Merge "codec2 hal: type conversion refactoring, step 2" into main am: d758be4c3f am: 5419864e7c am: deeb938092 am: 45d19b7c75 am: 54ed5919f6

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

Change-Id: Id1fae4d944fcedecb6720c4e7682e8b43028bcff
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/camera/Camera.cpp b/camera/Camera.cpp
index 2244682..35b8e21 100644
--- a/camera/Camera.cpp
+++ b/camera/Camera.cpp
@@ -19,7 +19,6 @@
 #define LOG_TAG "Camera"
 #include <utils/Log.h>
 #include <utils/threads.h>
-#include <utils/String16.h>
 #include <binder/IPCThreadState.h>
 #include <binder/IServiceManager.h>
 #include <binder/IMemory.h>
@@ -70,7 +69,7 @@
     // deadlock if we call any method of ICamera here.
 }
 
-sp<Camera> Camera::connect(int cameraId, const String16& clientPackageName,
+sp<Camera> Camera::connect(int cameraId, const std::string& clientPackageName,
         int clientUid, int clientPid, int targetSdkVersion, bool overrideToPortrait,
         bool forceSlowJpegMode)
 {
diff --git a/camera/CameraBase.cpp b/camera/CameraBase.cpp
index 9ae4607..2a102d0 100644
--- a/camera/CameraBase.cpp
+++ b/camera/CameraBase.cpp
@@ -31,6 +31,7 @@
 
 #include <camera/CameraBase.h>
 #include <camera/CameraUtils.h>
+#include <camera/StringUtils.h>
 
 // needed to instantiate
 #include <camera/Camera.h>
@@ -58,7 +59,7 @@
 }
 
 status_t CameraStatus::writeToParcel(android::Parcel* parcel) const {
-    auto res = parcel->writeString16(String16(cameraId));
+    auto res = parcel->writeString16(toString16(cameraId));
     if (res != OK) return res;
 
     res = parcel->writeInt32(status);
@@ -66,12 +67,12 @@
 
     std::vector<String16> unavailablePhysicalIds16;
     for (auto& id8 : unavailablePhysicalIds) {
-        unavailablePhysicalIds16.push_back(String16(id8));
+        unavailablePhysicalIds16.push_back(toString16(id8));
     }
     res = parcel->writeString16Vector(unavailablePhysicalIds16);
     if (res != OK) return res;
 
-    res = parcel->writeString16(String16(clientPackage));
+    res = parcel->writeString16(toString16(clientPackage));
     return res;
 }
 
@@ -79,7 +80,7 @@
     String16 tempCameraId;
     auto res = parcel->readString16(&tempCameraId);
     if (res != OK) return res;
-    cameraId = String8(tempCameraId);
+    cameraId = toString8(tempCameraId);
 
     res = parcel->readInt32(&status);
     if (res != OK) return res;
@@ -88,13 +89,13 @@
     res = parcel->readString16Vector(&unavailablePhysicalIds16);
     if (res != OK) return res;
     for (auto& id16 : unavailablePhysicalIds16) {
-        unavailablePhysicalIds.push_back(String8(id16));
+        unavailablePhysicalIds.push_back(toStdString(id16));
     }
 
     String16 tempClientPackage;
     res = parcel->readString16(&tempClientPackage);
     if (res != OK) return res;
-    clientPackage = String8(tempClientPackage);
+    clientPackage = toStdString(tempClientPackage);
 
     return res;
 }
@@ -103,7 +104,6 @@
 
 namespace {
     sp<::android::hardware::ICameraService> gCameraService;
-    const int                 kCameraServicePollDelay = 500000; // 0.5s
     const char*               kCameraServiceName      = "media.camera";
 
     Mutex                     gLock;
@@ -141,14 +141,10 @@
 
         sp<IServiceManager> sm = defaultServiceManager();
         sp<IBinder> binder;
-        do {
-            binder = sm->getService(String16(kCameraServiceName));
-            if (binder != 0) {
-                break;
-            }
-            ALOGW("CameraService not published, waiting...");
-            usleep(kCameraServicePollDelay);
-        } while(true);
+        binder = sm->waitForService(toString16(kCameraServiceName));
+        if (binder == nullptr) {
+            return nullptr;
+        }
         if (gDeathNotifier == NULL) {
             gDeathNotifier = new DeathNotifier();
         }
@@ -161,7 +157,7 @@
 
 template <typename TCam, typename TCamTraits>
 sp<TCam> CameraBase<TCam, TCamTraits>::connect(int cameraId,
-                                               const String16& clientPackageName,
+                                               const std::string& clientPackageName,
                                                int clientUid, int clientPid, int targetSdkVersion,
                                                bool overrideToPortrait, bool forceSlowJpegMode)
 {
diff --git a/camera/CameraSessionStats.cpp b/camera/CameraSessionStats.cpp
index 9e9793d..36bf24c 100644
--- a/camera/CameraSessionStats.cpp
+++ b/camera/CameraSessionStats.cpp
@@ -20,6 +20,7 @@
 #include <utils/String16.h>
 
 #include <camera/CameraSessionStats.h>
+#include <camera/StringUtils.h>
 
 #include <binder/Parcel.h>
 
@@ -282,8 +283,8 @@
         mSessionIndex(0),
         mCameraExtensionSessionStats() {}
 
-CameraSessionStats::CameraSessionStats(const String16& cameraId,
-        int facing, int newCameraState, const String16& clientName,
+CameraSessionStats::CameraSessionStats(const std::string& cameraId,
+        int facing, int newCameraState, const std::string& clientName,
         int apiLevel, bool isNdk, int32_t latencyMs, int64_t logId) :
                 mCameraId(cameraId),
                 mFacing(facing),
@@ -425,10 +426,10 @@
         return err;
     }
 
-    mCameraId = id;
+    mCameraId = toStdString(id);
     mFacing = facing;
     mNewCameraState = newCameraState;
-    mClientName = clientName;
+    mClientName = toStdString(clientName);
     mApiLevel = apiLevel;
     mIsNdk = isNdk;
     mLatencyMs = latencyMs;
@@ -440,7 +441,7 @@
     mResultErrorCount = resultErrorCount;
     mDeviceError = deviceError;
     mStreamStats = std::move(streamStats);
-    mUserTag = userTag;
+    mUserTag = toStdString(userTag);
     mVideoStabilizationMode = videoStabilizationMode;
     mSessionIndex = sessionIdx;
     mCameraExtensionSessionStats = extStats;
@@ -456,7 +457,7 @@
 
     status_t err = OK;
 
-    if ((err = parcel->writeString16(mCameraId)) != OK) {
+    if ((err = parcel->writeString16(toString16(mCameraId))) != OK) {
         ALOGE("%s: Failed to write camera id!", __FUNCTION__);
         return err;
     }
@@ -471,7 +472,7 @@
         return err;
     }
 
-    if ((err = parcel->writeString16(mClientName)) != OK) {
+    if ((err = parcel->writeString16(toString16(mClientName))) != OK) {
         ALOGE("%s: Failed to write client name!", __FUNCTION__);
         return err;
     }
@@ -531,7 +532,7 @@
         return err;
     }
 
-    if ((err = parcel->writeString16(mUserTag)) != OK) {
+    if ((err = parcel->writeString16(toString16(mUserTag))) != OK) {
         ALOGE("%s: Failed to write user tag!", __FUNCTION__);
         return err;
     }
diff --git a/camera/CaptureResult.cpp b/camera/CaptureResult.cpp
index bb880d1..9ff2578 100644
--- a/camera/CaptureResult.cpp
+++ b/camera/CaptureResult.cpp
@@ -18,6 +18,7 @@
 #include <utils/Log.h>
 
 #include <camera/CaptureResult.h>
+#include <camera/StringUtils.h>
 #include <binder/Parcel.h>
 
 namespace android {
@@ -47,7 +48,7 @@
             ALOGE("%s: Failed to read camera id: %d", __FUNCTION__, res);
             return res;
         }
-        errorPhysicalCameraId = cameraId;
+        errorPhysicalCameraId = toStdString(cameraId);
     }
     parcel->readInt64(&lastCompletedRegularFrameNumber);
     parcel->readInt64(&lastCompletedReprocessFrameNumber);
@@ -75,7 +76,7 @@
     if (errorPhysicalCameraId.size() > 0) {
         parcel->writeBool(true);
         status_t res = OK;
-        if ((res = parcel->writeString16(errorPhysicalCameraId)) != OK) {
+        if ((res = parcel->writeString16(toString16(errorPhysicalCameraId))) != OK) {
             ALOGE("%s: Failed to write physical camera ID to parcel: %d", __FUNCTION__, res);
             return res;
         }
@@ -96,13 +97,15 @@
 status_t PhysicalCaptureResultInfo::readFromParcel(const android::Parcel* parcel) {
     status_t res;
 
-    mPhysicalCameraId.setTo(u"");
+    mPhysicalCameraId = "";
     mPhysicalCameraMetadata.clear();
 
-    if ((res = parcel->readString16(&mPhysicalCameraId)) != OK) {
+    String16 physicalCameraId;
+    if ((res = parcel->readString16(&physicalCameraId)) != OK) {
         ALOGE("%s: Failed to read camera id: %d", __FUNCTION__, res);
         return res;
     }
+    mPhysicalCameraId = toStdString(physicalCameraId);
 
     if ((res = mPhysicalCameraMetadata.readFromParcel(parcel)) != OK) {
         ALOGE("%s: Failed to read metadata from parcel: %d", __FUNCTION__, res);
@@ -113,7 +116,7 @@
 
 status_t PhysicalCaptureResultInfo::writeToParcel(android::Parcel* parcel) const {
     status_t res;
-    if ((res = parcel->writeString16(mPhysicalCameraId)) != OK) {
+    if ((res = parcel->writeString16(toString16(mPhysicalCameraId))) != OK) {
         ALOGE("%s: Failed to write physical camera ID to parcel: %d",
                 __FUNCTION__, res);
         return res;
@@ -187,7 +190,8 @@
             return res;
         }
 
-        mPhysicalMetadatas.emplace(mPhysicalMetadatas.end(), cameraId, physicalMetadata);
+        mPhysicalMetadatas.emplace(mPhysicalMetadatas.end(), toStdString(cameraId),
+                physicalMetadata);
     }
     ALOGV("%s: Read physical metadata from parcel", __FUNCTION__);
 
@@ -228,7 +232,7 @@
         return BAD_VALUE;
     }
     for (const auto& physicalMetadata : mPhysicalMetadatas) {
-        if ((res = parcel->writeString16(physicalMetadata.mPhysicalCameraId)) != OK) {
+        if ((res = parcel->writeString16(toString16(physicalMetadata.mPhysicalCameraId))) != OK) {
             ALOGE("%s: Failed to write physical camera ID to parcel: %d",
                     __FUNCTION__, res);
             return res;
diff --git a/camera/aidl/android/hardware/ICameraService.aidl b/camera/aidl/android/hardware/ICameraService.aidl
index f8e1631..ed37b2d 100644
--- a/camera/aidl/android/hardware/ICameraService.aidl
+++ b/camera/aidl/android/hardware/ICameraService.aidl
@@ -82,7 +82,7 @@
      */
     ICamera connect(ICameraClient client,
             int cameraId,
-            String opPackageName,
+            @utf8InCpp String opPackageName,
             int clientUid, int clientPid,
             int targetSdkVersion,
             boolean overrideToPortrait,
@@ -93,9 +93,9 @@
      * Only supported for device HAL versions >= 3.2
      */
     ICameraDeviceUser connectDevice(ICameraDeviceCallbacks callbacks,
-            String cameraId,
-            String opPackageName,
-            @nullable String featureId,
+            @utf8InCpp String cameraId,
+            @utf8InCpp String opPackageName,
+            @nullable @utf8InCpp String featureId,
             int clientUid, int oomScoreOffset,
             int targetSdkVersion,
             boolean overrideToPortrait);
@@ -139,7 +139,7 @@
      * Read the static camera metadata for a camera device.
      * Only supported for device HAL versions >= 3.2
      */
-    CameraMetadataNative getCameraCharacteristics(String cameraId, int targetSdkVersion,
+    CameraMetadataNative getCameraCharacteristics(@utf8InCpp String cameraId, int targetSdkVersion,
             boolean overrideToPortrait);
 
     /**
@@ -160,7 +160,7 @@
     /**
      * Read the legacy camera1 parameters into a String
      */
-    String getLegacyParameters(int cameraId);
+    @utf8InCpp String getLegacyParameters(int cameraId);
 
     /**
      * apiVersion constants for supportsCameraApi
@@ -169,21 +169,21 @@
     const int API_VERSION_2 = 2;
 
     // Determines if a particular API version is supported directly for a cameraId.
-    boolean supportsCameraApi(String cameraId, int apiVersion);
+    boolean supportsCameraApi(@utf8InCpp String cameraId, int apiVersion);
     // Determines if a cameraId is a hidden physical camera of a logical multi-camera.
-    boolean isHiddenPhysicalCamera(String cameraId);
+    boolean isHiddenPhysicalCamera(@utf8InCpp String cameraId);
     // Inject the external camera to replace the internal camera session.
-    ICameraInjectionSession injectCamera(String packageName, String internalCamId,
-            String externalCamId, in ICameraInjectionCallback CameraInjectionCallback);
+    ICameraInjectionSession injectCamera(@utf8InCpp String packageName, @utf8InCpp String internalCamId,
+            @utf8InCpp String externalCamId, in ICameraInjectionCallback CameraInjectionCallback);
 
-    void setTorchMode(String cameraId, boolean enabled, IBinder clientBinder);
+    void setTorchMode(@utf8InCpp String cameraId, boolean enabled, IBinder clientBinder);
 
     // Change the brightness level of the flash unit associated with cameraId to strengthLevel.
     // If the torch is in OFF state and strengthLevel > 0 then the torch will also be turned ON.
-    void turnOnTorchWithStrengthLevel(String cameraId, int strengthLevel, IBinder clientBinder);
+    void turnOnTorchWithStrengthLevel(@utf8InCpp String cameraId, int strengthLevel, IBinder clientBinder);
 
     // Get the brightness level of the flash unit associated with cameraId.
-    int getTorchStrengthLevel(String cameraId);
+    int getTorchStrengthLevel(@utf8InCpp String cameraId);
 
     /**
      * Notify the camera service of a system event.  Should only be called from system_server.
@@ -233,7 +233,7 @@
      *
      * @return the key that must be used to report updates to previously reported stats.
      */
-    String reportExtensionSessionStats(in CameraExtensionSessionStats stats);
+    @utf8InCpp String reportExtensionSessionStats(in CameraExtensionSessionStats stats);
 
     // Bitfield constants for notifyDeviceStateChange
     // All bits >= 32 are for custom vendor states
diff --git a/camera/aidl/android/hardware/ICameraServiceListener.aidl b/camera/aidl/android/hardware/ICameraServiceListener.aidl
index 5f17f5b..23a87d3 100644
--- a/camera/aidl/android/hardware/ICameraServiceListener.aidl
+++ b/camera/aidl/android/hardware/ICameraServiceListener.aidl
@@ -51,13 +51,14 @@
     // Use to initialize variables only
     const int STATUS_UNKNOWN          = -1;
 
-    oneway void onStatusChanged(int status, String cameraId);
+    oneway void onStatusChanged(int status, @utf8InCpp 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);
+    oneway void onPhysicalCameraStatusChanged(int status, @utf8InCpp String cameraId,
+            @utf8InCpp String physicalCameraId);
 
     /**
      * The torch mode status of a camera.
@@ -81,9 +82,9 @@
     // Use to initialize variables only
     const int TORCH_STATUS_UNKNOWN = -1;
 
-    oneway void onTorchStatusChanged(int status, String cameraId);
+    oneway void onTorchStatusChanged(int status, @utf8InCpp String cameraId);
 
-    oneway void onTorchStrengthLevelChanged(String cameraId, int newTorchStrength);
+    oneway void onTorchStrengthLevelChanged(@utf8InCpp String cameraId, int newTorchStrength);
 
     /**
      * Notify registered clients about camera access priority changes.
@@ -97,6 +98,6 @@
      * Only clients with android.permission.CAMERA_OPEN_CLOSE_LISTENER permission
      * will receive such callbacks.
      */
-    oneway void onCameraOpened(String cameraId, String clientPackageId);
-    oneway void onCameraClosed(String cameraId);
+    oneway void onCameraOpened(@utf8InCpp String cameraId, @utf8InCpp String clientPackageId);
+    oneway void onCameraClosed(@utf8InCpp String cameraId);
 }
diff --git a/camera/aidl/android/hardware/ICameraServiceProxy.aidl b/camera/aidl/android/hardware/ICameraServiceProxy.aidl
index 4faa6b4..dcd69b0 100644
--- a/camera/aidl/android/hardware/ICameraServiceProxy.aidl
+++ b/camera/aidl/android/hardware/ICameraServiceProxy.aidl
@@ -44,14 +44,14 @@
      * {@link android.hardware.camera2.CameraMetadata#SCALER_ROTATE_AND_CROP_180},
      * {@link android.hardware.camera2.CameraMetadata#SCALER_ROTATE_AND_CROP_270}).
      */
-    int getRotateAndCropOverride(String packageName, int lensFacing, int userId);
+    int getRotateAndCropOverride(@utf8InCpp String packageName, int lensFacing, int userId);
 
     /**
      * Returns the necessary autoframing override for the top activity which
      * will be one of ({@link android.hardware.camera2.CameraMetadata#AUTOFRAMING_FALSE},
      * {@link android.hardware.camera2.CameraMetadata#AUTOFRAMING_TRUE}).
      */
-    int getAutoframingOverride(String packageName);
+    int getAutoframingOverride(@utf8InCpp String packageName);
 
     /**
      * Checks if the camera has been disabled via device policy.
diff --git a/camera/camera2/CaptureRequest.cpp b/camera/camera2/CaptureRequest.cpp
index 7a8a4ba..071f34e 100644
--- a/camera/camera2/CaptureRequest.cpp
+++ b/camera/camera2/CaptureRequest.cpp
@@ -21,6 +21,7 @@
 #include <utils/String16.h>
 
 #include <camera/camera2/CaptureRequest.h>
+#include <camera/StringUtils.h>
 
 #include <binder/Parcel.h>
 #include <gui/Surface.h>
@@ -74,7 +75,7 @@
             return err;
         }
         ALOGV("%s: Read metadata from parcel", __FUNCTION__);
-        mPhysicalCameraSettings.push_back({std::string(String8(id).string()), settings});
+        mPhysicalCameraSettings.push_back({toStdString(id), settings});
     }
 
     int isReprocess = 0;
@@ -157,7 +158,7 @@
             ALOGE("%s: Failed to read user tag!", __FUNCTION__);
             return BAD_VALUE;
         }
-        mUserTag = String8(userTag).c_str();
+        mUserTag = toStdString(userTag);
     }
 
     return OK;
@@ -179,7 +180,7 @@
     }
 
     for (const auto &it : mPhysicalCameraSettings) {
-        if ((err = parcel->writeString16(String16(it.id.c_str()))) != OK) {
+        if ((err = parcel->writeString16(toString16(it.id))) != OK) {
             ALOGE("%s: Failed to camera id!", __FUNCTION__);
             return err;
         }
@@ -232,7 +233,7 @@
         parcel->writeInt32(0);
     } else {
         parcel->writeInt32(1);
-        parcel->writeString16(String16(mUserTag.c_str()));
+        parcel->writeString16(toString16(mUserTag));
     }
 
     return OK;
diff --git a/camera/camera2/ConcurrentCamera.cpp b/camera/camera2/ConcurrentCamera.cpp
index 01a695c..67aa876 100644
--- a/camera/camera2/ConcurrentCamera.cpp
+++ b/camera/camera2/ConcurrentCamera.cpp
@@ -20,6 +20,7 @@
 #include <utils/String16.h>
 
 #include <camera/camera2/ConcurrentCamera.h>
+#include <camera/StringUtils.h>
 
 #include <binder/Parcel.h>
 
@@ -53,7 +54,7 @@
             ALOGE("%s: Failed to read camera id!", __FUNCTION__);
             return err;
         }
-        mConcurrentCameraIds.push_back(std::string(String8(id).string()));
+        mConcurrentCameraIds.push_back(toStdString(id));
     }
     return OK;
 }
@@ -73,7 +74,7 @@
     }
 
     for (const auto &it : mConcurrentCameraIds) {
-        if ((err = parcel->writeString16(String16(it.c_str()))) != OK) {
+        if ((err = parcel->writeString16(toString16(it))) != OK) {
             ALOGE("%s: Failed to write the camera id string to parcel: %d", __FUNCTION__, err);
             return err;
         }
@@ -99,7 +100,7 @@
         ALOGE("%s: Failed to read sessionConfiguration!", __FUNCTION__);
         return err;
     }
-    mCameraId = std::string(String8(id).string());
+    mCameraId = toStdString(id);
     return OK;
 }
 
@@ -111,7 +112,7 @@
     }
 
     status_t err = OK;
-    if ((err = parcel->writeString16(String16(mCameraId.c_str()))) != OK) {
+    if ((err = parcel->writeString16(toString16(mCameraId))) != OK) {
         ALOGE("%s: Failed to write camera id!", __FUNCTION__);
         return err;
     }
diff --git a/camera/camera2/OutputConfiguration.cpp b/camera/camera2/OutputConfiguration.cpp
index da4484a..33220ce 100644
--- a/camera/camera2/OutputConfiguration.cpp
+++ b/camera/camera2/OutputConfiguration.cpp
@@ -21,6 +21,7 @@
 #include <utils/Log.h>
 
 #include <camera/camera2/OutputConfiguration.h>
+#include <camera/StringUtils.h>
 #include <binder/Parcel.h>
 #include <gui/view/Surface.h>
 #include <system/camera_metadata.h>
@@ -65,7 +66,7 @@
     return mIsShared;
 }
 
-String16 OutputConfiguration::getPhysicalCameraId() const {
+std::string OutputConfiguration::getPhysicalCameraId() const {
     return mPhysicalCameraId;
 }
 
@@ -183,7 +184,9 @@
         return err;
     }
 
-    parcel->readString16(&mPhysicalCameraId);
+    String16 physicalCameraId;
+    parcel->readString16(&physicalCameraId);
+    mPhysicalCameraId = toStdString(physicalCameraId);
 
     int isMultiResolution = 0;
     if ((err = parcel->readInt32(&isMultiResolution)) != OK) {
@@ -246,7 +249,7 @@
     for (auto& surface : surfaceShims) {
         ALOGV("%s: OutputConfiguration: %p, name %s", __FUNCTION__,
                 surface.graphicBufferProducer.get(),
-                String8(surface.name).string());
+                toString8(surface.name).string());
         mGbps.push_back(surface.graphicBufferProducer);
     }
 
@@ -258,14 +261,14 @@
           " physicalCameraId = %s, isMultiResolution = %d, streamUseCase = %" PRId64
           ", timestampBase = %d, mirrorMode = %d, useReadoutTimestamp = %d",
           __FUNCTION__, mRotation, mSurfaceSetID, mSurfaceType,
-          String8(mPhysicalCameraId).string(), mIsMultiResolution, mStreamUseCase, timestampBase,
+          mPhysicalCameraId.c_str(), mIsMultiResolution, mStreamUseCase, timestampBase,
           mMirrorMode, mUseReadoutTimestamp);
 
     return err;
 }
 
 OutputConfiguration::OutputConfiguration(sp<IGraphicBufferProducer>& gbp, int rotation,
-        const String16& physicalId,
+        const std::string& physicalId,
         int surfaceSetID, bool isShared) {
     mGbps.push_back(gbp);
     mRotation = rotation;
@@ -284,7 +287,7 @@
 
 OutputConfiguration::OutputConfiguration(
         const std::vector<sp<IGraphicBufferProducer>>& gbps,
-    int rotation, const String16& physicalCameraId, int surfaceSetID,  int surfaceType,
+    int rotation, const std::string& physicalCameraId, int surfaceSetID,  int surfaceType,
     int width, int height, bool isShared)
   : mGbps(gbps), mRotation(rotation), mSurfaceSetID(surfaceSetID), mSurfaceType(surfaceType),
     mWidth(width), mHeight(height), mIsDeferred(false), mIsShared(isShared),
@@ -331,7 +334,8 @@
     err = parcel->writeParcelableVector(surfaceShims);
     if (err != OK) return err;
 
-    err = parcel->writeString16(mPhysicalCameraId);
+    String16 physicalCameraId = toString16(mPhysicalCameraId);
+    err = parcel->writeString16(physicalCameraId);
     if (err != OK) return err;
 
     err = parcel->writeInt32(mIsMultiResolution ? 1 : 0);
diff --git a/camera/cameraserver/Android.bp b/camera/cameraserver/Android.bp
index 8472562..13b705c 100644
--- a/camera/cameraserver/Android.bp
+++ b/camera/cameraserver/Android.bp
@@ -26,12 +26,15 @@
 
     srcs: ["main_cameraserver.cpp"],
 
+    defaults: [
+        "libcameraservice_deps",
+    ],
+
     header_libs: [
         "libmedia_headers",
     ],
 
     shared_libs: [
-        "libcameraservice",
         "liblog",
         "libutils",
         "libui",
@@ -40,15 +43,13 @@
         "libbinder_ndk",
         "libhidlbase",
         "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.provider@2.7",
-        "android.hardware.camera.provider-V2-ndk",
         "android.hardware.camera.device@1.0",
         "android.hardware.camera.device@3.2",
         "android.hardware.camera.device@3.4",
     ],
+    static_libs: [
+        "libcameraservice",
+    ],
     compile_multilib: "first",
     cflags: [
         "-Wall",
diff --git a/camera/include/camera/Camera.h b/camera/include/camera/Camera.h
index 21b57af..6655f82 100644
--- a/camera/include/camera/Camera.h
+++ b/camera/include/camera/Camera.h
@@ -56,9 +56,9 @@
     typedef CameraListener                     TCamListener;
     typedef ::android::hardware::ICamera       TCamUser;
     typedef ::android::hardware::ICameraClient TCamCallbacks;
-    typedef ::android::binder::Status(::android::hardware::ICameraService::*TCamConnectService)
+    typedef ::android::binder::Status (::android::hardware::ICameraService::*TCamConnectService)
         (const sp<::android::hardware::ICameraClient>&,
-        int, const String16&, int, int, int, bool, bool,
+        int, const std::string&, int, int, int, bool, bool,
         /*out*/
         sp<::android::hardware::ICamera>*);
     static TCamConnectService     fnConnectService;
@@ -80,7 +80,7 @@
             // construct a camera client from an existing remote
     static  sp<Camera>  create(const sp<::android::hardware::ICamera>& camera);
     static  sp<Camera>  connect(int cameraId,
-                                const String16& clientPackageName,
+                                const std::string& clientPackageName,
                                 int clientUid, int clientPid, int targetSdkVersion,
                                 bool overrideToPortrait, bool forceSlowJpegMode);
 
diff --git a/camera/include/camera/CameraBase.h b/camera/include/camera/CameraBase.h
index b20dc1b..6af7f2a 100644
--- a/camera/include/camera/CameraBase.h
+++ b/camera/include/camera/CameraBase.h
@@ -73,7 +73,7 @@
     /**
      * The name of the camera device
      */
-    String8 cameraId;
+    std::string cameraId;
 
     /**
      * Its current status, one of the ICameraService::STATUS_* fields
@@ -83,18 +83,18 @@
     /**
      * Unavailable physical camera names for a multi-camera device
      */
-    std::vector<String8> unavailablePhysicalIds;
+    std::vector<std::string> unavailablePhysicalIds;
 
     /**
      * Client package name if camera is open, otherwise not applicable
      */
-    String8 clientPackage;
+    std::string clientPackage;
 
     virtual status_t writeToParcel(android::Parcel* parcel) const;
     virtual status_t readFromParcel(const android::Parcel* parcel);
 
-    CameraStatus(String8 id, int32_t s, const std::vector<String8>& unavailSubIds,
-            const String8& clientPkg) : cameraId(id), status(s),
+    CameraStatus(std::string id, int32_t s, const std::vector<std::string>& unavailSubIds,
+            const std::string& clientPkg) : cameraId(id), status(s),
             unavailablePhysicalIds(unavailSubIds), clientPackage(clientPkg) {}
     CameraStatus() : status(ICameraServiceListener::STATUS_PRESENT) {}
 };
@@ -118,7 +118,7 @@
     typedef typename TCamTraits::TCamConnectService TCamConnectService;
 
     static sp<TCam>      connect(int cameraId,
-                                 const String16& clientPackageName,
+                                 const std::string& clientPackageName,
                                  int clientUid, int clientPid, int targetSdkVersion,
                                  bool overrideToPortrait, bool forceSlowJpegMode);
     virtual void         disconnect();
diff --git a/camera/include/camera/CameraSessionStats.h b/camera/include/camera/CameraSessionStats.h
index 071bc736..70ca0b3 100644
--- a/camera/include/camera/CameraSessionStats.h
+++ b/camera/include/camera/CameraSessionStats.h
@@ -17,6 +17,8 @@
 #ifndef ANDROID_HARDWARE_CAMERA_SERVICE_SESSION_STATS_H
 #define ANDROID_HARDWARE_CAMERA_SERVICE_SESSION_STATS_H
 
+#include <string>
+
 #include <binder/Parcelable.h>
 
 #include <camera/CameraMetadata.h>
@@ -121,10 +123,10 @@
     static const int CAMERA_API_LEVEL_1;
     static const int CAMERA_API_LEVEL_2;
 
-    String16 mCameraId;
+    std::string mCameraId;
     int mFacing;
     int mNewCameraState;
-    String16 mClientName;
+    std::string mClientName;
     int mApiLevel;
     bool mIsNdk;
     // latency in ms for camera open, close, or session creation.
@@ -157,7 +159,7 @@
     // Whether the device runs into an error state
     bool mDeviceError;
     std::vector<CameraStreamStats> mStreamStats;
-    String16 mUserTag;
+    std::string mUserTag;
     int mVideoStabilizationMode;
     int mSessionIndex;
 
@@ -165,8 +167,8 @@
 
     // Constructors
     CameraSessionStats();
-    CameraSessionStats(const String16& cameraId, int facing, int newCameraState,
-                       const String16& clientName, int apiLevel, bool isNdk, int32_t latencyMs,
+    CameraSessionStats(const std::string& cameraId, int facing, int newCameraState,
+                       const std::string& clientName, int apiLevel, bool isNdk, int32_t latencyMs,
                        int64_t logId);
 
     virtual status_t readFromParcel(const android::Parcel* parcel) override;
diff --git a/camera/include/camera/CaptureResult.h b/camera/include/camera/CaptureResult.h
index de534ab..e08c9ca 100644
--- a/camera/include/camera/CaptureResult.h
+++ b/camera/include/camera/CaptureResult.h
@@ -74,7 +74,7 @@
      * a reference to physical camera device.
      * Empty otherwise.
      */
-    String16  errorPhysicalCameraId;
+    std::string errorPhysicalCameraId;
 
     // The last completed frame numbers shouldn't be checked in onResultReceived() and notifyError()
     // because the output buffers could be arriving after onResultReceived() and
@@ -150,13 +150,13 @@
         : mPhysicalCameraId(),
           mPhysicalCameraMetadata() {
     }
-    PhysicalCaptureResultInfo(const String16& cameraId,
+    PhysicalCaptureResultInfo(const std::string& cameraId,
             const CameraMetadata& cameraMetadata)
             : mPhysicalCameraId(cameraId),
               mPhysicalCameraMetadata(cameraMetadata) {
     }
 
-    String16  mPhysicalCameraId;
+    std::string mPhysicalCameraId;
     CameraMetadata mPhysicalCameraMetadata;
 
     virtual status_t                readFromParcel(const android::Parcel* parcel) override;
diff --git a/camera/include/camera/StringUtils.h b/camera/include/camera/StringUtils.h
new file mode 100644
index 0000000..b9dfbfc
--- /dev/null
+++ b/camera/include/camera/StringUtils.h
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_SERVERS_CAMERA_STRINGUTILS_H
+#define ANDROID_SERVERS_CAMERA_STRINGUTILS_H
+
+#include <codecvt>
+#include <locale>
+#include <memory>
+#include <optional>
+#include <string>
+
+#include <fmt/printf.h>
+#include <utils/String8.h>
+#include <utils/String16.h>
+
+namespace android {
+    inline String8 toString8(const std::string &str) {
+        return String8(str.c_str());
+    }
+
+    inline String8 toString8(const String16 &str) {
+        return String8(str);
+    }
+
+    inline String8 toString8(const char *str) {
+        return String8(str);
+    }
+
+    inline String16 toString16(const std::string &str) {
+        return String16(str.c_str());
+    }
+
+    inline String16 toString16(const String8 &str) {
+        return String16(str);
+    }
+
+    inline String16 toString16(const char *str) {
+        return String16(str);
+    }
+
+    inline std::optional<String16> toString16(std::optional<std::string> str) {
+        if (str.has_value()) {
+            return std::optional<String16>(toString16(str.value()));
+        }
+
+        return std::nullopt;
+    }
+
+    inline std::string toStdString(const String8 &str) {
+        return std::string(str.string());
+    }
+
+    inline std::string toStdString(const String16 &str) {
+        std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> convert;
+        return convert.to_bytes(str.string());
+    }
+
+    /**
+     * Convert a non-null-terminated UTF16 string to a UTF8 string (i.e. in jni functions)
+     * len is the number of characters.
+     */
+    inline std::string toStdString(const char16_t *str, size_t len) {
+        std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> convert;
+        return convert.to_bytes(str, str + len);
+    }
+} // namespace android
+
+#endif // ANDROID_SERVERS_CAMERA_STRINGUTILS_H
diff --git a/camera/include/camera/camera2/OutputConfiguration.h b/camera/include/camera/camera2/OutputConfiguration.h
index 16fddb5..3f74b4a 100644
--- a/camera/include/camera/camera2/OutputConfiguration.h
+++ b/camera/include/camera/camera2/OutputConfiguration.h
@@ -17,6 +17,8 @@
 #ifndef ANDROID_HARDWARE_CAMERA2_OUTPUTCONFIGURATION_H
 #define ANDROID_HARDWARE_CAMERA2_OUTPUTCONFIGURATION_H
 
+#include <string>
+
 #include <gui/IGraphicBufferProducer.h>
 #include <binder/Parcelable.h>
 
@@ -63,7 +65,7 @@
     int32_t                    getColorSpace() const;
     bool                       isDeferred() const;
     bool                       isShared() const;
-    String16                   getPhysicalCameraId() const;
+    std::string                getPhysicalCameraId() const;
     bool                       isMultiResolution() const;
     int64_t                    getStreamUseCase() const;
     int                        getTimestampBase() const;
@@ -90,11 +92,11 @@
     OutputConfiguration(const android::Parcel& parcel);
 
     OutputConfiguration(sp<IGraphicBufferProducer>& gbp, int rotation,
-            const String16& physicalCameraId,
+            const std::string& physicalCameraId,
             int surfaceSetID = INVALID_SET_ID, bool isShared = false);
 
     OutputConfiguration(const std::vector<sp<IGraphicBufferProducer>>& gbps,
-                        int rotation, const String16& physicalCameraId,
+                        int rotation, const std::string& physicalCameraId,
                         int surfaceSetID = INVALID_SET_ID,
                         int surfaceType = OutputConfiguration::SURFACE_TYPE_UNKNOWN, int width = 0,
                         int height = 0, bool isShared = false);
@@ -192,7 +194,7 @@
     int                        mHeight;
     bool                       mIsDeferred;
     bool                       mIsShared;
-    String16                   mPhysicalCameraId;
+    std::string                mPhysicalCameraId;
     bool                       mIsMultiResolution;
     std::vector<int32_t>       mSensorPixelModesUsed;
     int64_t                    mDynamicRangeProfile;
diff --git a/camera/ndk/Android.bp b/camera/ndk/Android.bp
index bfd02b3..866dc72 100644
--- a/camera/ndk/Android.bp
+++ b/camera/ndk/Android.bp
@@ -182,6 +182,7 @@
     shared_libs: [
         "libcamera2ndk_vendor",
         "libcamera_metadata",
+        "libhidlbase",
         "libmediandk",
         "libnativewindow",
         "libutils",
@@ -191,6 +192,7 @@
     ],
     static_libs: [
         "android.hardware.camera.common@1.0-helper",
+        "android.hidl.token@1.0",
     ],
     cflags: [
         "-D__ANDROID_VNDK__",
diff --git a/camera/ndk/impl/ACameraDevice.cpp b/camera/ndk/impl/ACameraDevice.cpp
index 1dae0f9..8bdb6d4 100644
--- a/camera/ndk/impl/ACameraDevice.cpp
+++ b/camera/ndk/impl/ACameraDevice.cpp
@@ -21,6 +21,7 @@
 #include <inttypes.h>
 #include <android/hardware/ICameraService.h>
 #include <gui/Surface.h>
+#include <camera/StringUtils.h>
 #include "ACameraDevice.h"
 #include "ACameraMetadata.h"
 #include "ACaptureRequest.h"
@@ -234,8 +235,7 @@
             return ret;
         }
 
-        String16 physicalId16(output.mPhysicalCameraId.c_str());
-        OutputConfiguration outConfig(iGBP, output.mRotation, physicalId16,
+        OutputConfiguration outConfig(iGBP, output.mRotation, output.mPhysicalCameraId,
                 OutputConfiguration::INVALID_SET_ID, true);
 
         for (auto& anw : output.mSharedWindows) {
@@ -299,8 +299,7 @@
         return ret;
     }
 
-    String16 physicalId16(output->mPhysicalCameraId.c_str());
-    OutputConfiguration outConfig(iGBP, output->mRotation, physicalId16,
+    OutputConfiguration outConfig(iGBP, output->mRotation, output->mPhysicalCameraId,
             OutputConfiguration::INVALID_SET_ID, true);
 
     for (auto& anw : output->mSharedWindows) {
@@ -683,9 +682,8 @@
         if (ret != ACAMERA_OK) {
             return ret;
         }
-        String16 physicalId16(outConfig.mPhysicalCameraId.c_str());
         outputSet.insert(std::make_pair(
-                anw, OutputConfiguration(iGBP, outConfig.mRotation, physicalId16,
+                anw, OutputConfiguration(iGBP, outConfig.mRotation, outConfig.mPhysicalCameraId,
                         OutputConfiguration::INVALID_SET_ID, outConfig.mIsShared)));
     }
     auto addSet = outputSet;
@@ -919,7 +917,7 @@
         msg->setObject(kSessionSpKey, session);
         if (cbh.mIsLogicalCameraCallback) {
             if (resultExtras.errorPhysicalCameraId.size() > 0) {
-                String8 cameraId(resultExtras.errorPhysicalCameraId);
+                String8 cameraId = toString8(resultExtras.errorPhysicalCameraId);
                 msg->setString(kFailingPhysicalCameraId, cameraId.string(), cameraId.size());
             }
             msg->setPointer(kCallbackFpKey, (void*) cbh.mOnLogicalCameraCaptureFailed);
@@ -1215,7 +1213,7 @@
                     std::vector<std::string> physicalCameraIds;
                     std::vector<sp<ACameraMetadata>> physicalMetadataCopy;
                     for (size_t i = 0; i < physicalResultInfo.size(); i++) {
-                        String8 physicalId8(physicalResultInfo[i].mPhysicalCameraId);
+                        String8 physicalId8 = toString8(physicalResultInfo[i].mPhysicalCameraId);
                         physicalCameraIds.push_back(physicalId8.c_str());
 
                         CameraMetadata clone = physicalResultInfo[i].mPhysicalCameraMetadata;
diff --git a/camera/ndk/impl/ACameraManager.cpp b/camera/ndk/impl/ACameraManager.cpp
index 837b5be..299ffc0 100644
--- a/camera/ndk/impl/ACameraManager.cpp
+++ b/camera/ndk/impl/ACameraManager.cpp
@@ -25,6 +25,7 @@
 #include <cutils/properties.h>
 #include <stdlib.h>
 #include <camera/CameraUtils.h>
+#include <camera/StringUtils.h>
 #include <camera/VendorTagDescriptor.h>
 
 using namespace android::acam;
@@ -84,7 +85,7 @@
         sp<IServiceManager> sm = defaultServiceManager();
         sp<IBinder> binder;
         do {
-            binder = sm->getService(String16(kCameraServiceName));
+            binder = sm->getService(toString16(kCameraServiceName));
             if (binder != nullptr) {
                 break;
             }
@@ -188,12 +189,12 @@
     sp<CameraManagerGlobal> cm = mCameraManager.promote();
     if (cm != nullptr) {
         AutoMutex lock(cm->mLock);
-        std::vector<String8> cameraIdList;
+        std::vector<std::string> cameraIdList;
         for (auto& pair : cm->mDeviceStatusMap) {
             cameraIdList.push_back(pair.first);
         }
 
-        for (String8 cameraId : cameraIdList) {
+        for (const std::string& cameraId : cameraIdList) {
             cm->onStatusChangedLocked(
                     CameraServiceListener::STATUS_NOT_PRESENT, cameraId);
         }
@@ -259,7 +260,7 @@
     // Send initial callbacks if callback is newly registered
     if (pair.second) {
         for (auto& pair : mDeviceStatusMap) {
-            const String8& cameraId = pair.first;
+            const std::string& cameraId = pair.first;
             int32_t status = pair.second.getStatus();
             // Don't send initial callbacks for camera ids which don't support
             // camera2
@@ -273,12 +274,12 @@
                     cb.mAvailable : cb.mUnavailable;
             msg->setPointer(kCallbackFpKey, (void *) cbFunc);
             msg->setPointer(kContextKey, cb.mContext);
-            msg->setString(kCameraIdKey, AString(cameraId));
+            msg->setString(kCameraIdKey, AString(cameraId.c_str()));
             mPendingCallbackCnt++;
             msg->post();
 
             // Physical camera unavailable callback
-            std::set<String8> unavailablePhysicalCameras =
+            std::set<std::string> unavailablePhysicalCameras =
                     pair.second.getUnavailablePhysicalIds();
             for (const auto& physicalCameraId : unavailablePhysicalCameras) {
                 sp<AMessage> msg = new AMessage(kWhatSendSinglePhysicalCameraCallback, mHandler);
@@ -286,8 +287,8 @@
                         cb.mPhysicalCamUnavailable;
                 msg->setPointer(kCallbackFpKey, (void *) cbFunc);
                 msg->setPointer(kContextKey, cb.mContext);
-                msg->setString(kCameraIdKey, AString(cameraId));
-                msg->setString(kPhysicalCameraIdKey, AString(physicalCameraId));
+                msg->setString(kCameraIdKey, AString(cameraId.c_str()));
+                msg->setString(kPhysicalCameraIdKey, AString(physicalCameraId.c_str()));
                 mPendingCallbackCnt++;
                 msg->post();
             }
@@ -295,11 +296,11 @@
     }
 }
 
-bool CameraManagerGlobal::supportsCamera2ApiLocked(const String8 &cameraId) {
+bool CameraManagerGlobal::supportsCamera2ApiLocked(const std::string &cameraId) {
     bool camera2Support = false;
     auto cs = getCameraServiceLocked();
     binder::Status serviceRet =
-        cs->supportsCameraApi(String16(cameraId),
+        cs->supportsCameraApi(cameraId,
                 hardware::ICameraService::API_VERSION_2, &camera2Support);
     if (!serviceRet.isOk()) {
         ALOGE("%s: supportsCameraApi2Locked() call failed for cameraId  %s",
@@ -309,7 +310,7 @@
     return camera2Support;
 }
 
-void CameraManagerGlobal::getCameraIdList(std::vector<String8>* cameraIds) {
+void CameraManagerGlobal::getCameraIdList(std::vector<std::string>* cameraIds) {
     // Ensure that we have initialized/refreshed the list of available devices
     Mutex::Autolock _l(mLock);
     // Needed to make sure we're connected to cameraservice
@@ -459,10 +460,10 @@
 }
 
 binder::Status CameraManagerGlobal::CameraServiceListener::onStatusChanged(
-        int32_t status, const String16& cameraId) {
+        int32_t status, const std::string& cameraId) {
     sp<CameraManagerGlobal> cm = mCameraManager.promote();
     if (cm != nullptr) {
-        cm->onStatusChanged(status, String8(cameraId));
+        cm->onStatusChanged(status, cameraId);
     } else {
         ALOGE("Cannot deliver status change. Global camera manager died");
     }
@@ -470,10 +471,10 @@
 }
 
 binder::Status CameraManagerGlobal::CameraServiceListener::onPhysicalCameraStatusChanged(
-        int32_t status, const String16& cameraId, const String16& physicalCameraId) {
+        int32_t status, const std::string& cameraId, const std::string& physicalCameraId) {
     sp<CameraManagerGlobal> cm = mCameraManager.promote();
     if (cm != nullptr) {
-        cm->onStatusChanged(status, String8(cameraId), String8(physicalCameraId));
+        cm->onStatusChanged(status, cameraId, physicalCameraId);
     } else {
         ALOGE("Cannot deliver physical camera status change. Global camera manager died");
     }
@@ -495,13 +496,13 @@
 }
 
 void CameraManagerGlobal::onStatusChanged(
-        int32_t status, const String8& cameraId) {
+        int32_t status, const std::string& cameraId) {
     Mutex::Autolock _l(mLock);
     onStatusChangedLocked(status, cameraId);
 }
 
 void CameraManagerGlobal::onStatusChangedLocked(
-        int32_t status, const String8& cameraId) {
+        int32_t status, const std::string& cameraId) {
     if (!validStatus(status)) {
         ALOGE("%s: Invalid status %d", __FUNCTION__, status);
         return;
@@ -534,7 +535,7 @@
                     cb.mAvailable : cb.mUnavailable;
             msg->setPointer(kCallbackFpKey, (void *) cbFp);
             msg->setPointer(kContextKey, cb.mContext);
-            msg->setString(kCameraIdKey, AString(cameraId));
+            msg->setString(kCameraIdKey, AString(cameraId.c_str()));
             mPendingCallbackCnt++;
             msg->post();
         }
@@ -545,13 +546,13 @@
 }
 
 void CameraManagerGlobal::onStatusChanged(
-        int32_t status, const String8& cameraId, const String8& physicalCameraId) {
+        int32_t status, const std::string& cameraId, const std::string& physicalCameraId) {
     Mutex::Autolock _l(mLock);
     onStatusChangedLocked(status, cameraId, physicalCameraId);
 }
 
 void CameraManagerGlobal::onStatusChangedLocked(
-        int32_t status, const String8& cameraId, const String8& physicalCameraId) {
+        int32_t status, const std::string& cameraId, const std::string& physicalCameraId) {
     if (!validStatus(status)) {
         ALOGE("%s: Invalid status %d", __FUNCTION__, status);
         return;
@@ -567,7 +568,7 @@
     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);
+                __FUNCTION__, physicalCameraId.c_str(), status, logicalCamStatus);
         return;
     }
 
@@ -588,8 +589,8 @@
                     cb.mPhysicalCamAvailable : cb.mPhysicalCamUnavailable;
             msg->setPointer(kCallbackFpKey, (void *) cbFp);
             msg->setPointer(kContextKey, cb.mContext);
-            msg->setString(kCameraIdKey, AString(cameraId));
-            msg->setString(kPhysicalCameraIdKey, AString(physicalCameraId));
+            msg->setString(kCameraIdKey, AString(cameraId.c_str()));
+            msg->setString(kPhysicalCameraIdKey, AString(physicalCameraId.c_str()));
             mPendingCallbackCnt++;
             msg->post();
         }
@@ -607,20 +608,20 @@
 }
 
 bool CameraManagerGlobal::StatusAndHAL3Support::addUnavailablePhysicalId(
-        const String8& physicalCameraId) {
+        const std::string& physicalCameraId) {
     std::lock_guard<std::mutex> lock(mLock);
     auto result = unavailablePhysicalIds.insert(physicalCameraId);
     return result.second;
 }
 
 bool CameraManagerGlobal::StatusAndHAL3Support::removeUnavailablePhysicalId(
-        const String8& physicalCameraId) {
+        const std::string& physicalCameraId) {
     std::lock_guard<std::mutex> lock(mLock);
     auto count = unavailablePhysicalIds.erase(physicalCameraId);
     return count > 0;
 }
 
-std::set<String8> CameraManagerGlobal::StatusAndHAL3Support::getUnavailablePhysicalIds() {
+std::set<std::string> CameraManagerGlobal::StatusAndHAL3Support::getUnavailablePhysicalIds() {
     std::lock_guard<std::mutex> lock(mLock);
     return unavailablePhysicalIds;
 }
@@ -635,7 +636,7 @@
 ACameraManager::getCameraIdList(ACameraIdList** cameraIdList) {
     Mutex::Autolock _l(mLock);
 
-    std::vector<String8> idList;
+    std::vector<std::string> idList;
     CameraManagerGlobal::getInstance()->getCameraIdList(&idList);
 
     int numCameras = idList.size();
@@ -652,7 +653,7 @@
         return ACAMERA_ERROR_NOT_ENOUGH_MEMORY;
     }
     for (int i = 0; i < numCameras; i++) {
-        const char* src = idList[i].string();
+        const char* src = idList[i].c_str();
         size_t dstSize = strlen(src) + 1;
         char* dst = new char[dstSize];
         if (!dst) {
@@ -694,7 +695,7 @@
 
     CameraMetadata rawMetadata;
     int targetSdkVersion = android_get_application_target_sdk_version();
-    binder::Status serviceRet = cs->getCameraCharacteristics(String16(cameraIdStr),
+    binder::Status serviceRet = cs->getCameraCharacteristics(cameraIdStr,
             targetSdkVersion, /*overrideToPortrait*/false, &rawMetadata);
     if (!serviceRet.isOk()) {
         switch(serviceRet.serviceSpecificErrorCode()) {
@@ -745,7 +746,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, cameraId, "", {},
             hardware::ICameraService::USE_CALLING_UID, /*oomScoreOffset*/0,
             targetSdkVersion, /*overrideToPortrait*/false, /*out*/&deviceRemote);
 
diff --git a/camera/ndk/impl/ACameraManager.h b/camera/ndk/impl/ACameraManager.h
index 0dd79da..c135d0f 100644
--- a/camera/ndk/impl/ACameraManager.h
+++ b/camera/ndk/impl/ACameraManager.h
@@ -62,7 +62,7 @@
     /**
      * Return camera IDs that support camera2
      */
-    void getCameraIdList(std::vector<String8> *cameraIds);
+    void getCameraIdList(std::vector<std::string> *cameraIds);
 
   private:
     sp<hardware::ICameraService> mCameraService;
@@ -87,23 +87,23 @@
     class CameraServiceListener final : public hardware::BnCameraServiceListener {
       public:
         explicit CameraServiceListener(CameraManagerGlobal* cm) : mCameraManager(cm) {}
-        virtual binder::Status onStatusChanged(int32_t status, const String16& cameraId);
+        virtual binder::Status onStatusChanged(int32_t status, const std::string& cameraId);
         virtual binder::Status onPhysicalCameraStatusChanged(int32_t status,
-                const String16& cameraId, const String16& physicalCameraId);
+                const std::string& cameraId, const std::string& physicalCameraId);
 
         // Torch API not implemented yet
-        virtual binder::Status onTorchStatusChanged(int32_t, const String16&) {
+        virtual binder::Status onTorchStatusChanged(int32_t, const std::string&) {
             return binder::Status::ok();
         }
-        virtual binder::Status onTorchStrengthLevelChanged(const String16&, int32_t) {
+        virtual binder::Status onTorchStrengthLevelChanged(const std::string&, int32_t) {
             return binder::Status::ok();
         }
 
         virtual binder::Status onCameraAccessPrioritiesChanged();
-        virtual binder::Status onCameraOpened(const String16&, const String16&) {
+        virtual binder::Status onCameraOpened(const std::string&, const std::string&) {
             return binder::Status::ok();
         }
-        virtual binder::Status onCameraClosed(const String16&) {
+        virtual binder::Status onCameraClosed(const std::string&) {
             return binder::Status::ok();
         }
 
@@ -203,20 +203,20 @@
 
     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);
+    void onStatusChanged(int32_t status, const std::string& cameraId);
+    void onStatusChangedLocked(int32_t status, const std::string& cameraId);
+    void onStatusChanged(int32_t status, const std::string& cameraId, const std::string& physicalCameraId);
+    void onStatusChangedLocked(int32_t status, const std::string& cameraId,
+           const std::string& physicalCameraId);
     // Utils for status
     static bool validStatus(int32_t status);
     static bool isStatusAvailable(int32_t status);
-    bool supportsCamera2ApiLocked(const String8 &cameraId);
+    bool supportsCamera2ApiLocked(const std::string &cameraId);
 
     // The sort logic must match the logic in
     // libcameraservice/common/CameraProviderManager.cpp::getAPI1CompatibleCameraDeviceIds
     struct CameraIdComparator {
-        bool operator()(const String8& a, const String8& b) const {
+        bool operator()(const std::string& a, const std::string& b) const {
             uint32_t aUint = 0, bUint = 0;
             bool aIsUint = base::ParseUint(a.c_str(), &aUint);
             bool bIsUint = base::ParseUint(b.c_str(), &bUint);
@@ -238,22 +238,22 @@
       private:
         int32_t status = hardware::ICameraServiceListener::STATUS_NOT_PRESENT;
         mutable std::mutex mLock;
-        std::set<String8> unavailablePhysicalIds;
+        std::set<std::string> 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);
+        bool addUnavailablePhysicalId(const std::string& physicalCameraId);
+        bool removeUnavailablePhysicalId(const std::string& physicalCameraId);
         int32_t getStatus();
         void updateStatus(int32_t newStatus);
-        std::set<String8> getUnavailablePhysicalIds();
+        std::set<std::string> getUnavailablePhysicalIds();
     };
 
     // Map camera_id -> status
-    std::map<String8, StatusAndHAL3Support, CameraIdComparator> mDeviceStatusMap;
+    std::map<std::string, StatusAndHAL3Support, CameraIdComparator> mDeviceStatusMap;
 
     // For the singleton instance
     static Mutex sLock;
diff --git a/camera/ndk/ndk_vendor/tests/AImageReaderVendorTest.cpp b/camera/ndk/ndk_vendor/tests/AImageReaderVendorTest.cpp
index 7f6ea9d..74c6cad 100644
--- a/camera/ndk/ndk_vendor/tests/AImageReaderVendorTest.cpp
+++ b/camera/ndk/ndk_vendor/tests/AImageReaderVendorTest.cpp
@@ -31,10 +31,13 @@
 #include <stdio.h>
 
 #include <android/log.h>
+#include <android/hidl/manager/1.2/IServiceManager.h>
+#include <android/hidl/token/1.0/ITokenManager.h>
 #include <camera/NdkCameraError.h>
 #include <camera/NdkCameraManager.h>
 #include <camera/NdkCameraDevice.h>
 #include <camera/NdkCameraCaptureSession.h>
+#include <hidl/ServiceManagement.h>
 #include <media/NdkImage.h>
 #include <media/NdkImageReader.h>
 #include <cutils/native_handle.h>
@@ -50,6 +53,8 @@
 static constexpr int kTestImageFormat = AIMAGE_FORMAT_YUV_420_888;
 
 using android::hardware::camera::common::V1_0::helper::VendorTagDescriptorCache;
+using android::hidl::manager::V1_0::IServiceManager;
+using android::hidl::token::V1_0::ITokenManager;
 using ConfiguredWindows = std::set<const native_handle_t *>;
 
 class CameraHelper {
@@ -981,11 +986,19 @@
 
 
 TEST_F(AImageReaderVendorTest, CreateWindowNativeHandle) {
+    auto transport = android::hardware::defaultServiceManager()->getTransport(ITokenManager::descriptor, "default");
+    if (transport.isOk() && transport == IServiceManager::Transport::EMPTY) {
+        GTEST_SKIP() << "This device no longer supports AImageReader_getWindowNativeHandle";
+    }
     testBasicTakePictures(/*prepareSurfaces*/ false);
     testBasicTakePictures(/*prepareSurfaces*/ true);
 }
 
 TEST_F(AImageReaderVendorTest, LogicalCameraPhysicalStream) {
+    auto transport = android::hardware::defaultServiceManager()->getTransport(ITokenManager::descriptor, "default");
+    if (transport.isOk() && transport == IServiceManager::Transport::EMPTY) {
+        GTEST_SKIP() << "This device no longer supports AImageReader_getWindowNativeHandle";
+    }
     for (auto & v2 : {true, false}) {
         testLogicalCameraPhysicalStream(false/*usePhysicalSettings*/, v2);
         testLogicalCameraPhysicalStream(true/*usePhysicalSettings*/, v2);
diff --git a/camera/tests/CameraBinderTests.cpp b/camera/tests/CameraBinderTests.cpp
index 1af5637..bb963ab 100644
--- a/camera/tests/CameraBinderTests.cpp
+++ b/camera/tests/CameraBinderTests.cpp
@@ -43,6 +43,7 @@
 #include <camera/camera2/OutputConfiguration.h>
 #include <camera/camera2/SessionConfiguration.h>
 #include <camera/camera2/SubmitInfo.h>
+#include <camera/StringUtils.h>
 
 #include <gui/BufferItemConsumer.h>
 #include <gui/IGraphicBufferProducer.h>
@@ -68,15 +69,15 @@
 
 // Stub listener implementation
 class TestCameraServiceListener : public hardware::BnCameraServiceListener {
-    std::map<String16, int32_t> mCameraTorchStatuses;
-    std::map<String16, int32_t> mCameraStatuses;
+    std::map<std::string, int32_t> mCameraTorchStatuses;
+    std::map<std::string, int32_t> mCameraStatuses;
     mutable Mutex mLock;
     mutable Condition mCondition;
     mutable Condition mTorchCondition;
 public:
     virtual ~TestCameraServiceListener() {};
 
-    virtual binder::Status onStatusChanged(int32_t status, const String16& cameraId) {
+    virtual binder::Status onStatusChanged(int32_t status, const std::string& cameraId) override {
         Mutex::Autolock l(mLock);
         mCameraStatuses[cameraId] = status;
         mCondition.broadcast();
@@ -84,36 +85,37 @@
     };
 
     virtual binder::Status onPhysicalCameraStatusChanged(int32_t /*status*/,
-            const String16& /*cameraId*/, const String16& /*physicalCameraId*/) {
+            const std::string& /*cameraId*/, const std::string& /*physicalCameraId*/) override {
         // No op
         return binder::Status::ok();
     };
 
-    virtual binder::Status onTorchStatusChanged(int32_t status, const String16& cameraId) {
+    virtual binder::Status onTorchStatusChanged(int32_t status,
+            const std::string& cameraId) override {
         Mutex::Autolock l(mLock);
         mCameraTorchStatuses[cameraId] = status;
         mTorchCondition.broadcast();
         return binder::Status::ok();
     };
 
-    virtual binder::Status onTorchStrengthLevelChanged(const String16& /*cameraId*/,
-            int32_t /*torchStrength*/) {
+    virtual binder::Status onTorchStrengthLevelChanged(const std::string& /*cameraId*/,
+            int32_t /*torchStrength*/) override {
         // No op
         return binder::Status::ok();
     }
 
-    virtual binder::Status onCameraAccessPrioritiesChanged() {
+    virtual binder::Status onCameraAccessPrioritiesChanged() override {
         // No op
         return binder::Status::ok();
     }
 
-    virtual binder::Status onCameraOpened(const String16& /*cameraId*/,
-            const String16& /*clientPackageName*/) {
+    virtual binder::Status onCameraOpened(const std::string& /*cameraId*/,
+            const std::string& /*clientPackageName*/) {
         // No op
         return binder::Status::ok();
     }
 
-    virtual binder::Status onCameraClosed(const String16& /*cameraId*/) {
+    virtual binder::Status onCameraClosed(const std::string& /*cameraId*/) override {
         // No op
         return binder::Status::ok();
     }
@@ -136,7 +138,7 @@
     bool waitForTorchState(int32_t status, int32_t cameraId) const {
         Mutex::Autolock l(mLock);
 
-        const auto& iter = mCameraTorchStatuses.find(String16(String8::format("%d", cameraId)));
+        const auto& iter = mCameraTorchStatuses.find(std::to_string(cameraId));
         if (iter != mCameraTorchStatuses.end() && iter->second == status) {
             return true;
         }
@@ -147,7 +149,7 @@
                 return false;
             }
             const auto& iter =
-                    mCameraTorchStatuses.find(String16(String8::format("%d", cameraId)));
+                    mCameraTorchStatuses.find(std::to_string(cameraId));
             foundStatus = (iter != mCameraTorchStatuses.end() && iter->second == status);
         }
         return true;
@@ -155,14 +157,14 @@
 
     int32_t getTorchStatus(int32_t cameraId) const {
         Mutex::Autolock l(mLock);
-        const auto& iter = mCameraTorchStatuses.find(String16(String8::format("%d", cameraId)));
+        const auto& iter = mCameraTorchStatuses.find(std::to_string(cameraId));
         if (iter == mCameraTorchStatuses.end()) {
             return hardware::ICameraServiceListener::TORCH_STATUS_UNKNOWN;
         }
         return iter->second;
     };
 
-    int32_t getStatus(const String16& cameraId) const {
+    int32_t getStatus(const std::string& cameraId) const {
         Mutex::Autolock l(mLock);
         const auto& iter = mCameraStatuses.find(cameraId);
         if (iter == mCameraStatuses.end()) {
@@ -352,11 +354,11 @@
 
     EXPECT_EQ(numCameras, static_cast<const int>(statuses.size()));
     for (const auto &it : statuses) {
-        listener->onStatusChanged(it.status, String16(it.cameraId));
+        listener->onStatusChanged(it.status, it.cameraId);
     }
 
     for (int32_t i = 0; i < numCameras; i++) {
-        String16 cameraId = String16(String8::format("%d", i));
+        std::string cameraId = std::to_string(i);
         bool isSupported = false;
         res = service->supportsCameraApi(cameraId,
                 hardware::ICameraService::API_VERSION_2, &isSupported);
@@ -384,7 +386,7 @@
         // Check connect binder calls
         sp<TestCameraDeviceCallbacks> callbacks(new TestCameraDeviceCallbacks());
         sp<hardware::camera2::ICameraDeviceUser> device;
-        res = service->connectDevice(callbacks, cameraId, String16("meeeeeeeee!"),
+        res = service->connectDevice(callbacks, cameraId, "meeeeeeeee!",
                 {}, hardware::ICameraService::USE_CALLING_UID, /*oomScoreOffset*/ 0,
                 /*targetSdkVersion*/__ANDROID_API_FUTURE__,
                 /*overrideToPortrait*/false, /*out*/&device);
@@ -423,12 +425,12 @@
     sp<TestCameraServiceListener> serviceListener;
 
     std::pair<sp<TestCameraDeviceCallbacks>, sp<hardware::camera2::ICameraDeviceUser>>
-            openNewDevice(const String16& deviceId) {
+            openNewDevice(const std::string& deviceId) {
         sp<TestCameraDeviceCallbacks> callbacks(new TestCameraDeviceCallbacks());
         sp<hardware::camera2::ICameraDeviceUser> device;
         {
             SCOPED_TRACE("openNewDevice");
-            binder::Status res = service->connectDevice(callbacks, deviceId, String16("meeeeeeeee!"),
+            binder::Status res = service->connectDevice(callbacks, deviceId, "meeeeeeeee!",
                     {}, hardware::ICameraService::USE_CALLING_UID, /*oomScoreOffset*/ 0,
                     /*targetSdkVersion*/__ANDROID_API_FUTURE__,
                     /*overrideToPortrait*/false, /*out*/&device);
@@ -464,7 +466,7 @@
         std::vector<hardware::CameraStatus> statuses;
         service->addListener(serviceListener, &statuses);
         for (const auto &it : statuses) {
-            serviceListener->onStatusChanged(it.status, String16(it.cameraId));
+            serviceListener->onStatusChanged(it.status, it.cameraId);
         }
         service->getNumberOfCameras(hardware::ICameraService::CAMERA_TYPE_BACKWARD_COMPATIBLE,
                 &numCameras);
@@ -484,9 +486,8 @@
     ASSERT_NOT_NULL(service);
     EXPECT_TRUE(serviceListener->waitForNumCameras(numCameras));
     for (int32_t i = 0; i < numCameras; i++) {
-        String8 cameraId8 = String8::format("%d", i);
+        std::string cameraId = std::to_string(i);
         // Make sure we're available, or skip device tests otherwise
-        String16 cameraId(cameraId8);
         int32_t s = serviceListener->getStatus(cameraId);
         EXPECT_EQ(hardware::ICameraServiceListener::STATUS_PRESENT, s);
         if (s != hardware::ICameraServiceListener::STATUS_PRESENT) {
@@ -513,7 +514,7 @@
 
         sp<Surface> surface(new Surface(gbProducer, /*controlledByApp*/false));
 
-        String16 noPhysicalId;
+        std::string noPhysicalId;
         OutputConfiguration output(gbProducer, /*rotation*/0, noPhysicalId);
 
         // Can we configure?
@@ -550,7 +551,7 @@
         EXPECT_TRUE(res.isOk()) << res;
 
         hardware::camera2::CaptureRequest request;
-        request.mPhysicalCameraSettings.push_back({cameraId8.string(), requestTemplate});
+        request.mPhysicalCameraSettings.push_back({cameraId, requestTemplate});
         request.mSurfaceList.add(surface);
         request.mIsReprocess = false;
         int64_t lastFrameNumber = 0;
@@ -577,7 +578,7 @@
                 /*out*/&requestTemplate);
         EXPECT_TRUE(res.isOk()) << res;
         hardware::camera2::CaptureRequest request2;
-        request2.mPhysicalCameraSettings.push_back({cameraId8.string(), requestTemplate});
+        request2.mPhysicalCameraSettings.push_back({cameraId, requestTemplate});
         request2.mSurfaceList.add(surface);
         request2.mIsReprocess = false;
         callbacks->clearStatus();
@@ -610,10 +611,10 @@
         EXPECT_TRUE(res.isOk()) << res;
         android::hardware::camera2::CaptureRequest request3;
         android::hardware::camera2::CaptureRequest request4;
-        request3.mPhysicalCameraSettings.push_back({cameraId8.string(), requestTemplate});
+        request3.mPhysicalCameraSettings.push_back({cameraId, requestTemplate});
         request3.mSurfaceList.add(surface);
         request3.mIsReprocess = false;
-        request4.mPhysicalCameraSettings.push_back({cameraId8.string(), requestTemplate2});
+        request4.mPhysicalCameraSettings.push_back({cameraId, requestTemplate2});
         request4.mSurfaceList.add(surface);
         request4.mIsReprocess = false;
         std::vector<hardware::camera2::CaptureRequest> requestList;
diff --git a/camera/tests/CameraCharacteristicsPermission.cpp b/camera/tests/CameraCharacteristicsPermission.cpp
index f2fa48c..1de7cb4 100644
--- a/camera/tests/CameraCharacteristicsPermission.cpp
+++ b/camera/tests/CameraCharacteristicsPermission.cpp
@@ -62,7 +62,7 @@
 TEST_F(CameraCharacteristicsPermission, TestCameraPermission) {
     for (int32_t cameraId = 0; cameraId < numCameras; cameraId++) {
 
-        String16 cameraIdStr = String16(String8::format("%d", cameraId));
+        std::string cameraIdStr = std::to_string(cameraId);
         bool isSupported = false;
         auto rc = mCameraService->supportsCameraApi(cameraIdStr,
                 hardware::ICameraService::API_VERSION_2, &isSupported);
diff --git a/camera/tests/CameraZSLTests.cpp b/camera/tests/CameraZSLTests.cpp
index 6423709..3ae7659 100644
--- a/camera/tests/CameraZSLTests.cpp
+++ b/camera/tests/CameraZSLTests.cpp
@@ -27,6 +27,7 @@
 #include <camera/CameraParameters.h>
 #include <camera/CameraMetadata.h>
 #include <camera/Camera.h>
+#include <camera/StringUtils.h>
 #include <android/hardware/ICameraService.h>
 
 using namespace android;
@@ -169,7 +170,7 @@
         sp<SurfaceControl> surfaceControl;
         sp<ICamera> cameraDevice;
 
-        String16 cameraIdStr = String16(String8::format("%d", cameraId));
+        std::string cameraIdStr = std::to_string(cameraId);
         bool isSupported = false;
         rc = mCameraService->supportsCameraApi(cameraIdStr,
                 hardware::ICameraService::API_VERSION_1, &isSupported);
@@ -208,7 +209,7 @@
         }
 
         rc = mCameraService->connect(this, cameraId,
-                String16("ZSLTest"), hardware::ICameraService::USE_CALLING_UID,
+                "ZSLTest", hardware::ICameraService::USE_CALLING_UID,
                 hardware::ICameraService::USE_CALLING_PID,
                 /*targetSdkVersion*/__ANDROID_API_FUTURE__,
                 /*overrideToPortrait*/false, /*forceSlowJpegMode*/false, &cameraDevice);
diff --git a/camera/tests/fuzzer/camera_Parameters_fuzzer.cpp b/camera/tests/fuzzer/camera_Parameters_fuzzer.cpp
index 45b3526..07efc20 100644
--- a/camera/tests/fuzzer/camera_Parameters_fuzzer.cpp
+++ b/camera/tests/fuzzer/camera_Parameters_fuzzer.cpp
@@ -19,6 +19,7 @@
 #include <fcntl.h>
 #include <fuzzer/FuzzedDataProvider.h>
 #include <utils/String16.h>
+#include <camera/StringUtils.h>
 
 using namespace std;
 using namespace android;
@@ -77,7 +78,7 @@
         } else {
             params = mFDP->ConsumeRandomLengthString();
         }
-        *obj = new type(String8(params.c_str()));
+        *obj = new type(toString8(params));
     }
 }
 
diff --git a/camera/tests/fuzzer/camera_SessionStats_fuzzer.cpp b/camera/tests/fuzzer/camera_SessionStats_fuzzer.cpp
index 2f2ad77..c9bb20c 100644
--- a/camera/tests/fuzzer/camera_SessionStats_fuzzer.cpp
+++ b/camera/tests/fuzzer/camera_SessionStats_fuzzer.cpp
@@ -17,6 +17,7 @@
 #include <CameraSessionStats.h>
 #include <binder/Parcel.h>
 #include <fuzzer/FuzzedDataProvider.h>
+#include <camera/StringUtils.h>
 #include "camera2common.h"
 
 using namespace std;
@@ -100,10 +101,9 @@
     if (fdp.ConsumeBool()) {
         cameraSessionStats = new CameraSessionStats();
     } else {
-        string camId = fdp.ConsumeRandomLengthString();
-        String16 cameraId(camId.c_str());
+        string cameraId = fdp.ConsumeRandomLengthString();
         if (fdp.ConsumeBool()) {
-            parcelCamSessionStats.writeString16(cameraId);
+            parcelCamSessionStats.writeString16(toString16(cameraId));
         }
         int32_t facing = fdp.ConsumeIntegral<int32_t>();
         if (fdp.ConsumeBool()) {
@@ -113,10 +113,9 @@
         if (fdp.ConsumeBool()) {
             parcelCamSessionStats.writeInt32(newCameraState);
         }
-        string name = fdp.ConsumeRandomLengthString();
-        String16 clientName(name.c_str());
+        string clientName = fdp.ConsumeRandomLengthString();
         if (fdp.ConsumeBool()) {
-            parcelCamSessionStats.writeString16(clientName);
+            parcelCamSessionStats.writeString16(toString16(clientName));
         }
         int32_t apiLevel = fdp.ConsumeIntegral<int32_t>();
         if (fdp.ConsumeBool()) {
diff --git a/camera/tests/fuzzer/camera_c2CaptureRequest_fuzzer.cpp b/camera/tests/fuzzer/camera_c2CaptureRequest_fuzzer.cpp
index 06215a5..494ec1b 100644
--- a/camera/tests/fuzzer/camera_c2CaptureRequest_fuzzer.cpp
+++ b/camera/tests/fuzzer/camera_c2CaptureRequest_fuzzer.cpp
@@ -15,6 +15,7 @@
  */
 
 #include <CameraMetadata.h>
+#include <camera/StringUtils.h>
 #include <camera2/CaptureRequest.h>
 #include <fuzzer/FuzzedDataProvider.h>
 #include <gui/Surface.h>
@@ -45,7 +46,7 @@
     for (size_t idx = 0; idx < physicalCameraSettingsSize; ++idx) {
         string id = fdp.ConsumeRandomLengthString();
         if (fdp.ConsumeBool()) {
-            parcelCamCaptureReq.writeString16(String16(id.c_str()));
+            parcelCamCaptureReq.writeString16(toString16(id));
         }
         CameraMetadata cameraMetadata;
         if (fdp.ConsumeBool()) {
diff --git a/camera/tests/fuzzer/camera_c2OutputConfiguration_fuzzer.cpp b/camera/tests/fuzzer/camera_c2OutputConfiguration_fuzzer.cpp
index 51ac4e8..2fe9a94 100644
--- a/camera/tests/fuzzer/camera_c2OutputConfiguration_fuzzer.cpp
+++ b/camera/tests/fuzzer/camera_c2OutputConfiguration_fuzzer.cpp
@@ -38,8 +38,7 @@
         outputConfiguration = new OutputConfiguration();
     } else {
         int32_t rotation = fdp.ConsumeIntegral<int32_t>();
-        string phyCameraId = fdp.ConsumeRandomLengthString();
-        String16 physicalCameraId(phyCameraId.c_str());
+        string physicalCameraId = fdp.ConsumeRandomLengthString();
         int32_t surfaceSetID = fdp.ConsumeIntegral<int32_t>();
         bool isShared = fdp.ConsumeBool();
 
diff --git a/camera/tests/fuzzer/camera_c2SessionConfiguration_fuzzer.cpp b/camera/tests/fuzzer/camera_c2SessionConfiguration_fuzzer.cpp
index b2de95d..7cd0e59 100644
--- a/camera/tests/fuzzer/camera_c2SessionConfiguration_fuzzer.cpp
+++ b/camera/tests/fuzzer/camera_c2SessionConfiguration_fuzzer.cpp
@@ -65,8 +65,7 @@
             surface.clear();
         }
         int32_t rotation = fdp.ConsumeIntegral<int32_t>();
-        string phyCameraId = fdp.ConsumeRandomLengthString();
-        String16 physicalCameraId(phyCameraId.c_str());
+        string physicalCameraId = fdp.ConsumeRandomLengthString();
         int32_t surfaceSetID = fdp.ConsumeIntegral<int32_t>();
         bool isShared = fdp.ConsumeBool();
         outputConfiguration =
diff --git a/camera/tests/fuzzer/camera_captureResult_fuzzer.cpp b/camera/tests/fuzzer/camera_captureResult_fuzzer.cpp
index 1396431..dd857d4 100644
--- a/camera/tests/fuzzer/camera_captureResult_fuzzer.cpp
+++ b/camera/tests/fuzzer/camera_captureResult_fuzzer.cpp
@@ -32,8 +32,7 @@
     if (fdp.ConsumeBool()) {
         physicalCaptureResultInfo = new PhysicalCaptureResultInfo();
     } else {
-        string camId = fdp.ConsumeRandomLengthString();
-        String16 cameraId(camId.c_str());
+        string cameraId = fdp.ConsumeRandomLengthString();
         CameraMetadata cameraMetadata = CameraMetadata();
         physicalCaptureResultInfo = new PhysicalCaptureResultInfo(cameraId, cameraMetadata);
     }
@@ -47,9 +46,7 @@
     }
     if (fdp.ConsumeBool()) {
         captureResult->mResultExtras = CaptureResultExtras();
-        string errCamId = fdp.ConsumeRandomLengthString();
-        String16 errCameraId(errCamId.c_str());
-        captureResult->mResultExtras.errorPhysicalCameraId = errCameraId;
+        captureResult->mResultExtras.errorPhysicalCameraId = fdp.ConsumeRandomLengthString();
         captureResult->mResultExtras.isValid();
         invokeReadWriteNullParcel<CaptureResultExtras>(&(captureResult->mResultExtras));
     }
diff --git a/camera/tests/fuzzer/camera_fuzzer.cpp b/camera/tests/fuzzer/camera_fuzzer.cpp
index f9ef98e..d09a6dd 100644
--- a/camera/tests/fuzzer/camera_fuzzer.cpp
+++ b/camera/tests/fuzzer/camera_fuzzer.cpp
@@ -149,7 +149,7 @@
     sp<IBinder> binder = sm->getService(String16("media.camera"));
     mCameraService = interface_cast<ICameraService>(binder);
     mCameraService->connect(this, mFDP->ConsumeIntegral<int32_t>() /* cameraId */,
-                            String16("CAMERAFUZZ"), hardware::ICameraService::USE_CALLING_UID,
+                            "CAMERAFUZZ", hardware::ICameraService::USE_CALLING_UID,
                             hardware::ICameraService::USE_CALLING_PID,
                             /*targetSdkVersion*/ __ANDROID_API_FUTURE__,
                             /*overrideToPortrait*/false, /*forceSlowJpegMode*/false, &cameraDevice);
@@ -294,18 +294,15 @@
         cameraStatus = new CameraStatus();
     } else {
         string cid = mFDP->ConsumeRandomLengthString();
-        String8 id(cid.c_str());
         int32_t status = mFDP->ConsumeIntegral<int32_t>();
         size_t unavailSubIdsSize = mFDP->ConsumeIntegralInRange<size_t>(kSizeMin, kSizeMax);
-        vector<String8> unavailSubIds;
+        vector<std::string> unavailSubIds;
         for (size_t idx = 0; idx < unavailSubIdsSize; ++idx) {
             string subId = mFDP->ConsumeRandomLengthString();
-            String8 unavailSubId(subId.c_str());
-            unavailSubIds.push_back(unavailSubId);
+            unavailSubIds.push_back(subId);
         }
-        string clientPkg = mFDP->ConsumeRandomLengthString();
-        String8 clientPackage(clientPkg.c_str());
-        cameraStatus = new CameraStatus(id, status, unavailSubIds, clientPackage);
+        string clientPackage = mFDP->ConsumeRandomLengthString();
+        cameraStatus = new CameraStatus(cid, status, unavailSubIds, clientPackage);
     }
 
     invokeReadWriteParcel<CameraStatus>(cameraStatus);
diff --git a/media/audioserver/Android.bp b/media/audioserver/Android.bp
index 828d861..2030dc7 100644
--- a/media/audioserver/Android.bp
+++ b/media/audioserver/Android.bp
@@ -25,21 +25,31 @@
         "libmediametrics_headers",
     ],
 
-    shared_libs: [
-        "packagemanager_aidl-cpp",
+    defaults: [
+        "libaaudioservice_dependencies",
+        "libaudioflinger_dependencies",
+        "libaudiopolicyservice_dependencies",
+        "latest_android_media_audio_common_types_cpp_shared",
+        "latest_android_hardware_audio_core_sounddose_ndk_shared",
+    ],
+
+    static_libs: [
         "libaaudioservice",
-        "libaudioclient",
         "libaudioflinger",
         "libaudiopolicyservice",
+        "libmedialogservice",
+        "libnbaio",
+    ],
+
+    shared_libs: [
+        "libaudioclient",
         "libaudioprocessing",
         "libbinder",
         "libcutils",
         "libhidlbase",
         "liblog",
         "libmedia",
-        "libmedialogservice",
         "libmediautils",
-        "libnbaio",
         "libnblog",
         "libpowermanager",
         "libutils",
@@ -59,9 +69,9 @@
         "frameworks/av/services/audiopolicy/engine/interface",
         "frameworks/av/services/audiopolicy/service",
         "frameworks/av/services/medialog",
+        "frameworks/av/services/oboeservice", // TODO oboeservice is the old folder name for aaudioservice. It will be changed.
 
-        // TODO oboeservice is the old folder name for aaudioservice. It will be changed.
-        "frameworks/av/services/oboeservice",
+
     ],
 
     init_rc: ["audioserver.rc"],
diff --git a/media/audioserver/main_audioserver.cpp b/media/audioserver/main_audioserver.cpp
index 1e3bfe0..c7a1bfd 100644
--- a/media/audioserver/main_audioserver.cpp
+++ b/media/audioserver/main_audioserver.cpp
@@ -184,7 +184,7 @@
         // attempting to call audio flinger on a null pointer could make the process crash
         // and attract attentions.
         std::vector<AudioMMapPolicyInfo> policyInfos;
-        status_t status = af->getMmapPolicyInfos(
+        status_t status = sp<IAudioFlinger>::cast(af)->getMmapPolicyInfos(
                 AudioMMapPolicyType::DEFAULT, &policyInfos);
         // Initialize aaudio service when querying mmap policy succeeds and
         // any of the policy supports MMAP.
diff --git a/media/codec2/components/aac/C2SoftAacEnc.cpp b/media/codec2/components/aac/C2SoftAacEnc.cpp
index d865ab2..721a12a 100644
--- a/media/codec2/components/aac/C2SoftAacEnc.cpp
+++ b/media/codec2/components/aac/C2SoftAacEnc.cpp
@@ -69,7 +69,7 @@
         addParameter(
                 DefineParam(mChannelCount, C2_PARAMKEY_CHANNEL_COUNT)
                 .withDefault(new C2StreamChannelCountInfo::input(0u, 1))
-                .withFields({C2F(mChannelCount, value).inRange(1, 6)})
+                .withFields({C2F(mChannelCount, value).inRange(1, kMaxChannelCount)})
                 .withSetter(Setter<decltype(*mChannelCount)>::StrictValueWithNoDeps)
                 .build());
 
@@ -198,10 +198,17 @@
 }
 
 c2_status_t C2SoftAacEnc::onFlush_sm() {
+    if (mAACEncoder != nullptr) {
+        /* encoder's internal input buffer needs to be reset during flush */
+        if (AACENC_OK != aacEncoder_SetParam(mAACEncoder, AACENC_CONTROL_STATE, AACENC_INIT_ALL)) {
+            ALOGE("Failed to reset AAC encoder");
+        }
+    }
     mSentCodecSpecificData = false;
     mInputSize = 0u;
     mNextFrameTimestampUs.reset();
     mLastFrameEndTimestampUs.reset();
+    mRemainderLen = 0;
     return C2_OK;
 }
 
@@ -562,6 +569,11 @@
                 inBufferSize[0] -= outargs.numInSamples * sizeof(int16_t);
                 inargs.numInSamples -= outargs.numInSamples;
             }
+        } else {
+            // In case of error in encode call, discard remaining input bytes.
+            inBuffer[0] = nullptr;
+            inBufferSize[0] = 0;
+            inargs.numInSamples = 0;
         }
         ALOGV("encoderErr = %d mInputSize = %zu "
               "inargs.numInSamples = %d, mNextFrameTimestampUs = %lld",
@@ -597,10 +609,19 @@
                            &outBufDesc,
                            &inargs,
                            &outargs);
+
+        // after flush, discard remaining input bytes.
+        inBuffer[0] = nullptr;
         inBufferSize[0] = 0;
     }
 
     if (inBufferSize[0] > 0) {
+        if (inBufferSize[0] > kRemainderBufSize) {
+            ALOGE("Remaining bytes %d greater than remainder buffer size %zu", inBufferSize[0],
+                    kRemainderBufSize);
+            work->result = C2_CORRUPTED;
+            return;
+        }
         for (size_t i = 0; i < inBufferSize[0]; ++i) {
             mRemainder[i] = static_cast<uint8_t *>(inBuffer[0])[i];
         }
diff --git a/media/codec2/components/aac/C2SoftAacEnc.h b/media/codec2/components/aac/C2SoftAacEnc.h
index 9a28280..c79526c 100644
--- a/media/codec2/components/aac/C2SoftAacEnc.h
+++ b/media/codec2/components/aac/C2SoftAacEnc.h
@@ -47,6 +47,9 @@
             const std::shared_ptr<C2BlockPool> &pool) override;
 
 private:
+    static constexpr size_t kMaxChannelCount = 6;
+    static constexpr size_t kRemainderBufSize = kMaxChannelCount * sizeof(int16_t);
+
     std::shared_ptr<IntfImpl> mIntf;
 
     HANDLE_AACENCODER mAACEncoder;
@@ -63,7 +66,7 @@
     std::atomic_uint64_t mOutIndex;
 
     // We support max 6 channels
-    uint8_t mRemainder[6 * sizeof(int16_t)];
+    uint8_t mRemainder[kRemainderBufSize];
     size_t mRemainderLen;
 
     status_t initEncoder();
diff --git a/media/codec2/components/dav1d/Android.bp b/media/codec2/components/dav1d/Android.bp
new file mode 100644
index 0000000..f7850ad
--- /dev/null
+++ b/media/codec2/components/dav1d/Android.bp
@@ -0,0 +1,37 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_av_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_av_license"],
+}
+
+cc_library {
+    name: "libcodec2_soft_av1dec_dav1d",
+    // TODO: b/277797541 - enable once ready
+    enabled: false,
+
+    defaults: [
+        "libcodec2_soft-defaults",
+        "libcodec2_soft_sanitize_all-defaults",
+    ],
+
+    cflags: [
+        "-DCODECNAME=\"c2.android.dav1d-av1.decoder\"",
+        "-Wno-unused-variable",
+    ],
+
+    srcs: ["C2SoftDav1dDec.cpp"],
+    static_libs: [
+        "libyuv_static",
+        "libdav1d_8bit",
+        "libdav1d_16bit",
+    ],
+
+    apex_available: [
+        "//apex_available:platform",
+        "com.android.media.swcodec",
+    ],
+
+}
diff --git a/media/codec2/components/dav1d/C2SoftDav1dDec.cpp b/media/codec2/components/dav1d/C2SoftDav1dDec.cpp
new file mode 100644
index 0000000..b0cef41
--- /dev/null
+++ b/media/codec2/components/dav1d/C2SoftDav1dDec.cpp
@@ -0,0 +1,1493 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// #define LOG_NDEBUG 0
+#define LOG_TAG "C2SoftDav1dDec"
+#include <android-base/properties.h>
+#include <cutils/properties.h>
+#include <thread>
+
+#include <C2Debug.h>
+#include <C2PlatformSupport.h>
+#include <Codec2BufferUtils.h>
+#include <Codec2CommonUtils.h>
+#include <Codec2Mapper.h>
+#include <SimpleC2Interface.h>
+#include <libyuv.h>
+#include <log/log.h>
+#include <media/stagefright/foundation/AUtils.h>
+#include <media/stagefright/foundation/MediaDefs.h>
+#include "C2SoftDav1dDec.h"
+
+// libyuv version required for I410ToAB30Matrix and I210ToAB30Matrix.
+#if LIBYUV_VERSION >= 1780
+#include <algorithm>
+#define HAVE_LIBYUV_I410_I210_TO_AB30 1
+#else
+#define HAVE_LIBYUV_I410_I210_TO_AB30 0
+#endif
+
+namespace android {
+
+// Flag to enable dumping the bitsteram and the decoded pictures to files.
+static const bool ENABLE_DUMPING_FILES_DEFAULT = false;
+static const char ENABLE_DUMPING_FILES_PROPERTY[] = "debug.dav1d.enabledumping";
+
+// The number of frames to dump to a file
+static const int NUM_FRAMES_TO_DUMP_DEFAULT = INT_MAX;
+static const char NUM_FRAMES_TO_DUMP_PROPERTY[] = "debug.dav1d.numframestodump";
+
+// The number of threads used for the dav1d decoder.
+static const int NUM_THREADS_DAV1D_DEFAULT = 0;
+static const char NUM_THREADS_DAV1D_PROPERTY[] = "debug.dav1d.numthreads";
+
+// codecname set and passed in as a compile flag from Android.bp
+constexpr char COMPONENT_NAME[] = CODECNAME;
+
+constexpr size_t kMinInputBufferSize = 2 * 1024 * 1024;
+
+class C2SoftDav1dDec::IntfImpl : public SimpleInterface<void>::BaseParams {
+  public:
+    explicit IntfImpl(const std::shared_ptr<C2ReflectorHelper>& helper)
+        : SimpleInterface<void>::BaseParams(helper, COMPONENT_NAME, C2Component::KIND_DECODER,
+                                            C2Component::DOMAIN_VIDEO, MEDIA_MIMETYPE_VIDEO_AV1) {
+        noPrivateBuffers();
+        noInputReferences();
+        noOutputReferences();
+        noInputLatency();
+        noTimeStretch();
+
+        addParameter(DefineParam(mAttrib, C2_PARAMKEY_COMPONENT_ATTRIBUTES)
+                             .withConstValue(new C2ComponentAttributesSetting(
+                                     C2Component::ATTRIB_IS_TEMPORAL))
+                             .build());
+
+        addParameter(DefineParam(mSize, C2_PARAMKEY_PICTURE_SIZE)
+                             .withDefault(new C2StreamPictureSizeInfo::output(0u, 320, 240))
+                             .withFields({
+                                     C2F(mSize, width).inRange(2, 4096),
+                                     C2F(mSize, height).inRange(2, 4096),
+                             })
+                             .withSetter(SizeSetter)
+                             .build());
+
+        addParameter(DefineParam(mProfileLevel, C2_PARAMKEY_PROFILE_LEVEL)
+                             .withDefault(new C2StreamProfileLevelInfo::input(
+                                     0u, C2Config::PROFILE_AV1_0, C2Config::LEVEL_AV1_2_1))
+                             .withFields({C2F(mProfileLevel, profile)
+                                                  .oneOf({C2Config::PROFILE_AV1_0,
+                                                          C2Config::PROFILE_AV1_1}),
+                                          C2F(mProfileLevel, level)
+                                                  .oneOf({
+                                                          C2Config::LEVEL_AV1_2,
+                                                          C2Config::LEVEL_AV1_2_1,
+                                                          C2Config::LEVEL_AV1_2_2,
+                                                          C2Config::LEVEL_AV1_2_3,
+                                                          C2Config::LEVEL_AV1_3,
+                                                          C2Config::LEVEL_AV1_3_1,
+                                                          C2Config::LEVEL_AV1_3_2,
+                                                          C2Config::LEVEL_AV1_3_3,
+                                                          C2Config::LEVEL_AV1_4,
+                                                          C2Config::LEVEL_AV1_4_1,
+                                                          C2Config::LEVEL_AV1_4_2,
+                                                          C2Config::LEVEL_AV1_4_3,
+                                                          C2Config::LEVEL_AV1_5,
+                                                          C2Config::LEVEL_AV1_5_1,
+                                                          C2Config::LEVEL_AV1_5_2,
+                                                          C2Config::LEVEL_AV1_5_3,
+                                                  })})
+                             .withSetter(ProfileLevelSetter, mSize)
+                             .build());
+
+        mHdr10PlusInfoInput = C2StreamHdr10PlusInfo::input::AllocShared(0);
+        addParameter(DefineParam(mHdr10PlusInfoInput, C2_PARAMKEY_INPUT_HDR10_PLUS_INFO)
+                             .withDefault(mHdr10PlusInfoInput)
+                             .withFields({
+                                     C2F(mHdr10PlusInfoInput, m.value).any(),
+                             })
+                             .withSetter(Hdr10PlusInfoInputSetter)
+                             .build());
+
+        mHdr10PlusInfoOutput = C2StreamHdr10PlusInfo::output::AllocShared(0);
+        addParameter(DefineParam(mHdr10PlusInfoOutput, C2_PARAMKEY_OUTPUT_HDR10_PLUS_INFO)
+                             .withDefault(mHdr10PlusInfoOutput)
+                             .withFields({
+                                     C2F(mHdr10PlusInfoOutput, m.value).any(),
+                             })
+                             .withSetter(Hdr10PlusInfoOutputSetter)
+                             .build());
+
+        // default static info
+        C2HdrStaticMetadataStruct defaultStaticInfo{};
+        helper->addStructDescriptors<C2MasteringDisplayColorVolumeStruct, C2ColorXyStruct>();
+        addParameter(
+                DefineParam(mHdrStaticInfo, C2_PARAMKEY_HDR_STATIC_INFO)
+                        .withDefault(new C2StreamHdrStaticInfo::output(0u, defaultStaticInfo))
+                        .withFields({C2F(mHdrStaticInfo, mastering.red.x).inRange(0, 1),
+                                     C2F(mHdrStaticInfo, mastering.red.y).inRange(0, 1),
+                                     C2F(mHdrStaticInfo, mastering.green.x).inRange(0, 1),
+                                     C2F(mHdrStaticInfo, mastering.green.y).inRange(0, 1),
+                                     C2F(mHdrStaticInfo, mastering.blue.x).inRange(0, 1),
+                                     C2F(mHdrStaticInfo, mastering.blue.y).inRange(0, 1),
+                                     C2F(mHdrStaticInfo, mastering.white.x).inRange(0, 1),
+                                     C2F(mHdrStaticInfo, mastering.white.x).inRange(0, 1),
+                                     C2F(mHdrStaticInfo, mastering.maxLuminance).inRange(0, 65535),
+                                     C2F(mHdrStaticInfo, mastering.minLuminance).inRange(0, 6.5535),
+                                     C2F(mHdrStaticInfo, maxCll).inRange(0, 0XFFFF),
+                                     C2F(mHdrStaticInfo, maxFall).inRange(0, 0XFFFF)})
+                        .withSetter(HdrStaticInfoSetter)
+                        .build());
+
+        addParameter(DefineParam(mMaxSize, C2_PARAMKEY_MAX_PICTURE_SIZE)
+                             .withDefault(new C2StreamMaxPictureSizeTuning::output(0u, 320, 240))
+                             .withFields({
+                                     C2F(mSize, width).inRange(2, 2048, 2),
+                                     C2F(mSize, height).inRange(2, 2048, 2),
+                             })
+                             .withSetter(MaxPictureSizeSetter, mSize)
+                             .build());
+
+        addParameter(
+                DefineParam(mMaxInputSize, C2_PARAMKEY_INPUT_MAX_BUFFER_SIZE)
+                        .withDefault(new C2StreamMaxBufferSizeInfo::input(0u, kMinInputBufferSize))
+                        .withFields({
+                                C2F(mMaxInputSize, value).any(),
+                        })
+                        .calculatedAs(MaxInputSizeSetter, mMaxSize)
+                        .build());
+
+        C2ChromaOffsetStruct locations[1] = {C2ChromaOffsetStruct::ITU_YUV_420_0()};
+        std::shared_ptr<C2StreamColorInfo::output> defaultColorInfo =
+                C2StreamColorInfo::output::AllocShared(1u, 0u, 8u /* bitDepth */, C2Color::YUV_420);
+        memcpy(defaultColorInfo->m.locations, locations, sizeof(locations));
+
+        defaultColorInfo = C2StreamColorInfo::output::AllocShared(
+                {C2ChromaOffsetStruct::ITU_YUV_420_0()}, 0u, 8u /* bitDepth */, C2Color::YUV_420);
+        helper->addStructDescriptors<C2ChromaOffsetStruct>();
+
+        addParameter(DefineParam(mColorInfo, C2_PARAMKEY_CODED_COLOR_INFO)
+                             .withConstValue(defaultColorInfo)
+                             .build());
+
+        addParameter(DefineParam(mDefaultColorAspects, C2_PARAMKEY_DEFAULT_COLOR_ASPECTS)
+                             .withDefault(new C2StreamColorAspectsTuning::output(
+                                     0u, C2Color::RANGE_UNSPECIFIED, C2Color::PRIMARIES_UNSPECIFIED,
+                                     C2Color::TRANSFER_UNSPECIFIED, C2Color::MATRIX_UNSPECIFIED))
+                             .withFields({C2F(mDefaultColorAspects, range)
+                                                  .inRange(C2Color::RANGE_UNSPECIFIED,
+                                                           C2Color::RANGE_OTHER),
+                                          C2F(mDefaultColorAspects, primaries)
+                                                  .inRange(C2Color::PRIMARIES_UNSPECIFIED,
+                                                           C2Color::PRIMARIES_OTHER),
+                                          C2F(mDefaultColorAspects, transfer)
+                                                  .inRange(C2Color::TRANSFER_UNSPECIFIED,
+                                                           C2Color::TRANSFER_OTHER),
+                                          C2F(mDefaultColorAspects, matrix)
+                                                  .inRange(C2Color::MATRIX_UNSPECIFIED,
+                                                           C2Color::MATRIX_OTHER)})
+                             .withSetter(DefaultColorAspectsSetter)
+                             .build());
+
+        addParameter(DefineParam(mCodedColorAspects, C2_PARAMKEY_VUI_COLOR_ASPECTS)
+                             .withDefault(new C2StreamColorAspectsInfo::input(
+                                     0u, C2Color::RANGE_LIMITED, C2Color::PRIMARIES_UNSPECIFIED,
+                                     C2Color::TRANSFER_UNSPECIFIED, C2Color::MATRIX_UNSPECIFIED))
+                             .withFields({C2F(mCodedColorAspects, range)
+                                                  .inRange(C2Color::RANGE_UNSPECIFIED,
+                                                           C2Color::RANGE_OTHER),
+                                          C2F(mCodedColorAspects, primaries)
+                                                  .inRange(C2Color::PRIMARIES_UNSPECIFIED,
+                                                           C2Color::PRIMARIES_OTHER),
+                                          C2F(mCodedColorAspects, transfer)
+                                                  .inRange(C2Color::TRANSFER_UNSPECIFIED,
+                                                           C2Color::TRANSFER_OTHER),
+                                          C2F(mCodedColorAspects, matrix)
+                                                  .inRange(C2Color::MATRIX_UNSPECIFIED,
+                                                           C2Color::MATRIX_OTHER)})
+                             .withSetter(CodedColorAspectsSetter)
+                             .build());
+
+        addParameter(
+                DefineParam(mColorAspects, C2_PARAMKEY_COLOR_ASPECTS)
+                        .withDefault(new C2StreamColorAspectsInfo::output(
+                                0u, C2Color::RANGE_UNSPECIFIED, C2Color::PRIMARIES_UNSPECIFIED,
+                                C2Color::TRANSFER_UNSPECIFIED, C2Color::MATRIX_UNSPECIFIED))
+                        .withFields(
+                                {C2F(mColorAspects, range)
+                                         .inRange(C2Color::RANGE_UNSPECIFIED, C2Color::RANGE_OTHER),
+                                 C2F(mColorAspects, primaries)
+                                         .inRange(C2Color::PRIMARIES_UNSPECIFIED,
+                                                  C2Color::PRIMARIES_OTHER),
+                                 C2F(mColorAspects, transfer)
+                                         .inRange(C2Color::TRANSFER_UNSPECIFIED,
+                                                  C2Color::TRANSFER_OTHER),
+                                 C2F(mColorAspects, matrix)
+                                         .inRange(C2Color::MATRIX_UNSPECIFIED,
+                                                  C2Color::MATRIX_OTHER)})
+                        .withSetter(ColorAspectsSetter, mDefaultColorAspects, mCodedColorAspects)
+                        .build());
+
+        std::vector<uint32_t> pixelFormats = {HAL_PIXEL_FORMAT_YCBCR_420_888};
+        if (isHalPixelFormatSupported((AHardwareBuffer_Format)HAL_PIXEL_FORMAT_YCBCR_P010)) {
+            pixelFormats.push_back(HAL_PIXEL_FORMAT_YCBCR_P010);
+        }
+        // If color format surface isn't added to supported formats, there is no way to know
+        // when the color-format is configured to surface. This is necessary to be able to
+        // choose 10-bit format while decoding 10-bit clips in surface mode.
+        pixelFormats.push_back(HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED);
+
+        // TODO: support more formats?
+        addParameter(DefineParam(mPixelFormat, C2_PARAMKEY_PIXEL_FORMAT)
+                             .withDefault(new C2StreamPixelFormatInfo::output(
+                                     0u, HAL_PIXEL_FORMAT_YCBCR_420_888))
+                             .withFields({C2F(mPixelFormat, value).oneOf(pixelFormats)})
+                             .withSetter((Setter<decltype(*mPixelFormat)>::StrictValueWithNoDeps))
+                             .build());
+    }
+
+    static C2R SizeSetter(bool mayBlock, const C2P<C2StreamPictureSizeInfo::output>& oldMe,
+                          C2P<C2StreamPictureSizeInfo::output>& me) {
+        (void)mayBlock;
+        C2R res = C2R::Ok();
+        if (!me.F(me.v.width).supportsAtAll(me.v.width)) {
+            res = res.plus(C2SettingResultBuilder::BadValue(me.F(me.v.width)));
+            me.set().width = oldMe.v.width;
+        }
+        if (!me.F(me.v.height).supportsAtAll(me.v.height)) {
+            res = res.plus(C2SettingResultBuilder::BadValue(me.F(me.v.height)));
+            me.set().height = oldMe.v.height;
+        }
+        return res;
+    }
+
+    static C2R MaxPictureSizeSetter(bool mayBlock, C2P<C2StreamMaxPictureSizeTuning::output>& me,
+                                    const C2P<C2StreamPictureSizeInfo::output>& size) {
+        (void)mayBlock;
+        // TODO: get max width/height from the size's field helpers vs.
+        // hardcoding
+        me.set().width = c2_min(c2_max(me.v.width, size.v.width), 4096u);
+        me.set().height = c2_min(c2_max(me.v.height, size.v.height), 4096u);
+        return C2R::Ok();
+    }
+
+    static C2R MaxInputSizeSetter(bool mayBlock, C2P<C2StreamMaxBufferSizeInfo::input>& me,
+                                  const C2P<C2StreamMaxPictureSizeTuning::output>& maxSize) {
+        (void)mayBlock;
+        // assume compression ratio of 2, but enforce a floor
+        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) {
+        (void)mayBlock;
+        if (me.v.range > C2Color::RANGE_OTHER) {
+            me.set().range = C2Color::RANGE_OTHER;
+        }
+        if (me.v.primaries > C2Color::PRIMARIES_OTHER) {
+            me.set().primaries = C2Color::PRIMARIES_OTHER;
+        }
+        if (me.v.transfer > C2Color::TRANSFER_OTHER) {
+            me.set().transfer = C2Color::TRANSFER_OTHER;
+        }
+        if (me.v.matrix > C2Color::MATRIX_OTHER) {
+            me.set().matrix = C2Color::MATRIX_OTHER;
+        }
+        return C2R::Ok();
+    }
+
+    static C2R CodedColorAspectsSetter(bool mayBlock, C2P<C2StreamColorAspectsInfo::input>& me) {
+        (void)mayBlock;
+        if (me.v.range > C2Color::RANGE_OTHER) {
+            me.set().range = C2Color::RANGE_OTHER;
+        }
+        if (me.v.primaries > C2Color::PRIMARIES_OTHER) {
+            me.set().primaries = C2Color::PRIMARIES_OTHER;
+        }
+        if (me.v.transfer > C2Color::TRANSFER_OTHER) {
+            me.set().transfer = C2Color::TRANSFER_OTHER;
+        }
+        if (me.v.matrix > C2Color::MATRIX_OTHER) {
+            me.set().matrix = C2Color::MATRIX_OTHER;
+        }
+        return C2R::Ok();
+    }
+
+    static C2R ColorAspectsSetter(bool mayBlock, C2P<C2StreamColorAspectsInfo::output>& me,
+                                  const C2P<C2StreamColorAspectsTuning::output>& def,
+                                  const C2P<C2StreamColorAspectsInfo::input>& coded) {
+        (void)mayBlock;
+        // take default values for all unspecified fields, and coded values for specified ones
+        me.set().range = coded.v.range == RANGE_UNSPECIFIED ? def.v.range : coded.v.range;
+        me.set().primaries =
+                coded.v.primaries == PRIMARIES_UNSPECIFIED ? def.v.primaries : coded.v.primaries;
+        me.set().transfer =
+                coded.v.transfer == TRANSFER_UNSPECIFIED ? def.v.transfer : coded.v.transfer;
+        me.set().matrix = coded.v.matrix == MATRIX_UNSPECIFIED ? def.v.matrix : coded.v.matrix;
+        return C2R::Ok();
+    }
+
+    static C2R ProfileLevelSetter(bool mayBlock, C2P<C2StreamProfileLevelInfo::input>& me,
+                                  const C2P<C2StreamPictureSizeInfo::output>& size) {
+        (void)mayBlock;
+        (void)size;
+        (void)me;  // TODO: validate
+        return C2R::Ok();
+    }
+
+    std::shared_ptr<C2StreamColorAspectsTuning::output> getDefaultColorAspects_l() {
+        return mDefaultColorAspects;
+    }
+
+    std::shared_ptr<C2StreamColorAspectsInfo::output> getColorAspects_l() { return mColorAspects; }
+
+    static C2R Hdr10PlusInfoInputSetter(bool mayBlock, C2P<C2StreamHdr10PlusInfo::input>& me) {
+        (void)mayBlock;
+        (void)me;  // TODO: validate
+        return C2R::Ok();
+    }
+
+    static C2R Hdr10PlusInfoOutputSetter(bool mayBlock, C2P<C2StreamHdr10PlusInfo::output>& me) {
+        (void)mayBlock;
+        (void)me;  // TODO: validate
+        return C2R::Ok();
+    }
+
+    // unsafe getters
+    std::shared_ptr<C2StreamPixelFormatInfo::output> getPixelFormat_l() const {
+        return mPixelFormat;
+    }
+
+    static C2R HdrStaticInfoSetter(bool mayBlock, C2P<C2StreamHdrStaticInfo::output>& me) {
+        (void)mayBlock;
+        if (me.v.mastering.red.x > 1) {
+            me.set().mastering.red.x = 1;
+        }
+        if (me.v.mastering.red.y > 1) {
+            me.set().mastering.red.y = 1;
+        }
+        if (me.v.mastering.green.x > 1) {
+            me.set().mastering.green.x = 1;
+        }
+        if (me.v.mastering.green.y > 1) {
+            me.set().mastering.green.y = 1;
+        }
+        if (me.v.mastering.blue.x > 1) {
+            me.set().mastering.blue.x = 1;
+        }
+        if (me.v.mastering.blue.y > 1) {
+            me.set().mastering.blue.y = 1;
+        }
+        if (me.v.mastering.white.x > 1) {
+            me.set().mastering.white.x = 1;
+        }
+        if (me.v.mastering.white.y > 1) {
+            me.set().mastering.white.y = 1;
+        }
+        if (me.v.mastering.maxLuminance > 65535.0) {
+            me.set().mastering.maxLuminance = 65535.0;
+        }
+        if (me.v.mastering.minLuminance > 6.5535) {
+            me.set().mastering.minLuminance = 6.5535;
+        }
+        if (me.v.maxCll > 65535.0) {
+            me.set().maxCll = 65535.0;
+        }
+        if (me.v.maxFall > 65535.0) {
+            me.set().maxFall = 65535.0;
+        }
+        return C2R::Ok();
+    }
+
+  private:
+    std::shared_ptr<C2StreamProfileLevelInfo::input> mProfileLevel;
+    std::shared_ptr<C2StreamPictureSizeInfo::output> mSize;
+    std::shared_ptr<C2StreamMaxPictureSizeTuning::output> mMaxSize;
+    std::shared_ptr<C2StreamMaxBufferSizeInfo::input> mMaxInputSize;
+    std::shared_ptr<C2StreamColorInfo::output> mColorInfo;
+    std::shared_ptr<C2StreamPixelFormatInfo::output> mPixelFormat;
+    std::shared_ptr<C2StreamColorAspectsTuning::output> mDefaultColorAspects;
+    std::shared_ptr<C2StreamColorAspectsInfo::input> mCodedColorAspects;
+    std::shared_ptr<C2StreamColorAspectsInfo::output> mColorAspects;
+    std::shared_ptr<C2StreamHdr10PlusInfo::input> mHdr10PlusInfoInput;
+    std::shared_ptr<C2StreamHdr10PlusInfo::output> mHdr10PlusInfoOutput;
+    std::shared_ptr<C2StreamHdrStaticInfo::output> mHdrStaticInfo;
+};
+
+C2SoftDav1dDec::C2SoftDav1dDec(const char* name, c2_node_id_t id,
+                               const std::shared_ptr<IntfImpl>& intfImpl)
+    : SimpleC2Component(std::make_shared<SimpleInterface<IntfImpl>>(name, id, intfImpl)),
+      mIntf(intfImpl) {
+    mTimeStart = mTimeEnd = systemTime();
+}
+
+C2SoftDav1dDec::~C2SoftDav1dDec() {
+    onRelease();
+}
+
+c2_status_t C2SoftDav1dDec::onInit() {
+    return initDecoder() ? C2_OK : C2_CORRUPTED;
+}
+
+c2_status_t C2SoftDav1dDec::onStop() {
+    // TODO: b/277797541 - investigate if the decoder needs to be flushed.
+    mSignalledError = false;
+    mSignalledOutputEos = false;
+    return C2_OK;
+}
+
+void C2SoftDav1dDec::onReset() {
+    (void)onStop();
+    c2_status_t err = onFlush_sm();
+    if (err != C2_OK) {
+        ALOGW("Failed to flush the av1 decoder. Trying to hard reset.");
+        destroyDecoder();
+        if (!initDecoder()) {
+            ALOGE("Hard reset failed.");
+        }
+    }
+}
+
+void C2SoftDav1dDec::flushDav1d() {
+    if (mDav1dCtx) {
+        Dav1dPicture p;
+
+        while (mDecodedPictures.size() > 0) {
+            p = mDecodedPictures.front();
+            mDecodedPictures.pop_front();
+
+            dav1d_picture_unref(&p);
+        }
+
+        int res = 0;
+        while (true) {
+            memset(&p, 0, sizeof(p));
+
+            if ((res = dav1d_get_picture(mDav1dCtx, &p)) < 0) {
+                if (res != DAV1D_ERR(EAGAIN)) {
+                    ALOGE("Error decoding frame: %s\n", strerror(DAV1D_ERR(res)));
+                    break;
+                } else {
+                    res = 0;
+                    break;
+                }
+            } else {
+                dav1d_picture_unref(&p);
+            }
+        }
+
+        dav1d_flush(mDav1dCtx);
+    }
+}
+
+void C2SoftDav1dDec::onRelease() {
+    destroyDecoder();
+}
+
+c2_status_t C2SoftDav1dDec::onFlush_sm() {
+    flushDav1d();
+
+    mSignalledError = false;
+    mSignalledOutputEos = false;
+
+    return C2_OK;
+}
+
+static int GetCPUCoreCount() {
+    int cpuCoreCount = 1;
+#if defined(_SC_NPROCESSORS_ONLN)
+    cpuCoreCount = sysconf(_SC_NPROCESSORS_ONLN);
+#else
+    // _SC_NPROC_ONLN must be defined...
+    cpuCoreCount = sysconf(_SC_NPROC_ONLN);
+#endif
+    CHECK(cpuCoreCount >= 1);
+    ALOGV("Number of CPU cores: %d", cpuCoreCount);
+    return cpuCoreCount;
+}
+
+bool C2SoftDav1dDec::initDecoder() {
+    nsecs_t now = systemTime();
+#ifdef FILE_DUMP_ENABLE
+    snprintf(mInDataFileName, 256, "%s_%" PRId64 "d.%s", DUMP_FILE_PATH, now, INPUT_DATA_DUMP_EXT);
+    snprintf(mInSizeFileName, 256, "%s_%" PRId64 "d.%s", DUMP_FILE_PATH, now, INPUT_SIZE_DUMP_EXT);
+    snprintf(mDav1dOutYuvFileName, 256, "%s_%" PRId64 "dx.%s", DUMP_FILE_PATH, now,
+             OUTPUT_YUV_DUMP_EXT);
+
+    bool enableDumping = android::base::GetBoolProperty(ENABLE_DUMPING_FILES_PROPERTY,
+                                                        ENABLE_DUMPING_FILES_DEFAULT);
+
+    num_frames_to_dump =
+            android::base::GetIntProperty(NUM_FRAMES_TO_DUMP_PROPERTY, NUM_FRAMES_TO_DUMP_DEFAULT);
+
+    if (enableDumping) {
+        ALOGD("enableDumping = %d, num_frames_to_dump = %d", enableDumping, num_frames_to_dump);
+
+        mInDataFile = fopen(mInDataFileName, "wb");
+        if (mInDataFile == nullptr) {
+            ALOGD("Could not open file %s", mInDataFileName);
+        }
+
+        mInSizeFile = fopen(mInSizeFileName, "wb");
+        if (mInSizeFile == nullptr) {
+            ALOGD("Could not open file %s", mInSizeFileName);
+        }
+
+        mDav1dOutYuvFile = fopen(mDav1dOutYuvFileName, "wb");
+        if (mDav1dOutYuvFile == nullptr) {
+            ALOGD("Could not open file %s", mDav1dOutYuvFileName);
+        }
+    }
+#endif
+    mSignalledError = false;
+    mSignalledOutputEos = false;
+    mHalPixelFormat = HAL_PIXEL_FORMAT_YV12;
+    {
+        IntfImpl::Lock lock = mIntf->lock();
+        mPixelFormatInfo = mIntf->getPixelFormat_l();
+    }
+
+    const char* version = dav1d_version();
+
+    Dav1dSettings lib_settings;
+    dav1d_default_settings(&lib_settings);
+    int cpu_count = GetCPUCoreCount();
+    lib_settings.n_threads = std::max(cpu_count / 2, 1);  // use up to half the cores by default.
+
+    int32_t numThreads =
+            android::base::GetIntProperty(NUM_THREADS_DAV1D_PROPERTY, NUM_THREADS_DAV1D_DEFAULT);
+    if (numThreads > 0) lib_settings.n_threads = numThreads;
+
+    int res = 0;
+    if ((res = dav1d_open(&mDav1dCtx, &lib_settings))) {
+        ALOGE("dav1d_open failed. status: %d.", res);
+        return false;
+    } else {
+        ALOGD("dav1d_open succeeded(n_threads=%d,version=%s).", lib_settings.n_threads, version);
+    }
+
+    return true;
+}
+
+void C2SoftDav1dDec::destroyDecoder() {
+    if (mDav1dCtx) {
+        Dav1dPicture p;
+        while (mDecodedPictures.size() > 0) {
+            memset(&p, 0, sizeof(p));
+            p = mDecodedPictures.front();
+            mDecodedPictures.pop_front();
+
+            dav1d_picture_unref(&p);
+        }
+
+        dav1d_close(&mDav1dCtx);
+        mDav1dCtx = nullptr;
+        mOutputBufferIndex = 0;
+        mInputBufferIndex = 0;
+    }
+#ifdef FILE_DUMP_ENABLE
+    if (mInDataFile != nullptr) {
+        fclose(mInDataFile);
+        mInDataFile = nullptr;
+    }
+
+    if (mInSizeFile != nullptr) {
+        fclose(mInSizeFile);
+        mInSizeFile = nullptr;
+    }
+
+    if (mDav1dOutYuvFile != nullptr) {
+        fclose(mDav1dOutYuvFile);
+        mDav1dOutYuvFile = nullptr;
+    }
+#endif
+}
+
+void fillEmptyWork(const std::unique_ptr<C2Work>& work) {
+    uint32_t flags = 0;
+    if (work->input.flags & C2FrameData::FLAG_END_OF_STREAM) {
+        flags |= C2FrameData::FLAG_END_OF_STREAM;
+        ALOGV("signalling end_of_stream.");
+    }
+    work->worklets.front()->output.flags = (C2FrameData::flags_t)flags;
+    work->worklets.front()->output.buffers.clear();
+    work->worklets.front()->output.ordinal = work->input.ordinal;
+    work->workletsProcessed = 1u;
+}
+
+void C2SoftDav1dDec::finishWork(uint64_t index, const std::unique_ptr<C2Work>& work,
+                                const std::shared_ptr<C2GraphicBlock>& block) {
+    std::shared_ptr<C2Buffer> buffer = createGraphicBuffer(block, C2Rect(mWidth, mHeight));
+    {
+        IntfImpl::Lock lock = mIntf->lock();
+        buffer->setInfo(mIntf->getColorAspects_l());
+    }
+    auto fillWork = [buffer, index](const std::unique_ptr<C2Work>& work) {
+        uint32_t flags = 0;
+        if ((work->input.flags & C2FrameData::FLAG_END_OF_STREAM) &&
+            (c2_cntr64_t(index) == work->input.ordinal.frameIndex)) {
+            flags |= C2FrameData::FLAG_END_OF_STREAM;
+            ALOGV("signalling end_of_stream.");
+        }
+        work->worklets.front()->output.flags = (C2FrameData::flags_t)flags;
+        work->worklets.front()->output.buffers.clear();
+        work->worklets.front()->output.buffers.push_back(buffer);
+        work->worklets.front()->output.ordinal = work->input.ordinal;
+        work->workletsProcessed = 1u;
+    };
+    if (work && c2_cntr64_t(index) == work->input.ordinal.frameIndex) {
+        fillWork(work);
+    } else {
+        finish(index, fillWork);
+    }
+}
+
+void C2SoftDav1dDec::process(const std::unique_ptr<C2Work>& work,
+                             const std::shared_ptr<C2BlockPool>& pool) {
+    work->result = C2_OK;
+    work->workletsProcessed = 0u;
+    work->worklets.front()->output.configUpdate.clear();
+    work->worklets.front()->output.flags = work->input.flags;
+    if (mSignalledError || mSignalledOutputEos) {
+        work->result = C2_BAD_VALUE;
+        return;
+    }
+
+    size_t inOffset = 0u;
+    size_t inSize = 0u;
+    C2ReadView rView = mDummyReadView;
+    if (!work->input.buffers.empty()) {
+        rView = work->input.buffers[0]->data().linearBlocks().front().map().get();
+        inSize = rView.capacity();
+        if (inSize && rView.error()) {
+            ALOGE("read view map failed %d", rView.error());
+            work->result = C2_CORRUPTED;
+            return;
+        }
+    }
+
+    bool codecConfig = ((work->input.flags & C2FrameData::FLAG_CODEC_CONFIG) != 0);
+    bool end_of_stream = ((work->input.flags & C2FrameData::FLAG_END_OF_STREAM) != 0);
+
+    if (codecConfig) {
+        fillEmptyWork(work);
+        return;
+    }
+
+    int64_t in_frameIndex = work->input.ordinal.frameIndex.peekll();
+    if (inSize) {
+        mInputBufferIndex = in_frameIndex;
+
+        uint8_t* bitstream = const_cast<uint8_t*>(rView.data() + inOffset);
+
+        mTimeStart = systemTime();
+        nsecs_t delay = mTimeStart - mTimeEnd;
+
+        // Send the bitstream data (inputBuffer) to dav1d.
+        if (mDav1dCtx) {
+            int i_ret = 0;
+
+            Dav1dSequenceHeader seq;
+            int res = dav1d_parse_sequence_header(&seq, bitstream, inSize);
+            if (res == 0) {
+                ALOGV("dav1d found a sequenceHeader (%dx%d) for in_frameIndex=%ld.", seq.max_width,
+                      seq.max_height, (long)in_frameIndex);
+            }
+
+            // insert OBU TD if it is not present.
+            // TODO: b/286852962
+            uint8_t obu_type = (bitstream[0] >> 3) & 0xf;
+            Dav1dData data;
+
+            uint8_t* ptr = (obu_type == DAV1D_OBU_TD) ? dav1d_data_create(&data, inSize)
+                                                      : dav1d_data_create(&data, inSize + 2);
+            if (ptr == nullptr) {
+                ALOGE("dav1d_data_create failed!");
+                i_ret = -1;
+
+            } else {
+                data.m.timestamp = in_frameIndex;
+
+                int new_Size;
+                if (obu_type != DAV1D_OBU_TD) {
+                    new_Size = (int)(inSize + 2);
+
+                    // OBU TD
+                    ptr[0] = 0x12;
+                    ptr[1] = 0;
+
+                    memcpy(ptr + 2, bitstream, inSize);
+                } else {
+                    new_Size = (int)(inSize);
+                    // TODO: b/277797541 - investigate how to wrap this pointer in Dav1dData to
+                    // avoid memcopy operations.
+                    memcpy(ptr, bitstream, new_Size);
+                }
+
+                // ALOGV("memcpy(ptr,bitstream,inSize=%ld,new_Size=%d,in_frameIndex=%ld,timestamp=%ld,"
+                //       "ptr[0,1,2,3,4]=%x,%x,%x,%x,%x)",
+                //       inSize, new_Size, frameIndex, data.m.timestamp, ptr[0], ptr[1], ptr[2],
+                //       ptr[3], ptr[4]);
+
+                // Dump the bitstream data (inputBuffer) if dumping is enabled.
+#ifdef FILE_DUMP_ENABLE
+                if (mInDataFile) {
+                    int ret = fwrite(ptr, 1, new_Size, mInDataFile);
+
+                    if (ret != new_Size) {
+                        ALOGE("Error in fwrite %s, requested %d, returned %d", mInDataFileName,
+                              new_Size, ret);
+                    }
+                }
+
+                // Dump the size per inputBuffer if dumping is enabled.
+                if (mInSizeFile) {
+                    int ret = fwrite(&new_Size, 1, 4, mInSizeFile);
+
+                    if (ret != 4) {
+                        ALOGE("Error in fwrite %s, requested %d, returned %d", mInSizeFileName, 4,
+                              ret);
+                    }
+                }
+#endif
+
+                bool b_draining = false;
+                int res;
+
+                do {
+                    res = dav1d_send_data(mDav1dCtx, &data);
+                    if (res < 0 && res != DAV1D_ERR(EAGAIN)) {
+                        ALOGE("Decoder feed error %s!", strerror(DAV1D_ERR(res)));
+                        /* bitstream decoding errors (typically DAV1D_ERR(EINVAL), are assumed
+                         * to be recoverable. Other errors returned from this function are
+                         * either unexpected, or considered critical failures.
+                         */
+                        i_ret = res == DAV1D_ERR(EINVAL) ? 0 : -1;
+                        break;
+                    }
+
+                    bool b_output_error = false;
+
+                    do {
+                        Dav1dPicture img;
+                        memset(&img, 0, sizeof(img));
+
+                        res = dav1d_get_picture(mDav1dCtx, &img);
+                        if (res == 0) {
+                            mDecodedPictures.push_back(img);
+
+                            if (!end_of_stream) break;
+                        } else if (res == DAV1D_ERR(EAGAIN)) {
+                            /* the decoder needs more data to be able to output something.
+                             * if there is more data pending, continue the loop below or
+                             * otherwise break */
+                            if (data.sz != 0) res = 0;
+                            break;
+                        } else {
+                            ALOGE("warning! Decoder error %d!", res);
+                            b_output_error = true;
+                            break;
+                        }
+                    } while (res == 0);
+
+                    if (b_output_error) break;
+
+                    /* on drain, we must ignore the 1st EAGAIN */
+                    if (!b_draining && (res == DAV1D_ERR(EAGAIN) || res == 0) &&
+                        (end_of_stream)) {
+                        b_draining = true;
+                        res = 0;
+                    }
+                } while (res == 0 && ((data.sz != 0) || b_draining));
+
+                if (data.sz > 0) {
+                    ALOGE("unexpected data.sz=%zu after dav1d_send_data", data.sz);
+                    dav1d_data_unref(&data);
+                }
+            }
+
+            mTimeEnd = systemTime();
+            nsecs_t decodeTime = mTimeEnd - mTimeStart;
+            // ALOGV("decodeTime=%4" PRId64 " delay=%4" PRId64 "\n", decodeTime, delay);
+
+            if (i_ret != 0) {
+                ALOGE("av1 decoder failed to decode frame. status: %d.", i_ret);
+                work->result = C2_CORRUPTED;
+                work->workletsProcessed = 1u;
+                mSignalledError = true;
+                return;
+            }
+        }
+    }
+
+    (void)outputBuffer(pool, work);
+
+    if (end_of_stream) {
+        drainInternal(DRAIN_COMPONENT_WITH_EOS, pool, work);
+        mSignalledOutputEos = true;
+    } else if (!inSize) {
+        fillEmptyWork(work);
+    }
+}
+
+void C2SoftDav1dDec::getHDRStaticParams(Dav1dPicture* picture,
+                                        const std::unique_ptr<C2Work>& work) {
+    C2StreamHdrStaticMetadataInfo::output hdrStaticMetadataInfo{};
+    bool infoPresent = false;
+
+    if (picture != nullptr) {
+        if (picture->mastering_display != nullptr) {
+            hdrStaticMetadataInfo.mastering.red.x =
+                    picture->mastering_display->primaries[0][0] / 65536.0;
+            hdrStaticMetadataInfo.mastering.red.y =
+                    picture->mastering_display->primaries[0][1] / 65536.0;
+
+            hdrStaticMetadataInfo.mastering.green.x =
+                    picture->mastering_display->primaries[1][0] / 65536.0;
+            hdrStaticMetadataInfo.mastering.green.y =
+                    picture->mastering_display->primaries[1][1] / 65536.0;
+
+            hdrStaticMetadataInfo.mastering.blue.x =
+                    picture->mastering_display->primaries[2][0] / 65536.0;
+            hdrStaticMetadataInfo.mastering.blue.y =
+                    picture->mastering_display->primaries[2][1] / 65536.0;
+
+            hdrStaticMetadataInfo.mastering.white.x =
+                    picture->mastering_display->white_point[0] / 65536.0;
+            hdrStaticMetadataInfo.mastering.white.y =
+                    picture->mastering_display->white_point[1] / 65536.0;
+
+            hdrStaticMetadataInfo.mastering.maxLuminance =
+                    picture->mastering_display->max_luminance / 256.0;
+            hdrStaticMetadataInfo.mastering.minLuminance =
+                    picture->mastering_display->min_luminance / 16384.0;
+
+            infoPresent = true;
+        }
+
+        if (picture->content_light != nullptr) {
+            hdrStaticMetadataInfo.maxCll = picture->content_light->max_content_light_level;
+            hdrStaticMetadataInfo.maxFall = picture->content_light->max_frame_average_light_level;
+            infoPresent = true;
+        }
+    }
+
+    // if (infoPresent) {
+    //   ALOGD("received a hdrStaticMetadataInfo (mastering.red=%f,%f mastering.green=%f,%f
+    //   mastering.blue=%f,%f mastering.white=%f,%f mastering.maxLuminance=%f
+    //   mastering.minLuminance=%f maxCll=%f maxFall=%f) at mOutputBufferIndex=%d.",
+    //   hdrStaticMetadataInfo.mastering.red.x,hdrStaticMetadataInfo.mastering.red.y,
+    //   hdrStaticMetadataInfo.mastering.green.x,hdrStaticMetadataInfo.mastering.green.y,
+    //   hdrStaticMetadataInfo.mastering.blue.x,hdrStaticMetadataInfo.mastering.blue.y,
+    //   hdrStaticMetadataInfo.mastering.white.x,hdrStaticMetadataInfo.mastering.white.y,
+    //   hdrStaticMetadataInfo.mastering.maxLuminance,hdrStaticMetadataInfo.mastering.minLuminance,
+    //   hdrStaticMetadataInfo.maxCll,
+    //   hdrStaticMetadataInfo.maxFall,
+    //   mOutputBufferIndex);
+    // }
+
+    // config if static info has changed
+    if (infoPresent && !(hdrStaticMetadataInfo == mHdrStaticMetadataInfo)) {
+        mHdrStaticMetadataInfo = hdrStaticMetadataInfo;
+        work->worklets.front()->output.configUpdate.push_back(
+                C2Param::Copy(mHdrStaticMetadataInfo));
+    }
+}
+
+void C2SoftDav1dDec::getHDR10PlusInfoData(Dav1dPicture* picture,
+                                          const std::unique_ptr<C2Work>& work) {
+    if (picture != nullptr) {
+        if (picture->itut_t35 != nullptr) {
+            std::vector<uint8_t> payload;
+            size_t payloadSize = picture->itut_t35->payload_size;
+            if (payloadSize > 0) {
+                payload.push_back(picture->itut_t35->country_code);
+                if (picture->itut_t35->country_code == 0xFF) {
+                    payload.push_back(picture->itut_t35->country_code_extension_byte);
+                }
+                payload.insert(payload.end(), picture->itut_t35->payload,
+                               picture->itut_t35->payload + picture->itut_t35->payload_size);
+            }
+
+            std::unique_ptr<C2StreamHdr10PlusInfo::output> hdr10PlusInfo =
+                    C2StreamHdr10PlusInfo::output::AllocUnique(payload.size());
+            if (!hdr10PlusInfo) {
+                ALOGE("Hdr10PlusInfo allocation failed");
+                mSignalledError = true;
+                work->result = C2_NO_MEMORY;
+                return;
+            }
+            memcpy(hdr10PlusInfo->m.value, payload.data(), payload.size());
+
+            // ALOGD("Received a hdr10PlusInfo from picture->itut_t32
+            // (payload_size=%ld,country_code=%d) at mOutputBufferIndex=%d.",
+            // picture->itut_t35->payload_size,
+            // picture->itut_t35->country_code,
+            // mOutputBufferIndex);
+
+            // config if hdr10Plus info has changed
+            if (nullptr == mHdr10PlusInfo || !(*hdr10PlusInfo == *mHdr10PlusInfo)) {
+                mHdr10PlusInfo = std::move(hdr10PlusInfo);
+                work->worklets.front()->output.configUpdate.push_back(std::move(mHdr10PlusInfo));
+            }
+        }
+    }
+}
+
+void C2SoftDav1dDec::getVuiParams(Dav1dPicture* picture) {
+    VuiColorAspects vuiColorAspects;
+
+    if (picture) {
+        vuiColorAspects.primaries = picture->seq_hdr->pri;
+        vuiColorAspects.transfer = picture->seq_hdr->trc;
+        vuiColorAspects.coeffs = picture->seq_hdr->mtrx;
+        vuiColorAspects.fullRange = picture->seq_hdr->color_range;
+
+        // ALOGD("Received a vuiColorAspects from dav1d
+        //       (primaries = % d, transfer = % d, coeffs = % d, fullRange = % d)
+        //               at mOutputBufferIndex = % d,
+        //       out_frameIndex = % ld.",
+        //                          vuiColorAspects.primaries,
+        //       vuiColorAspects.transfer, vuiColorAspects.coeffs, vuiColorAspects.fullRange,
+        //       mOutputBufferIndex, picture->m.timestamp);
+    }
+
+    // convert vui aspects to C2 values if changed
+    if (!(vuiColorAspects == mBitstreamColorAspects)) {
+        mBitstreamColorAspects = vuiColorAspects;
+        ColorAspects sfAspects;
+        C2StreamColorAspectsInfo::input codedAspects = {0u};
+        ColorUtils::convertIsoColorAspectsToCodecAspects(
+                vuiColorAspects.primaries, vuiColorAspects.transfer, vuiColorAspects.coeffs,
+                vuiColorAspects.fullRange, sfAspects);
+        if (!C2Mapper::map(sfAspects.mPrimaries, &codedAspects.primaries)) {
+            codedAspects.primaries = C2Color::PRIMARIES_UNSPECIFIED;
+        }
+        if (!C2Mapper::map(sfAspects.mRange, &codedAspects.range)) {
+            codedAspects.range = C2Color::RANGE_UNSPECIFIED;
+        }
+        if (!C2Mapper::map(sfAspects.mMatrixCoeffs, &codedAspects.matrix)) {
+            codedAspects.matrix = C2Color::MATRIX_UNSPECIFIED;
+        }
+        if (!C2Mapper::map(sfAspects.mTransfer, &codedAspects.transfer)) {
+            codedAspects.transfer = C2Color::TRANSFER_UNSPECIFIED;
+        }
+        std::vector<std::unique_ptr<C2SettingResult>> failures;
+        mIntf->config({&codedAspects}, C2_MAY_BLOCK, &failures);
+    }
+}
+
+void C2SoftDav1dDec::setError(const std::unique_ptr<C2Work>& work, c2_status_t error) {
+    mSignalledError = true;
+    work->result = error;
+    work->workletsProcessed = 1u;
+}
+
+bool C2SoftDav1dDec::allocTmpFrameBuffer(size_t size) {
+    if (size > mTmpFrameBufferSize) {
+        mTmpFrameBuffer = std::make_unique<uint16_t[]>(size);
+        if (mTmpFrameBuffer == nullptr) {
+            mTmpFrameBufferSize = 0;
+            return false;
+        }
+        mTmpFrameBufferSize = size;
+    }
+    return true;
+}
+
+#ifdef FILE_DUMP_ENABLE
+void C2SoftDav1dDec::writeDav1dOutYuvFile(const Dav1dPicture& p) {
+    if (mDav1dOutYuvFile != NULL) {
+        uint8_t* ptr;
+        const int hbd = p.p.bpc > 8;
+
+        ptr = (uint8_t*)p.data[0];
+        for (int y = 0; y < p.p.h; y++) {
+            int iSize = p.p.w << hbd;
+            int ret = fwrite(ptr, 1, iSize, mDav1dOutYuvFile);
+            if (ret != iSize) {
+                ALOGE("Error in fwrite %s, requested %d, returned %d", mDav1dOutYuvFileName, iSize,
+                      ret);
+                break;
+            }
+
+            ptr += p.stride[0];
+        }
+
+        if (p.p.layout != DAV1D_PIXEL_LAYOUT_I400) {
+            // u/v
+            const int ss_ver = p.p.layout == DAV1D_PIXEL_LAYOUT_I420;
+            const int ss_hor = p.p.layout != DAV1D_PIXEL_LAYOUT_I444;
+            const int cw = (p.p.w + ss_hor) >> ss_hor;
+            const int ch = (p.p.h + ss_ver) >> ss_ver;
+            for (int pl = 1; pl <= 2; pl++) {
+                ptr = (uint8_t*)p.data[pl];
+                for (int y = 0; y < ch; y++) {
+                    int iSize = cw << hbd;
+                    int ret = fwrite(ptr, 1, cw << hbd, mDav1dOutYuvFile);
+                    if (ret != iSize) {
+                        ALOGE("Error in fwrite %s, requested %d, returned %d", mDav1dOutYuvFileName,
+                              iSize, ret);
+                        break;
+                    }
+                    ptr += p.stride[1];
+                }
+            }
+        }
+    }
+}
+#endif
+
+bool C2SoftDav1dDec::outputBuffer(const std::shared_ptr<C2BlockPool>& pool,
+                                  const std::unique_ptr<C2Work>& work) {
+    if (!(work && pool)) return false;
+    if (mDav1dCtx == nullptr) return false;
+
+    // Get a decoded picture from dav1d if it is enabled.
+    Dav1dPicture img;
+    memset(&img, 0, sizeof(img));
+
+    int res = 0;
+    if (mDecodedPictures.size() > 0) {
+        img = mDecodedPictures.front();
+        mDecodedPictures.pop_front();
+        // ALOGD("Got a picture(out_frameIndex=%ld,timestamp=%ld) from the deque for
+        // outputBuffer.",img.m.timestamp,img.m.timestamp);
+    } else {
+        res = dav1d_get_picture(mDav1dCtx, &img);
+        if (res == 0) {
+            // ALOGD("Got a picture(out_frameIndex=%ld,timestamp=%ld) from dav1d for
+            // outputBuffer.",img.m.timestamp,img.m.timestamp);
+        } else {
+            ALOGE("failed to get a picture from dav1d for outputBuffer.");
+        }
+    }
+
+    if (res == DAV1D_ERR(EAGAIN)) {
+        ALOGD("Not enough data to output a picture.");
+        return false;
+    }
+    if (res != 0) {
+        ALOGE("The AV1 decoder failed to get a picture (res=%s).", strerror(DAV1D_ERR(res)));
+        return false;
+    }
+
+    const int width = img.p.w;
+    const int height = img.p.h;
+    if (width != mWidth || height != mHeight) {
+        mWidth = width;
+        mHeight = height;
+
+        C2StreamPictureSizeInfo::output size(0u, mWidth, mHeight);
+        std::vector<std::unique_ptr<C2SettingResult>> failures;
+        c2_status_t err = mIntf->config({&size}, C2_MAY_BLOCK, &failures);
+        if (err == C2_OK) {
+            work->worklets.front()->output.configUpdate.push_back(C2Param::Copy(size));
+        } else {
+            ALOGE("Config update size failed");
+            mSignalledError = true;
+            work->result = C2_CORRUPTED;
+            work->workletsProcessed = 1u;
+            return false;
+        }
+    }
+
+    getVuiParams(&img);
+    getHDRStaticParams(&img, work);
+    getHDR10PlusInfoData(&img, work);
+
+    // out_frameIndex that the decoded picture returns from dav1d.
+    int64_t out_frameIndex = img.m.timestamp;
+
+#if LIBYUV_VERSION < 1779
+    if (!(img.p.layout != DAV1D_PIXEL_LAYOUT_I400 || img.p.layout != DAV1D_PIXEL_LAYOUT_I420)) {
+        ALOGE("image_format %d not supported", img.p.layout);
+        mSignalledError = true;
+        work->workletsProcessed = 1u;
+        work->result = C2_CORRUPTED;
+        return false;
+    }
+#endif
+
+    const bool isMonochrome = img.p.layout == DAV1D_PIXEL_LAYOUT_I400;
+
+    int bitdepth = img.p.bpc;
+
+    std::shared_ptr<C2GraphicBlock> block;
+    uint32_t format = HAL_PIXEL_FORMAT_YV12;
+    std::shared_ptr<C2StreamColorAspectsInfo::output> codedColorAspects;
+    if (bitdepth == 10 && mPixelFormatInfo->value != HAL_PIXEL_FORMAT_YCBCR_420_888) {
+        IntfImpl::Lock lock = mIntf->lock();
+        codedColorAspects = mIntf->getColorAspects_l();
+        bool allowRGBA1010102 = false;
+        if (codedColorAspects->primaries == C2Color::PRIMARIES_BT2020 &&
+            codedColorAspects->matrix == C2Color::MATRIX_BT2020 &&
+            codedColorAspects->transfer == C2Color::TRANSFER_ST2084) {
+            allowRGBA1010102 = true;
+        }
+        format = getHalPixelFormatForBitDepth10(allowRGBA1010102);
+#if !HAVE_LIBYUV_I410_I210_TO_AB30
+        if ((format == HAL_PIXEL_FORMAT_RGBA_1010102) &&
+            (is_img_ready ? img.p.layout == DAV1D_PIXEL_LAYOUT_I420
+                          : buffer->image_format != libgav1::kImageFormatYuv420)) {
+            ALOGE("Only YUV420 output is supported when targeting RGBA_1010102");
+            mSignalledError = true;
+            work->result = C2_OMITTED;
+            work->workletsProcessed = 1u;
+            return false;
+        }
+#endif
+    }
+
+    if (mHalPixelFormat != format) {
+        C2StreamPixelFormatInfo::output pixelFormat(0u, format);
+        std::vector<std::unique_ptr<C2SettingResult>> failures;
+        c2_status_t err = mIntf->config({&pixelFormat}, C2_MAY_BLOCK, &failures);
+        if (err == C2_OK) {
+            work->worklets.front()->output.configUpdate.push_back(C2Param::Copy(pixelFormat));
+        } else {
+            ALOGE("Config update pixelFormat failed");
+            mSignalledError = true;
+            work->workletsProcessed = 1u;
+            work->result = C2_CORRUPTED;
+            return UNKNOWN_ERROR;
+        }
+        mHalPixelFormat = format;
+    }
+
+    C2MemoryUsage usage = {C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE};
+
+    // We always create a graphic block that is width aligned to 16 and height
+    // aligned to 2. We set the correct "crop" value of the image in the call to
+    // createGraphicBuffer() by setting the correct image dimensions.
+    c2_status_t err =
+            pool->fetchGraphicBlock(align(mWidth, 16), align(mHeight, 2), format, usage, &block);
+
+    if (err != C2_OK) {
+        ALOGE("fetchGraphicBlock for Output failed with status %d", err);
+        work->result = err;
+        return false;
+    }
+
+    C2GraphicView wView = block->map().get();
+
+    if (wView.error()) {
+        ALOGE("graphic view map failed %d", wView.error());
+        work->result = C2_CORRUPTED;
+        return false;
+    }
+
+    // ALOGV("provided (%dx%d) required (%dx%d), out frameindex %d", block->width(),
+    //       block->height(), mWidth, mHeight, (int)out_frameIndex);
+
+    mOutputBufferIndex = out_frameIndex;
+
+    uint8_t* dstY = const_cast<uint8_t*>(wView.data()[C2PlanarLayout::PLANE_Y]);
+    uint8_t* dstU = const_cast<uint8_t*>(wView.data()[C2PlanarLayout::PLANE_U]);
+    uint8_t* dstV = const_cast<uint8_t*>(wView.data()[C2PlanarLayout::PLANE_V]);
+
+    C2PlanarLayout layout = wView.layout();
+    size_t dstYStride = layout.planes[C2PlanarLayout::PLANE_Y].rowInc;
+    size_t dstUStride = layout.planes[C2PlanarLayout::PLANE_U].rowInc;
+    size_t dstVStride = layout.planes[C2PlanarLayout::PLANE_V].rowInc;
+
+    if (bitdepth == 10) {
+        // TODO: b/277797541 - Investigate if we can ask DAV1D to output the required format during
+        // decompression to avoid color conversion.
+        const uint16_t* srcY = (const uint16_t*)img.data[0];
+        const uint16_t* srcU = (const uint16_t*)img.data[1];
+        const uint16_t* srcV = (const uint16_t*)img.data[2];
+        size_t srcYStride = img.stride[0] / 2;
+        size_t srcUStride = img.stride[1] / 2;
+        size_t srcVStride = img.stride[1] / 2;
+
+        if (format == HAL_PIXEL_FORMAT_RGBA_1010102) {
+            bool processed = false;
+#if HAVE_LIBYUV_I410_I210_TO_AB30
+            if (img.p.layout == DAV1D_PIXEL_LAYOUT_I444) {
+                libyuv::I410ToAB30Matrix(srcY, srcYStride, srcU, srcUStride, srcV, srcVStride, dstY,
+                                         dstYStride, &libyuv::kYuvV2020Constants, mWidth, mHeight);
+                processed = true;
+            } else if (img.p.layout == DAV1D_PIXEL_LAYOUT_I422) {
+                libyuv::I210ToAB30Matrix(srcY, srcYStride, srcU, srcUStride, srcV, srcVStride, dstY,
+                                         dstYStride, &libyuv::kYuvV2020Constants, mWidth, mHeight);
+                processed = true;
+            }
+#endif  // HAVE_LIBYUV_I410_I210_TO_AB30
+            if (!processed) {
+                if (isMonochrome) {
+                    const size_t tmpSize = mWidth;
+                    const bool needFill = tmpSize > mTmpFrameBufferSize;
+                    if (!allocTmpFrameBuffer(tmpSize)) {
+                        ALOGE("Error allocating temp conversion buffer (%zu bytes)", tmpSize);
+                        setError(work, C2_NO_MEMORY);
+                        return false;
+                    }
+                    srcU = srcV = mTmpFrameBuffer.get();
+                    srcUStride = srcVStride = 0;
+                    if (needFill) {
+                        std::fill_n(mTmpFrameBuffer.get(), tmpSize, 512);
+                    }
+                }
+                convertYUV420Planar16ToY410OrRGBA1010102(
+                        (uint32_t*)dstY, srcY, srcU, srcV, srcYStride, srcUStride, srcVStride,
+                        dstYStride / sizeof(uint32_t), mWidth, mHeight,
+                        std::static_pointer_cast<const C2ColorAspectsStruct>(codedColorAspects));
+            }
+        } else if (format == HAL_PIXEL_FORMAT_YCBCR_P010) {
+            dstYStride /= 2;
+            dstUStride /= 2;
+            dstVStride /= 2;
+#if LIBYUV_VERSION >= 1779
+            if ((img.p.layout == DAV1D_PIXEL_LAYOUT_I444) ||
+                (img.p.layout == DAV1D_PIXEL_LAYOUT_I422)) {
+                // TODO(https://crbug.com/libyuv/952): replace this block with libyuv::I410ToP010
+                // and libyuv::I210ToP010 when they are available. Note it may be safe to alias dstY
+                // in I010ToP010, but the libyuv API doesn't make any guarantees.
+                const size_t tmpSize = dstYStride * mHeight + dstUStride * align(mHeight, 2);
+                if (!allocTmpFrameBuffer(tmpSize)) {
+                    ALOGE("Error allocating temp conversion buffer (%zu bytes)", tmpSize);
+                    setError(work, C2_NO_MEMORY);
+                    return false;
+                }
+                uint16_t* const tmpY = mTmpFrameBuffer.get();
+                uint16_t* const tmpU = tmpY + dstYStride * mHeight;
+                uint16_t* const tmpV = tmpU + dstUStride * align(mHeight, 2) / 2;
+                if (img.p.layout == DAV1D_PIXEL_LAYOUT_I444) {
+                    libyuv::I410ToI010(srcY, srcYStride, srcU, srcUStride, srcV, srcVStride, tmpY,
+                                       dstYStride, tmpU, dstUStride, tmpV, dstUStride, mWidth,
+                                       mHeight);
+                } else {
+                    libyuv::I210ToI010(srcY, srcYStride, srcU, srcUStride, srcV, srcVStride, tmpY,
+                                       dstYStride, tmpU, dstUStride, tmpV, dstUStride, mWidth,
+                                       mHeight);
+                }
+                libyuv::I010ToP010(tmpY, dstYStride, tmpU, dstUStride, tmpV, dstVStride,
+                                   (uint16_t*)dstY, dstYStride, (uint16_t*)dstU, dstUStride, mWidth,
+                                   mHeight);
+            } else {
+                convertYUV420Planar16ToP010((uint16_t*)dstY, (uint16_t*)dstU, srcY, srcU, srcV,
+                                            srcYStride, srcUStride, srcVStride, dstYStride,
+                                            dstUStride, mWidth, mHeight, isMonochrome);
+            }
+#else   // LIBYUV_VERSION < 1779
+            convertYUV420Planar16ToP010((uint16_t*)dstY, (uint16_t*)dstU, srcY, srcU, srcV,
+                                        srcYStride, srcUStride, srcVStride, dstYStride, dstUStride,
+                                        mWidth, mHeight, isMonochrome);
+#endif  // LIBYUV_VERSION >= 1779
+        } else {
+#if LIBYUV_VERSION >= 1779
+            if (img.p.layout == DAV1D_PIXEL_LAYOUT_I444) {
+                // TODO(https://crbug.com/libyuv/950): replace this block with libyuv::I410ToI420
+                // when it's available.
+                const size_t tmpSize = dstYStride * mHeight + dstUStride * align(mHeight, 2);
+                if (!allocTmpFrameBuffer(tmpSize)) {
+                    ALOGE("Error allocating temp conversion buffer (%zu bytes)", tmpSize);
+                    setError(work, C2_NO_MEMORY);
+                    return false;
+                }
+                uint16_t* const tmpY = mTmpFrameBuffer.get();
+                uint16_t* const tmpU = tmpY + dstYStride * mHeight;
+                uint16_t* const tmpV = tmpU + dstUStride * align(mHeight, 2) / 2;
+                libyuv::I410ToI010(srcY, srcYStride, srcU, srcUStride, srcV, srcVStride, tmpY,
+                                   dstYStride, tmpU, dstUStride, tmpV, dstVStride, mWidth, mHeight);
+                libyuv::I010ToI420(tmpY, dstYStride, tmpU, dstUStride, tmpV, dstUStride, dstY,
+                                   dstYStride, dstU, dstUStride, dstV, dstVStride, mWidth, mHeight);
+            } else if (img.p.layout == DAV1D_PIXEL_LAYOUT_I422) {
+                libyuv::I210ToI420(srcY, srcYStride, srcU, srcUStride, srcV, srcVStride, dstY,
+                                   dstYStride, dstU, dstUStride, dstV, dstVStride, mWidth, mHeight);
+            } else {
+                convertYUV420Planar16ToYV12(dstY, dstU, dstV, srcY, srcU, srcV, srcYStride,
+                                            srcUStride, srcVStride, dstYStride, dstUStride, mWidth,
+                                            mHeight, isMonochrome);
+            }
+#else   // LIBYUV_VERSION < 1779
+            convertYUV420Planar16ToYV12(dstY, dstU, dstV, srcY, srcU, srcV, srcYStride, srcUStride,
+                                        srcVStride, dstYStride, dstUStride, mWidth, mHeight,
+                                        isMonochrome);
+#endif  // LIBYUV_VERSION >= 1779
+        }
+
+        // Dump the output buffer if dumping is enabled (debug only).
+#ifdef FILE_DUMP_ENABLE
+        FILE* fp_out = mDav1dOutYuvFile;
+
+        // if(mOutputBufferIndex % 100 == 0)
+        ALOGV("output a 10bit picture %dx%d from dav1d "
+              "(mInputBufferIndex=%d,mOutputBufferIndex=%d,format=%d).",
+              mWidth, mHeight, mInputBufferIndex, mOutputBufferIndex, format);
+
+        if (fp_out && mOutputBufferIndex <= num_frames_to_dump) {
+            for (int i = 0; i < mHeight; i++) {
+                int ret = fwrite((uint8_t*)srcY + i * srcYStride * 2, 1, mWidth * 2, fp_out);
+                if (ret != mWidth * 2) {
+                    ALOGE("Error in fwrite, requested %d, returned %d", mWidth * 2, ret);
+                    break;
+                }
+            }
+
+            for (int i = 0; i < mHeight / 2; i++) {
+                int ret = fwrite((uint8_t*)srcU + i * srcUStride * 2, 1, mWidth, fp_out);
+                if (ret != mWidth) {
+                    ALOGE("Error in fwrite, requested %d, returned %d", mWidth, ret);
+                    break;
+                }
+            }
+
+            for (int i = 0; i < mHeight / 2; i++) {
+                int ret = fwrite((uint8_t*)srcV + i * srcVStride * 2, 1, mWidth, fp_out);
+                if (ret != mWidth) {
+                    ALOGE("Error in fwrite, requested %d, returned %d", mWidth, ret);
+                    break;
+                }
+            }
+        }
+#endif
+    } else {
+        const uint8_t* srcY = (const uint8_t*)img.data[0];
+        const uint8_t* srcU = (const uint8_t*)img.data[1];
+        const uint8_t* srcV = (const uint8_t*)img.data[2];
+
+        size_t srcYStride = img.stride[0];
+        size_t srcUStride = img.stride[1];
+        size_t srcVStride = img.stride[1];
+
+        // Dump the output buffer is dumping is enabled (debug only)
+#ifdef FILE_DUMP_ENABLE
+        FILE* fp_out = mDav1dOutYuvFile;
+        // if(mOutputBufferIndex % 100 == 0)
+        ALOGV("output a 8bit picture %dx%d from dav1d "
+              "(mInputBufferIndex=%d,mOutputBufferIndex=%d,format=%d).",
+              mWidth, mHeight, mInputBufferIndex, mOutputBufferIndex, format);
+
+        if (fp_out && mOutputBufferIndex <= num_frames_to_dump) {
+            for (int i = 0; i < mHeight; i++) {
+                int ret = fwrite((uint8_t*)srcY + i * srcYStride, 1, mWidth, fp_out);
+                if (ret != mWidth) {
+                    ALOGE("Error in fwrite, requested %d, returned %d", mWidth, ret);
+                    break;
+                }
+            }
+
+            for (int i = 0; i < mHeight / 2; i++) {
+                int ret = fwrite((uint8_t*)srcU + i * srcUStride, 1, mWidth / 2, fp_out);
+                if (ret != mWidth / 2) {
+                    ALOGE("Error in fwrite, requested %d, returned %d", mWidth / 2, ret);
+                    break;
+                }
+            }
+
+            for (int i = 0; i < mHeight / 2; i++) {
+                int ret = fwrite((uint8_t*)srcV + i * srcVStride, 1, mWidth / 2, fp_out);
+                if (ret != mWidth / 2) {
+                    ALOGE("Error in fwrite, requested %d, returned %d", mWidth / 2, ret);
+                    break;
+                }
+            }
+        }
+#endif
+        if (img.p.layout == DAV1D_PIXEL_LAYOUT_I444) {
+            libyuv::I444ToI420(srcY, srcYStride, srcU, srcUStride, srcV, srcVStride, dstY,
+                               dstYStride, dstU, dstUStride, dstV, dstVStride, mWidth, mHeight);
+        } else if (img.p.layout == DAV1D_PIXEL_LAYOUT_I422) {
+            libyuv::I422ToI420(srcY, srcYStride, srcU, srcUStride, srcV, srcVStride, dstY,
+                               dstYStride, dstU, dstUStride, dstV, dstVStride, mWidth, mHeight);
+        } else {
+            convertYUV420Planar8ToYV12(dstY, dstU, dstV, srcY, srcU, srcV, srcYStride, srcUStride,
+                                       srcVStride, dstYStride, dstUStride, dstVStride, mWidth,
+                                       mHeight, isMonochrome);
+        }
+    }
+
+    dav1d_picture_unref(&img);
+
+    finishWork(out_frameIndex, work, std::move(block));
+    block = nullptr;
+    return true;
+}
+
+c2_status_t C2SoftDav1dDec::drainInternal(uint32_t drainMode,
+                                          const std::shared_ptr<C2BlockPool>& pool,
+                                          const std::unique_ptr<C2Work>& work) {
+    if (drainMode == NO_DRAIN) {
+        ALOGW("drain with NO_DRAIN: no-op");
+        return C2_OK;
+    }
+    if (drainMode == DRAIN_CHAIN) {
+        ALOGW("DRAIN_CHAIN not supported");
+        return C2_OMITTED;
+    }
+
+    while (outputBuffer(pool, work)) {
+    }
+
+    if (drainMode == DRAIN_COMPONENT_WITH_EOS && work && work->workletsProcessed == 0u) {
+        fillEmptyWork(work);
+    }
+
+    return C2_OK;
+}
+
+c2_status_t C2SoftDav1dDec::drain(uint32_t drainMode, const std::shared_ptr<C2BlockPool>& pool) {
+    return drainInternal(drainMode, pool, nullptr);
+}
+
+class C2SoftDav1dFactory : public C2ComponentFactory {
+  public:
+    C2SoftDav1dFactory()
+        : mHelper(std::static_pointer_cast<C2ReflectorHelper>(
+                  GetCodec2PlatformComponentStore()->getParamReflector())) {}
+
+    virtual c2_status_t createComponent(c2_node_id_t id,
+                                        std::shared_ptr<C2Component>* const component,
+                                        std::function<void(C2Component*)> deleter) override {
+        *component = std::shared_ptr<C2Component>(
+                new C2SoftDav1dDec(COMPONENT_NAME, id,
+                                   std::make_shared<C2SoftDav1dDec::IntfImpl>(mHelper)),
+                deleter);
+        return C2_OK;
+    }
+
+    virtual c2_status_t createInterface(
+            c2_node_id_t id, std::shared_ptr<C2ComponentInterface>* const interface,
+            std::function<void(C2ComponentInterface*)> deleter) override {
+        *interface = std::shared_ptr<C2ComponentInterface>(
+                new SimpleInterface<C2SoftDav1dDec::IntfImpl>(
+                        COMPONENT_NAME, id, std::make_shared<C2SoftDav1dDec::IntfImpl>(mHelper)),
+                deleter);
+        return C2_OK;
+    }
+
+    virtual ~C2SoftDav1dFactory() override = default;
+
+  private:
+    std::shared_ptr<C2ReflectorHelper> mHelper;
+};
+
+}  // namespace android
+
+__attribute__((cfi_canonical_jump_table)) extern "C" ::C2ComponentFactory* CreateCodec2Factory() {
+    ALOGV("in %s", __func__);
+    return new ::android::C2SoftDav1dFactory();
+}
+
+__attribute__((cfi_canonical_jump_table)) extern "C" void DestroyCodec2Factory(
+        ::C2ComponentFactory* factory) {
+    ALOGV("in %s", __func__);
+    delete factory;
+}
diff --git a/media/codec2/components/dav1d/C2SoftDav1dDec.h b/media/codec2/components/dav1d/C2SoftDav1dDec.h
new file mode 100644
index 0000000..5201456
--- /dev/null
+++ b/media/codec2/components/dav1d/C2SoftDav1dDec.h
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_C2_SOFT_DAV1D_DEC_H_
+#define ANDROID_C2_SOFT_DAV1D_DEC_H_
+
+#include <inttypes.h>
+
+#include <memory>
+
+#include <media/stagefright/foundation/ColorUtils.h>
+
+#include <C2Config.h>
+#include <SimpleC2Component.h>
+
+#include <dav1d/dav1d.h>
+#include <deque>
+
+//#define FILE_DUMP_ENABLE 1
+#define DUMP_FILE_PATH "/data/local/tmp/dump"
+#define INPUT_DATA_DUMP_EXT "av1"
+#define INPUT_SIZE_DUMP_EXT "size"
+#define OUTPUT_YUV_DUMP_EXT "yuv"
+
+namespace android {
+
+struct C2SoftDav1dDec : public SimpleC2Component {
+    class IntfImpl;
+
+    C2SoftDav1dDec(const char* name, c2_node_id_t id, const std::shared_ptr<IntfImpl>& intfImpl);
+    ~C2SoftDav1dDec();
+
+    // Begin SimpleC2Component overrides.
+    c2_status_t onInit() override;
+    c2_status_t onStop() override;
+    void onReset() override;
+    void onRelease() override;
+    c2_status_t onFlush_sm() override;
+    void process(const std::unique_ptr<C2Work>& work,
+                 const std::shared_ptr<C2BlockPool>& pool) override;
+    c2_status_t drain(uint32_t drainMode, const std::shared_ptr<C2BlockPool>& pool) override;
+    // End SimpleC2Component overrides.
+
+  private:
+    std::shared_ptr<IntfImpl> mIntf;
+
+    int mInputBufferIndex = 0;
+    int mOutputBufferIndex = 0;
+
+    Dav1dContext* mDav1dCtx = nullptr;
+    std::deque<Dav1dPicture> mDecodedPictures;
+
+    // configurations used by component in process
+    // (TODO: keep this in intf but make them internal only)
+    std::shared_ptr<C2StreamPixelFormatInfo::output> mPixelFormatInfo;
+
+    uint32_t mHalPixelFormat;
+    uint32_t mWidth;
+    uint32_t mHeight;
+    bool mSignalledOutputEos;
+    bool mSignalledError;
+    // Used during 10-bit I444/I422 to 10-bit P010 & 8-bit I420 conversions.
+    std::unique_ptr<uint16_t[]> mTmpFrameBuffer;
+    size_t mTmpFrameBufferSize = 0;
+
+    C2StreamHdrStaticMetadataInfo::output mHdrStaticMetadataInfo;
+    std::unique_ptr<C2StreamHdr10PlusInfo::output> mHdr10PlusInfo = nullptr;
+
+    // Color aspects. These are ISO values and are meant to detect changes in aspects to avoid
+    // converting them to C2 values for each frame
+    struct VuiColorAspects {
+        uint8_t primaries;
+        uint8_t transfer;
+        uint8_t coeffs;
+        uint8_t fullRange;
+
+        // default color aspects
+        VuiColorAspects()
+            : primaries(C2Color::PRIMARIES_UNSPECIFIED),
+              transfer(C2Color::TRANSFER_UNSPECIFIED),
+              coeffs(C2Color::MATRIX_UNSPECIFIED),
+              fullRange(C2Color::RANGE_UNSPECIFIED) {}
+
+        bool operator==(const VuiColorAspects& o) {
+            return primaries == o.primaries && transfer == o.transfer && coeffs == o.coeffs &&
+                   fullRange == o.fullRange;
+        }
+    } mBitstreamColorAspects;
+
+    nsecs_t mTimeStart = 0;  // Time at the start of decode()
+    nsecs_t mTimeEnd = 0;    // Time at the end of decode()
+
+    bool initDecoder();
+    void getHDRStaticParams(Dav1dPicture* picture, const std::unique_ptr<C2Work>& work);
+    void getHDR10PlusInfoData(Dav1dPicture* picture, const std::unique_ptr<C2Work>& work);
+    void getVuiParams(Dav1dPicture* picture);
+    void destroyDecoder();
+    void finishWork(uint64_t index, const std::unique_ptr<C2Work>& work,
+                    const std::shared_ptr<C2GraphicBlock>& block);
+    // Sets |work->result| and mSignalledError. Returns false.
+    void setError(const std::unique_ptr<C2Work>& work, c2_status_t error);
+    bool allocTmpFrameBuffer(size_t size);
+    bool outputBuffer(const std::shared_ptr<C2BlockPool>& pool,
+                      const std::unique_ptr<C2Work>& work);
+
+    c2_status_t drainInternal(uint32_t drainMode, const std::shared_ptr<C2BlockPool>& pool,
+                              const std::unique_ptr<C2Work>& work);
+
+    void flushDav1d();
+
+#ifdef FILE_DUMP_ENABLE
+    char mInDataFileName[256];
+    char mInSizeFileName[256];
+    char mDav1dOutYuvFileName[256];
+
+    FILE* mInDataFile = nullptr;
+    FILE* mInSizeFile = nullptr;
+    FILE* mDav1dOutYuvFile = nullptr;
+
+    void writeDav1dOutYuvFile(const Dav1dPicture& p);
+
+    int num_frames_to_dump = 0;
+#endif
+
+    C2_DO_NOT_COPY(C2SoftDav1dDec);
+};
+
+}  // namespace android
+
+#endif  // ANDROID_C2_SOFT_DAV1D_DEC_H_
diff --git a/media/codec2/components/gav1/C2SoftGav1Dec.cpp b/media/codec2/components/gav1/C2SoftGav1Dec.cpp
index 3e4247b..5f5f05d 100644
--- a/media/codec2/components/gav1/C2SoftGav1Dec.cpp
+++ b/media/codec2/components/gav1/C2SoftGav1Dec.cpp
@@ -752,6 +752,19 @@
     return true;
 }
 
+bool C2SoftGav1Dec::fillMonochromeRow(int value) {
+    const size_t tmpSize = mWidth;
+    const bool needFill = tmpSize > mTmpFrameBufferSize;
+    if (!allocTmpFrameBuffer(tmpSize)) {
+        ALOGE("Error allocating temp conversion buffer (%zu bytes)", tmpSize);
+        return false;
+    }
+    if (needFill) {
+        std::fill_n(mTmpFrameBuffer.get(), tmpSize, value);
+    }
+    return true;
+}
+
 bool C2SoftGav1Dec::outputBuffer(const std::shared_ptr<C2BlockPool> &pool,
                                  const std::unique_ptr<C2Work> &work) {
   if (!(work && pool)) return false;
@@ -773,6 +786,16 @@
     return false;
   }
 
+#if LIBYUV_VERSION < 1871
+  if (buffer->bitdepth > 10) {
+    ALOGE("bitdepth %d is not supported", buffer->bitdepth);
+    mSignalledError = true;
+    work->workletsProcessed = 1u;
+    work->result = C2_CORRUPTED;
+    return false;
+  }
+#endif
+
   const int width = buffer->displayed_width[0];
   const int height = buffer->displayed_height[0];
   if (width != mWidth || height != mHeight) {
@@ -816,7 +839,7 @@
   std::shared_ptr<C2GraphicBlock> block;
   uint32_t format = HAL_PIXEL_FORMAT_YV12;
   std::shared_ptr<C2StreamColorAspectsInfo::output> codedColorAspects;
-  if (buffer->bitdepth == 10 && mPixelFormatInfo->value != HAL_PIXEL_FORMAT_YCBCR_420_888) {
+  if (buffer->bitdepth >= 10 && mPixelFormatInfo->value != HAL_PIXEL_FORMAT_YCBCR_420_888) {
     IntfImpl::Lock lock = mIntf->lock();
     codedColorAspects = mIntf->getColorAspects_l();
     bool allowRGBA1010102 = false;
@@ -828,8 +851,9 @@
     format = getHalPixelFormatForBitDepth10(allowRGBA1010102);
 #if !HAVE_LIBYUV_I410_I210_TO_AB30
     if ((format == HAL_PIXEL_FORMAT_RGBA_1010102) &&
-        (buffer->image_format != libgav1::kImageFormatYuv420)) {
-        ALOGE("Only YUV420 output is supported when targeting RGBA_1010102");
+        (buffer->image_format != libgav1::kImageFormatYuv420) &&
+        (buffer->bitdepth == 10)) {
+        ALOGE("Only YUV420 output is supported for 10-bit when targeting RGBA_1010102");
       mSignalledError = true;
       work->result = C2_OMITTED;
       work->workletsProcessed = 1u;
@@ -837,6 +861,18 @@
     }
 #endif
   }
+  if (buffer->bitdepth == 12 && format == HAL_PIXEL_FORMAT_RGBA_1010102 &&
+      (buffer->image_format == libgav1::kImageFormatYuv422 ||
+       buffer->image_format == libgav1::kImageFormatYuv444)) {
+      // There are no 12-bit color conversion functions from YUV422/YUV444 to
+      // RGBA_1010102. Use 8-bit YV12 in this case.
+      format = HAL_PIXEL_FORMAT_YV12;
+  }
+  if (buffer->bitdepth == 12 && format == HAL_PIXEL_FORMAT_YCBCR_P010) {
+      // There are no 12-bit color conversion functions to P010. Use 8-bit YV12
+      // in this case.
+      format = HAL_PIXEL_FORMAT_YV12;
+  }
 
   if (mHalPixelFormat != format) {
     C2StreamPixelFormatInfo::output pixelFormat(0u, format);
@@ -890,7 +926,41 @@
   size_t dstUStride = layout.planes[C2PlanarLayout::PLANE_U].rowInc;
   size_t dstVStride = layout.planes[C2PlanarLayout::PLANE_V].rowInc;
 
-  if (buffer->bitdepth == 10) {
+  if (buffer->bitdepth == 12) {
+#if LIBYUV_VERSION >= 1871
+      const uint16_t *srcY = (const uint16_t *)buffer->plane[0];
+      const uint16_t *srcU = (const uint16_t *)buffer->plane[1];
+      const uint16_t *srcV = (const uint16_t *)buffer->plane[2];
+      size_t srcYStride = buffer->stride[0] / 2;
+      size_t srcUStride = buffer->stride[1] / 2;
+      size_t srcVStride = buffer->stride[2] / 2;
+      if (isMonochrome) {
+          if (!fillMonochromeRow(2048)) {
+              setError(work, C2_NO_MEMORY);
+              return false;
+          }
+          srcU = srcV = mTmpFrameBuffer.get();
+          srcUStride = srcVStride = 0;
+      }
+      if (format == HAL_PIXEL_FORMAT_RGBA_1010102) {
+          libyuv::I012ToAB30Matrix(srcY, srcYStride, srcU, srcUStride, srcV, srcVStride,
+                                   dstY, dstYStride, &libyuv::kYuvV2020Constants,
+                                   mWidth, mHeight);
+      } else if (isMonochrome || buffer->image_format == libgav1::kImageFormatYuv420) {
+          libyuv::I012ToI420(srcY, srcYStride, srcU, srcUStride, srcV, srcVStride,
+                             dstY, dstYStride, dstU, dstUStride, dstV, dstVStride,
+                             mWidth, mHeight);
+      } else if (buffer->image_format == libgav1::kImageFormatYuv444) {
+          libyuv::I412ToI420(srcY, srcYStride, srcU, srcUStride, srcV, srcVStride,
+                             dstY, dstYStride, dstU, dstUStride, dstV, dstVStride,
+                             mWidth, mHeight);
+      } else {
+          libyuv::I212ToI420(srcY, srcYStride, srcU, srcUStride, srcV, srcVStride,
+                             dstY, dstYStride, dstU, dstUStride, dstV, dstVStride,
+                             mWidth, mHeight);
+      }
+#endif  // LIBYUV_VERSION >= 1871
+  } else if (buffer->bitdepth == 10) {
     const uint16_t *srcY = (const uint16_t *)buffer->plane[0];
     const uint16_t *srcU = (const uint16_t *)buffer->plane[1];
     const uint16_t *srcV = (const uint16_t *)buffer->plane[2];
@@ -915,18 +985,12 @@
 #endif  // HAVE_LIBYUV_I410_I210_TO_AB30
         if (!processed) {
             if (isMonochrome) {
-                const size_t tmpSize = mWidth;
-                const bool needFill = tmpSize > mTmpFrameBufferSize;
-                if (!allocTmpFrameBuffer(tmpSize)) {
-                    ALOGE("Error allocating temp conversion buffer (%zu bytes)", tmpSize);
+                if (!fillMonochromeRow(512)) {
                     setError(work, C2_NO_MEMORY);
                     return false;
                 }
                 srcU = srcV = mTmpFrameBuffer.get();
                 srcUStride = srcVStride = 0;
-                if (needFill) {
-                    std::fill_n(mTmpFrameBuffer.get(), tmpSize, 512);
-                }
             }
             convertYUV420Planar16ToY410OrRGBA1010102(
                     (uint32_t *)dstY, srcY, srcU, srcV, srcYStride,
diff --git a/media/codec2/components/gav1/C2SoftGav1Dec.h b/media/codec2/components/gav1/C2SoftGav1Dec.h
index c3b27ea..0e09fcc 100644
--- a/media/codec2/components/gav1/C2SoftGav1Dec.h
+++ b/media/codec2/components/gav1/C2SoftGav1Dec.h
@@ -105,6 +105,7 @@
   // Sets |work->result| and mSignalledError. Returns false.
   void setError(const std::unique_ptr<C2Work> &work, c2_status_t error);
   bool allocTmpFrameBuffer(size_t size);
+  bool fillMonochromeRow(int value);
   bool outputBuffer(const std::shared_ptr<C2BlockPool>& pool,
                     const std::unique_ptr<C2Work>& work);
   c2_status_t drainInternal(uint32_t drainMode,
diff --git a/media/codec2/vndk/C2AllocatorGralloc.cpp b/media/codec2/vndk/C2AllocatorGralloc.cpp
index f272499..0803dc3 100644
--- a/media/codec2/vndk/C2AllocatorGralloc.cpp
+++ b/media/codec2/vndk/C2AllocatorGralloc.cpp
@@ -23,6 +23,7 @@
 #include <aidl/android/hardware/graphics/common/PlaneLayoutComponentType.h>
 #include <android/hardware/graphics/common/1.2/types.h>
 #include <cutils/native_handle.h>
+#include <drm/drm_fourcc.h>
 #include <gralloctypes/Gralloc4.h>
 #include <hardware/gralloc.h>
 #include <ui/GraphicBufferAllocator.h>
@@ -478,7 +479,25 @@
     // 'NATIVE' on Android means LITTLE_ENDIAN
     constexpr C2PlaneInfo::endianness_t kEndianness = C2PlaneInfo::NATIVE;
 
-    switch (mFormat) {
+    // Try to resolve IMPLEMENTATION_DEFINED format to accurate format if
+    // possible.
+    uint32_t format = mFormat;
+    uint32_t fourCc;
+    if (format == HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED &&
+        !GraphicBufferMapper::get().getPixelFormatFourCC(mBuffer, &fourCc)) {
+        switch (fourCc)  {
+            case DRM_FORMAT_XBGR8888:
+                 format = static_cast<uint32_t>(PixelFormat4::RGBX_8888);
+                 break;
+            case DRM_FORMAT_ABGR8888:
+                 format = static_cast<uint32_t>(PixelFormat4::RGBA_8888);
+                 break;
+            default:
+                 break;
+        }
+    }
+
+    switch (format) {
         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
diff --git a/media/libaaudio/src/client/AAudioFlowGraph.cpp b/media/libaaudio/src/client/AAudioFlowGraph.cpp
index 5444565..b7e0ae6 100644
--- a/media/libaaudio/src/client/AAudioFlowGraph.cpp
+++ b/media/libaaudio/src/client/AAudioFlowGraph.cpp
@@ -39,18 +39,21 @@
 
 aaudio_result_t AAudioFlowGraph::configure(audio_format_t sourceFormat,
                           int32_t sourceChannelCount,
+                          int32_t sourceSampleRate,
                           audio_format_t sinkFormat,
                           int32_t sinkChannelCount,
+                          int32_t sinkSampleRate,
                           bool useMonoBlend,
+                          bool useVolumeRamps,
                           float audioBalance,
-                          bool isExclusive) {
+                          aaudio::resampler::MultiChannelResampler::Quality resamplerQuality) {
     FlowGraphPortFloatOutput *lastOutput = nullptr;
 
-    // TODO change back to ALOGD
-    ALOGI("%s() source format = 0x%08x, channels = %d, sink format = 0x%08x, channels = %d, "
-          "useMonoBlend = %d, audioBalance = %f, isExclusive %d",
-          __func__, sourceFormat, sourceChannelCount, sinkFormat, sinkChannelCount,
-          useMonoBlend, audioBalance, isExclusive);
+    ALOGD("%s() source format = 0x%08x, channels = %d, sample rate = %d, "
+          "sink format = 0x%08x, channels = %d, sample rate = %d, "
+          "useMonoBlend = %d, audioBalance = %f, useVolumeRamps %d",
+          __func__, sourceFormat, sourceChannelCount, sourceSampleRate, sinkFormat,
+          sinkChannelCount, sinkSampleRate, useMonoBlend, audioBalance, useVolumeRamps);
 
     switch (sourceFormat) {
         case AUDIO_FORMAT_PCM_FLOAT:
@@ -85,6 +88,15 @@
         lastOutput = &mLimiter->output;
     }
 
+    if (sourceSampleRate != sinkSampleRate) {
+        mResampler.reset(aaudio::resampler::MultiChannelResampler::make(sourceChannelCount,
+                sourceSampleRate, sinkSampleRate, resamplerQuality));
+        mRateConverter = std::make_unique<SampleRateConverter>(sourceChannelCount,
+                                                               *mResampler);
+        lastOutput->connect(&mRateConverter->input);
+        lastOutput = &mRateConverter->output;
+    }
+
     // Expand the number of channels if required.
     if (sourceChannelCount == 1 && sinkChannelCount > 1) {
         mChannelConverter = std::make_unique<MonoToMultiConverter>(sinkChannelCount);
@@ -95,8 +107,7 @@
         return AAUDIO_ERROR_UNIMPLEMENTED;
     }
 
-    // Apply volume ramps for only exclusive streams.
-    if (isExclusive) {
+    if (useVolumeRamps) {
         // Apply volume ramps to set the left/right audio balance and target volumes.
         // The signals will be decoupled, volume ramps will be applied, before the signals are
         // combined again.
@@ -137,9 +148,14 @@
     return AAUDIO_OK;
 }
 
-void AAudioFlowGraph::process(const void *source, void *destination, int32_t numFrames) {
-    mSource->setData(source, numFrames);
-    mSink->read(destination, numFrames);
+int32_t AAudioFlowGraph::pull(void *destination, int32_t targetFramesToRead) {
+    return mSink->read(destination, targetFramesToRead);
+}
+
+int32_t AAudioFlowGraph::process(const void *source, int32_t numFramesToWrite, void *destination,
+                    int32_t targetFramesToRead) {
+    mSource->setData(source, numFramesToWrite);
+    return mSink->read(destination, targetFramesToRead);
 }
 
 /**
diff --git a/media/libaaudio/src/client/AAudioFlowGraph.h b/media/libaaudio/src/client/AAudioFlowGraph.h
index 35fef37..e1d517e 100644
--- a/media/libaaudio/src/client/AAudioFlowGraph.h
+++ b/media/libaaudio/src/client/AAudioFlowGraph.h
@@ -30,6 +30,7 @@
 #include <flowgraph/MonoToMultiConverter.h>
 #include <flowgraph/MultiToManyConverter.h>
 #include <flowgraph/RampLinear.h>
+#include <flowgraph/SampleRateConverter.h>
 
 class AAudioFlowGraph {
 public:
@@ -38,23 +39,57 @@
      *
      * @param sourceFormat
      * @param sourceChannelCount
+     * @param sourceSampleRate
      * @param sinkFormat
      * @param sinkChannelCount
+     * @param sinkSampleRate
      * @param useMonoBlend
+     * @param useVolumeRamps
      * @param audioBalance
-     * @param channelMask
-     * @param isExclusive
+     * @param resamplerQuality
      * @return
      */
     aaudio_result_t configure(audio_format_t sourceFormat,
                               int32_t sourceChannelCount,
+                              int32_t sourceSampleRate,
                               audio_format_t sinkFormat,
                               int32_t sinkChannelCount,
+                              int32_t sinkSampleRate,
                               bool useMonoBlend,
+                              bool useVolumeRamps,
                               float audioBalance,
-                              bool isExclusive);
+                              aaudio::resampler::MultiChannelResampler::Quality resamplerQuality);
 
-    void process(const void *source, void *destination, int32_t numFrames);
+    /**
+     * Attempt to read targetFramesToRead from the flowgraph.
+     * This function returns the number of frames actually read.
+     *
+     * This function does nothing if process() was not called before.
+     *
+     * @param destination
+     * @param targetFramesToRead
+     * @return numFramesRead
+     */
+    int32_t pull(void *destination, int32_t targetFramesToRead);
+
+    /**
+     * Set numFramesToWrite frames from the source into the flowgraph.
+     * Then, attempt to read targetFramesToRead from the flowgraph.
+     * This function returns the number of frames actually read.
+     *
+     * There may be data still in the flowgraph if targetFramesToRead is not large enough.
+     * Before calling process() again, pull() must be called until until all the data is consumed.
+     *
+     * TODO: b/289510598 - Calculate the exact number of input frames needed for Y output frames.
+     *
+     * @param source
+     * @param numFramesToWrite
+     * @param destination
+     * @param targetFramesToRead
+     * @return numFramesRead
+     */
+    int32_t process(const void *source, int32_t numFramesToWrite, void *destination,
+                    int32_t targetFramesToRead);
 
     /**
      * @param volume between 0.0 and 1.0
@@ -73,6 +108,8 @@
 
 private:
     std::unique_ptr<FLOWGRAPH_OUTER_NAMESPACE::flowgraph::FlowGraphSourceBuffered> mSource;
+    std::unique_ptr<RESAMPLER_OUTER_NAMESPACE::resampler::MultiChannelResampler> mResampler;
+    std::unique_ptr<FLOWGRAPH_OUTER_NAMESPACE::flowgraph::SampleRateConverter> mRateConverter;
     std::unique_ptr<FLOWGRAPH_OUTER_NAMESPACE::flowgraph::MonoBlend> mMonoBlend;
     std::unique_ptr<FLOWGRAPH_OUTER_NAMESPACE::flowgraph::Limiter> mLimiter;
     std::unique_ptr<FLOWGRAPH_OUTER_NAMESPACE::flowgraph::MonoToMultiConverter> mChannelConverter;
diff --git a/media/libaaudio/src/client/AudioStreamInternal.cpp b/media/libaaudio/src/client/AudioStreamInternal.cpp
index 84c715f..9b1ad72 100644
--- a/media/libaaudio/src/client/AudioStreamInternal.cpp
+++ b/media/libaaudio/src/client/AudioStreamInternal.cpp
@@ -63,6 +63,8 @@
 
 #define LOG_TIMESTAMPS            0
 
+#define ENABLE_SAMPLE_RATE_CONVERTER 1
+
 AudioStreamInternal::AudioStreamInternal(AAudioServiceInterface  &serviceInterface, bool inService)
         : AudioStream()
         , mClockModel()
@@ -132,12 +134,6 @@
 
     request.getConfiguration().setBufferCapacity(builder.getBufferCapacity());
 
-    request.getConfiguration().setHardwareSamplesPerFrame(builder.getHardwareSamplesPerFrame());
-    request.getConfiguration().setHardwareSampleRate(builder.getHardwareSampleRate());
-    request.getConfiguration().setHardwareFormat(builder.getHardwareFormat());
-
-    mDeviceChannelCount = getSamplesPerFrame(); // Assume it will be the same. Update if not.
-
     mServiceStreamHandleInfo = mServiceInterface.openStream(request, configurationOutput);
     if (getServiceHandle() < 0
             && (request.getConfiguration().getSamplesPerFrame() == 1
@@ -181,9 +177,6 @@
         setChannelMask(configurationOutput.getChannelMask());
     }
 
-    mDeviceChannelCount = configurationOutput.getSamplesPerFrame();
-
-    setSampleRate(configurationOutput.getSampleRate());
     setDeviceId(configurationOutput.getDeviceId());
     setSessionId(configurationOutput.getSessionId());
     setSharingMode(configurationOutput.getSharingMode());
@@ -194,8 +187,21 @@
     setIsContentSpatialized(configurationOutput.isContentSpatialized());
     setInputPreset(configurationOutput.getInputPreset());
 
+    setDeviceSampleRate(configurationOutput.getSampleRate());
+
+    if (getSampleRate() == AAUDIO_UNSPECIFIED) {
+        setSampleRate(configurationOutput.getSampleRate());
+    }
+
+#if !ENABLE_SAMPLE_RATE_CONVERTER
+    if (getSampleRate() != getDeviceSampleRate()) {
+        goto error;
+    }
+#endif
+
     // Save device format so we can do format conversion and volume scaling together.
     setDeviceFormat(configurationOutput.getFormat());
+    setDeviceSamplesPerFrame(configurationOutput.getSamplesPerFrame());
 
     setHardwareSamplesPerFrame(configurationOutput.getHardwareSamplesPerFrame());
     setHardwareSampleRate(configurationOutput.getHardwareSampleRate());
@@ -233,39 +239,46 @@
 }
 
 aaudio_result_t AudioStreamInternal::configureDataInformation(int32_t callbackFrames) {
-    int32_t framesPerHardwareBurst = mEndpointDescriptor.dataQueueDescriptor.framesPerBurst;
+    int32_t deviceFramesPerBurst = mEndpointDescriptor.dataQueueDescriptor.framesPerBurst;
 
     // Scale up the burst size to meet the minimum equivalent in microseconds.
     // This is to avoid waking the CPU too often when the HW burst is very small
-    // or at high sample rates.
-    int32_t framesPerBurst = framesPerHardwareBurst;
+    // or at high sample rates. The actual number of frames that we call back to
+    // the app with will be 0 < N <= framesPerBurst so round up the division.
+    int32_t framesPerBurst = (static_cast<int64_t>(deviceFramesPerBurst) * getSampleRate() +
+             getDeviceSampleRate() - 1) / getDeviceSampleRate();
     int32_t burstMicros = 0;
     const int32_t burstMinMicros = android::AudioSystem::getAAudioHardwareBurstMinUsec();
     do {
         if (burstMicros > 0) {  // skip first loop
+            deviceFramesPerBurst *= 2;
             framesPerBurst *= 2;
         }
         burstMicros = framesPerBurst * static_cast<int64_t>(1000000) / getSampleRate();
     } while (burstMicros < burstMinMicros);
     ALOGD("%s() original HW burst = %d, minMicros = %d => SW burst = %d\n",
-          __func__, framesPerHardwareBurst, burstMinMicros, framesPerBurst);
+          __func__, deviceFramesPerBurst, burstMinMicros, framesPerBurst);
 
     // Validate final burst size.
     if (framesPerBurst < MIN_FRAMES_PER_BURST || framesPerBurst > MAX_FRAMES_PER_BURST) {
         ALOGE("%s - framesPerBurst out of range = %d", __func__, framesPerBurst);
         return AAUDIO_ERROR_OUT_OF_RANGE;
     }
+    setDeviceFramesPerBurst(deviceFramesPerBurst);
     setFramesPerBurst(framesPerBurst); // only save good value
 
-    mBufferCapacityInFrames = mEndpointDescriptor.dataQueueDescriptor.capacityInFrames;
+    mDeviceBufferCapacityInFrames = mEndpointDescriptor.dataQueueDescriptor.capacityInFrames;
+
+    mBufferCapacityInFrames = static_cast<int64_t>(mDeviceBufferCapacityInFrames)
+            * getSampleRate() / getDeviceSampleRate();
     if (mBufferCapacityInFrames < getFramesPerBurst()
             || mBufferCapacityInFrames > MAX_BUFFER_CAPACITY_IN_FRAMES) {
         ALOGE("%s - bufferCapacity out of range = %d", __func__, mBufferCapacityInFrames);
         return AAUDIO_ERROR_OUT_OF_RANGE;
     }
 
-    mClockModel.setSampleRate(getSampleRate());
-    mClockModel.setFramesPerBurst(framesPerHardwareBurst);
+    mClockModel.setSampleRate(getDeviceSampleRate());
+    mClockModel.setFramesPerBurst(deviceFramesPerBurst);
 
     if (isDataCallbackSet()) {
         mCallbackFrames = callbackFrames;
@@ -315,7 +328,8 @@
         mTimeOffsetNanos = offsetMicros * AAUDIO_NANOS_PER_MICROSECOND;
     }
 
-    setBufferSize(mBufferCapacityInFrames / 2); // Default buffer size to match Q
+    // Default buffer size to match Q
+    setBufferSize(mBufferCapacityInFrames / 2);
     return AAUDIO_OK;
 }
 
@@ -374,9 +388,9 @@
     // Cache the buffer size which may be from client.
     const int32_t previousBufferSize = mBufferSizeInFrames;
     // Copy all available data from current data queue.
-    uint8_t buffer[getBufferCapacity() * getBytesPerFrame()];
-    android::fifo_frames_t fullFramesAvailable =
-            mAudioEndpoint->read(buffer, getBufferCapacity());
+    uint8_t buffer[getDeviceBufferCapacity() * getBytesPerFrame()];
+    android::fifo_frames_t fullFramesAvailable = mAudioEndpoint->read(buffer,
+            getDeviceBufferCapacity());
     mEndPointParcelable.closeDataFileDescriptor();
     aaudio_result_t result = mServiceInterface.exitStandby(
             mServiceStreamHandleInfo, endpointParcelable);
@@ -408,7 +422,7 @@
         goto exit;
     }
     // Write data from previous data buffer to new endpoint.
-    if (android::fifo_frames_t framesWritten =
+    if (const android::fifo_frames_t framesWritten =
                 mAudioEndpoint->write(buffer, fullFramesAvailable);
             framesWritten != fullFramesAvailable) {
         ALOGW("Some data lost after exiting standby, frames written: %d, "
@@ -448,7 +462,7 @@
         ALOGD("requestStart() but DISCONNECTED");
         return AAUDIO_ERROR_DISCONNECTED;
     }
-    aaudio_stream_state_t originalState = getState();
+    const aaudio_stream_state_t originalState = getState();
     setState(AAUDIO_STREAM_STATE_STARTING);
 
     // Clear any stale timestamps from the previous run.
@@ -605,7 +619,11 @@
     // Generated in server and passed to client. Return latest.
     if (mAtomicInternalTimestamp.isValid()) {
         Timestamp timestamp = mAtomicInternalTimestamp.read();
-        int64_t position = timestamp.getPosition() + mFramesOffsetFromService;
+        // This should not overflow as timestamp.getPosition() should be a position in a buffer and
+        // not the actual timestamp. timestamp.getNanoseconds() below uses the actual timestamp.
+        // At 48000 Hz we can run for over 100 years before overflowing the int64_t.
+        int64_t position = (timestamp.getPosition() + mFramesOffsetFromService) * getSampleRate() /
+                getDeviceSampleRate();
         if (position >= 0) {
             *framePosition = position;
             *timeNanoseconds = timestamp.getNanoseconds();
@@ -889,7 +907,8 @@
         adjustedFrames = maximumSize;
     } else {
         // Round to the next highest burst size.
-        int32_t numBursts = (adjustedFrames + getFramesPerBurst() - 1) / getFramesPerBurst();
+        int32_t numBursts = (static_cast<int64_t>(adjustedFrames) + getFramesPerBurst() - 1) /
+                getFramesPerBurst();
         adjustedFrames = numBursts * getFramesPerBurst();
         // Clip just in case maximumSize is not a multiple of getFramesPerBurst().
         adjustedFrames = std::min(maximumSize, adjustedFrames);
@@ -897,23 +916,32 @@
 
     if (mAudioEndpoint) {
         // Clip against the actual size from the endpoint.
-        int32_t actualFrames = 0;
+        int32_t actualFramesDevice = 0;
+        int32_t maximumFramesDevice = (static_cast<int64_t>(maximumSize) * getDeviceSampleRate()
+                + getSampleRate() - 1) / getSampleRate();
         // 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);
+        mAudioEndpoint->setBufferSizeInFrames(maximumFramesDevice, &actualFramesDevice);
+        int32_t actualFrames = (static_cast<int64_t>(actualFramesDevice) * getSampleRate() +
+                 getDeviceSampleRate() - 1) / getDeviceSampleRate();
         // actualFrames should be <= actual maximum size of endpoint
         adjustedFrames = std::min(actualFrames, adjustedFrames);
     }
 
-    if (adjustedFrames != mBufferSizeInFrames) {
+    const int32_t bufferSizeInFrames = adjustedFrames;
+    const int32_t deviceBufferSizeInFrames = static_cast<int64_t>(bufferSizeInFrames) *
+            getDeviceSampleRate() / getSampleRate();
+
+    if (deviceBufferSizeInFrames != mDeviceBufferSizeInFrames) {
         android::mediametrics::LogItem(mMetricsId)
                 .set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_SETBUFFERSIZE)
-                .set(AMEDIAMETRICS_PROP_BUFFERSIZEFRAMES, adjustedFrames)
+                .set(AMEDIAMETRICS_PROP_BUFFERSIZEFRAMES, deviceBufferSizeInFrames)
                 .set(AMEDIAMETRICS_PROP_UNDERRUN, (int32_t) getXRunCount())
                 .record();
     }
 
-    mBufferSizeInFrames = adjustedFrames;
+    mBufferSizeInFrames = bufferSizeInFrames;
+    mDeviceBufferSizeInFrames = deviceBufferSizeInFrames;
     ALOGV("%s(%d) returns %d", __func__, requestedFrames, adjustedFrames);
     return (aaudio_result_t) adjustedFrames;
 }
@@ -922,10 +950,18 @@
     return mBufferSizeInFrames;
 }
 
+int32_t AudioStreamInternal::getDeviceBufferSize() const {
+    return mDeviceBufferSizeInFrames;
+}
+
 int32_t AudioStreamInternal::getBufferCapacity() const {
     return mBufferCapacityInFrames;
 }
 
+int32_t AudioStreamInternal::getDeviceBufferCapacity() const {
+    return mDeviceBufferCapacityInFrames;
+}
+
 bool AudioStreamInternal::isClockModelInControl() const {
     return isActive() && mAudioEndpoint->isFreeRunning() && mClockModel.isRunning();
 }
diff --git a/media/libaaudio/src/client/AudioStreamInternal.h b/media/libaaudio/src/client/AudioStreamInternal.h
index 9c06121..a5981b1 100644
--- a/media/libaaudio/src/client/AudioStreamInternal.h
+++ b/media/libaaudio/src/client/AudioStreamInternal.h
@@ -22,8 +22,9 @@
 
 #include "binding/AudioEndpointParcelable.h"
 #include "binding/AAudioServiceInterface.h"
-#include "client/IsochronousClockModel.h"
+#include "client/AAudioFlowGraph.h"
 #include "client/AudioEndpoint.h"
+#include "client/IsochronousClockModel.h"
 #include "core/AudioStream.h"
 #include "utility/AudioClock.h"
 
@@ -56,8 +57,12 @@
 
     int32_t getBufferSize() const override;
 
+    int32_t getDeviceBufferSize() const;
+
     int32_t getBufferCapacity() const override;
 
+    int32_t getDeviceBufferCapacity() const override;
+
     int32_t getXRunCount() const override {
         return mXRunCount;
     }
@@ -133,8 +138,6 @@
     // Calculate timeout for an operation involving framesPerOperation.
     int64_t calculateReasonableTimeout(int32_t framesPerOperation);
 
-    int32_t getDeviceChannelCount() const { return mDeviceChannelCount; }
-
     /**
      * @return true if running in audio service, versus in app process
      */
@@ -177,6 +180,8 @@
     int64_t                  mLastFramesWritten = 0;
     int64_t                  mLastFramesRead = 0;
 
+    AAudioFlowGraph          mFlowGraph;
+
 private:
     /*
      * Asynchronous write with data conversion.
@@ -206,13 +211,10 @@
 
     int64_t                  mServiceLatencyNanos = 0;
 
-    // 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                  mDeviceBufferSizeInFrames = 0;
     int32_t                  mBufferCapacityInFrames = 0;
-
+    int32_t                  mDeviceBufferCapacityInFrames = 0;
 
 };
 
diff --git a/media/libaaudio/src/client/AudioStreamInternalCapture.cpp b/media/libaaudio/src/client/AudioStreamInternalCapture.cpp
index f5cc2be..7d7b4ef 100644
--- a/media/libaaudio/src/client/AudioStreamInternalCapture.cpp
+++ b/media/libaaudio/src/client/AudioStreamInternalCapture.cpp
@@ -47,6 +47,27 @@
 
 }
 
+aaudio_result_t AudioStreamInternalCapture::open(const AudioStreamBuilder &builder) {
+    aaudio_result_t result = AudioStreamInternal::open(builder);
+    if (result == AAUDIO_OK) {
+        result = mFlowGraph.configure(getDeviceFormat(),
+                             getDeviceSamplesPerFrame(),
+                             getDeviceSampleRate(),
+                             getFormat(),
+                             getSamplesPerFrame(),
+                             getSampleRate(),
+                             getRequireMonoBlend(),
+                             false /* useVolumeRamps */,
+                             getAudioBalance(),
+                             aaudio::resampler::MultiChannelResampler::Quality::Medium);
+
+        if (result != AAUDIO_OK) {
+            safeReleaseClose();
+        }
+    }
+    return result;
+}
+
 void AudioStreamInternalCapture::advanceClientToMatchServerPosition(int32_t serverMargin) {
     int64_t readCounter = mAudioEndpoint->getDataReadCounter();
     int64_t writeCounter = mAudioEndpoint->getDataWriteCounter() + serverMargin;
@@ -149,7 +170,8 @@
                 // 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() + getFramesPerBurst();
+                const int64_t nextPosition = mAudioEndpoint->getDataReadCounter() +
+                        getDeviceFramesPerBurst();
                 wakeTime = mClockModel.convertPositionToLatestTime(nextPosition);
             }
                 break;
@@ -166,42 +188,73 @@
 
 aaudio_result_t AudioStreamInternalCapture::readNowWithConversion(void *buffer,
                                                                 int32_t numFrames) {
-    // ALOGD("readNowWithConversion(%p, %d)",
-    //              buffer, numFrames);
     WrappingBuffer wrappingBuffer;
-    uint8_t *destination = (uint8_t *) buffer;
-    int32_t framesLeft = numFrames;
+    uint8_t *byteBuffer = (uint8_t *) buffer;
+    int32_t framesLeftInByteBuffer = numFrames;
+
+    if (framesLeftInByteBuffer > 0) {
+        // Pull data from the flowgraph in case there is residual data.
+        const int32_t framesActuallyWrittenToByteBuffer = mFlowGraph.pull(
+                (void *)byteBuffer,
+                framesLeftInByteBuffer);
+
+        const int32_t numBytesActuallyWrittenToByteBuffer =
+                framesActuallyWrittenToByteBuffer * getBytesPerFrame();
+        byteBuffer += numBytesActuallyWrittenToByteBuffer;
+        framesLeftInByteBuffer -= framesActuallyWrittenToByteBuffer;
+    }
 
     mAudioEndpoint->getFullFramesAvailable(&wrappingBuffer);
 
-    // Read data in one or two parts.
-    for (int partIndex = 0; framesLeft > 0 && partIndex < WrappingBuffer::SIZE; partIndex++) {
-        int32_t framesToProcess = framesLeft;
-        const int32_t framesAvailable = wrappingBuffer.numFrames[partIndex];
-        if (framesAvailable <= 0) break;
+    // Write data in one or two parts.
+    int partIndex = 0;
+    int framesReadFromAudioEndpoint = 0;
+    while (framesLeftInByteBuffer > 0 && partIndex < WrappingBuffer::SIZE) {
+        const int32_t totalFramesInWrappingBuffer = wrappingBuffer.numFrames[partIndex];
+        int32_t framesAvailableInWrappingBuffer = totalFramesInWrappingBuffer;
+        uint8_t *currentWrappingBuffer = (uint8_t *) wrappingBuffer.data[partIndex];
 
-        if (framesToProcess > framesAvailable) {
-            framesToProcess = framesAvailable;
+        // Put data from the wrapping buffer into the flowgraph 8 frames at a time.
+        // Continuously pull as much data as possible from the flowgraph into the byte buffer.
+        // The return value of mFlowGraph.process is the number of frames actually pulled.
+        while (framesAvailableInWrappingBuffer > 0 && framesLeftInByteBuffer > 0) {
+            const int32_t framesToReadFromWrappingBuffer = std::min(flowgraph::kDefaultBufferSize,
+                    framesAvailableInWrappingBuffer);
+
+            const int32_t numBytesToReadFromWrappingBuffer = getBytesPerDeviceFrame() *
+                    framesToReadFromWrappingBuffer;
+
+            // If framesActuallyWrittenToByteBuffer < framesLeftInByteBuffer, it is guaranteed
+            // that all the data is pulled. If there is no more space in the byteBuffer, the
+            // remaining data will be pulled in the following readNowWithConversion().
+            const int32_t framesActuallyWrittenToByteBuffer = mFlowGraph.process(
+                    (void *)currentWrappingBuffer,
+                    framesToReadFromWrappingBuffer,
+                    (void *)byteBuffer,
+                    framesLeftInByteBuffer);
+
+            const int32_t numBytesActuallyWrittenToByteBuffer =
+                    framesActuallyWrittenToByteBuffer * getBytesPerFrame();
+            byteBuffer += numBytesActuallyWrittenToByteBuffer;
+            framesLeftInByteBuffer -= framesActuallyWrittenToByteBuffer;
+            currentWrappingBuffer += numBytesToReadFromWrappingBuffer;
+            framesAvailableInWrappingBuffer -= framesToReadFromWrappingBuffer;
+
+            //ALOGD("%s() numBytesActuallyWrittenToByteBuffer %d, framesLeftInByteBuffer %d"
+            //      "framesAvailableInWrappingBuffer %d, framesReadFromAudioEndpoint %d"
+            //      , __func__, numBytesActuallyWrittenToByteBuffer, framesLeftInByteBuffer,
+            //      framesAvailableInWrappingBuffer, framesReadFromAudioEndpoint);
         }
-
-        const int32_t numBytes = getBytesPerFrame() * framesToProcess;
-        const int32_t numSamples = framesToProcess * getSamplesPerFrame();
-
-        const audio_format_t sourceFormat = getDeviceFormat();
-        const audio_format_t destinationFormat = getFormat();
-
-        memcpy_by_audio_format(destination, destinationFormat,
-                wrappingBuffer.data[partIndex], sourceFormat, numSamples);
-
-        destination += numBytes;
-        framesLeft -= framesToProcess;
+        framesReadFromAudioEndpoint += totalFramesInWrappingBuffer -
+                framesAvailableInWrappingBuffer;
+        partIndex++;
     }
 
-    int32_t framesProcessed = numFrames - framesLeft;
-    mAudioEndpoint->advanceReadIndex(framesProcessed);
+    // The audio endpoint should reference the number of frames written to the wrapping buffer.
+    mAudioEndpoint->advanceReadIndex(framesReadFromAudioEndpoint);
 
-    //ALOGD("readNowWithConversion() returns %d", framesProcessed);
-    return framesProcessed;
+    // The internal code should use the number of frames read from the app.
+    return numFrames - framesLeftInByteBuffer;
 }
 
 int64_t AudioStreamInternalCapture::getFramesWritten() {
diff --git a/media/libaaudio/src/client/AudioStreamInternalCapture.h b/media/libaaudio/src/client/AudioStreamInternalCapture.h
index 87017de..10e247d 100644
--- a/media/libaaudio/src/client/AudioStreamInternalCapture.h
+++ b/media/libaaudio/src/client/AudioStreamInternalCapture.h
@@ -32,6 +32,8 @@
                                         bool inService = false);
     virtual ~AudioStreamInternalCapture() = default;
 
+    aaudio_result_t open(const AudioStreamBuilder &builder) override;
+
     aaudio_result_t read(void *buffer,
                          int32_t numFrames,
                          int64_t timeoutNanoseconds) override;
diff --git a/media/libaaudio/src/client/AudioStreamInternalPlay.cpp b/media/libaaudio/src/client/AudioStreamInternalPlay.cpp
index 89dd8ff..ac927ae 100644
--- a/media/libaaudio/src/client/AudioStreamInternalPlay.cpp
+++ b/media/libaaudio/src/client/AudioStreamInternalPlay.cpp
@@ -48,14 +48,18 @@
 
 aaudio_result_t AudioStreamInternalPlay::open(const AudioStreamBuilder &builder) {
     aaudio_result_t result = AudioStreamInternal::open(builder);
+    const bool useVolumeRamps = (getSharingMode() == AAUDIO_SHARING_MODE_EXCLUSIVE);
     if (result == AAUDIO_OK) {
         result = mFlowGraph.configure(getFormat(),
                              getSamplesPerFrame(),
+                             getSampleRate(),
                              getDeviceFormat(),
-                             getDeviceChannelCount(),
+                             getDeviceSamplesPerFrame(),
+                             getDeviceSampleRate(),
                              getRequireMonoBlend(),
+                             useVolumeRamps,
                              getAudioBalance(),
-                             (getSharingMode() == AAUDIO_SHARING_MODE_EXCLUSIVE));
+                             aaudio::resampler::MultiChannelResampler::Quality::Medium);
 
         if (result != AAUDIO_OK) {
             safeReleaseClose();
@@ -186,7 +190,7 @@
     // Sleep if there is too much data in the buffer.
     // Calculate an ideal time to wake up.
     if (wakeTimePtr != nullptr
-            && (mAudioEndpoint->getFullFramesAvailable() >= getBufferSize())) {
+            && (mAudioEndpoint->getFullFramesAvailable() >= getDeviceBufferSize())) {
         // 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();
@@ -206,12 +210,12 @@
                 // If the appBufferSize is smaller than the endpointBufferSize then
                 // we will have room to write data beyond the appBufferSize.
                 // That is a technique used to reduce glitches without adding latency.
-                const int32_t appBufferSize = getBufferSize();
+                const int64_t appBufferSize = getDeviceBufferSize();
                 // The endpoint buffer size is set to the maximum that can be written.
                 // If we use it then we must carve out some room to write data when we wake up.
-                const int32_t endBufferSize = mAudioEndpoint->getBufferSizeInFrames()
-                        - getFramesPerBurst();
-                const int32_t bestBufferSize = std::min(appBufferSize, endBufferSize);
+                const int64_t endBufferSize = mAudioEndpoint->getBufferSizeInFrames()
+                        - getDeviceFramesPerBurst();
+                const int64_t bestBufferSize = std::min(appBufferSize, endBufferSize);
                 int64_t targetReadPosition = mAudioEndpoint->getDataWriteCounter() - bestBufferSize;
                 wakeTime = mClockModel.convertPositionToTime(targetReadPosition);
             }
@@ -232,37 +236,78 @@
                                                             int32_t numFrames) {
     WrappingBuffer wrappingBuffer;
     uint8_t *byteBuffer = (uint8_t *) buffer;
-    int32_t framesLeft = numFrames;
+    int32_t framesLeftInByteBuffer = numFrames;
 
     mAudioEndpoint->getEmptyFramesAvailable(&wrappingBuffer);
 
     // Write data in one or two parts.
     int partIndex = 0;
-    while (framesLeft > 0 && partIndex < WrappingBuffer::SIZE) {
-        int32_t framesToWrite = framesLeft;
-        int32_t framesAvailable = wrappingBuffer.numFrames[partIndex];
-        if (framesAvailable > 0) {
-            if (framesToWrite > framesAvailable) {
-                framesToWrite = framesAvailable;
-            }
+    int framesWrittenToAudioEndpoint = 0;
+    while (framesLeftInByteBuffer > 0 && partIndex < WrappingBuffer::SIZE) {
+        int32_t framesAvailableInWrappingBuffer = wrappingBuffer.numFrames[partIndex];
+        uint8_t *currentWrappingBuffer = (uint8_t *) wrappingBuffer.data[partIndex];
 
-            int32_t numBytes = getBytesPerFrame() * framesToWrite;
+        if (framesAvailableInWrappingBuffer > 0) {
+            // Pull data from the flowgraph in case there is residual data.
+            const int32_t framesActuallyWrittenToWrappingBuffer = mFlowGraph.pull(
+                (void*) currentWrappingBuffer,
+                framesAvailableInWrappingBuffer);
 
-            mFlowGraph.process((void *)byteBuffer,
-                               wrappingBuffer.data[partIndex],
-                               framesToWrite);
+            const int32_t numBytesActuallyWrittenToWrappingBuffer =
+                framesActuallyWrittenToWrappingBuffer * getBytesPerDeviceFrame();
+            currentWrappingBuffer += numBytesActuallyWrittenToWrappingBuffer;
+            framesAvailableInWrappingBuffer -= framesActuallyWrittenToWrappingBuffer;
+            framesWrittenToAudioEndpoint += framesActuallyWrittenToWrappingBuffer;
+        }
 
-            byteBuffer += numBytes;
-            framesLeft -= framesToWrite;
-        } else {
-            break;
+        // Put data from byteBuffer into the flowgraph one buffer (8 frames) at a time.
+        // Continuously pull as much data as possible from the flowgraph into the wrapping buffer.
+        // The return value of mFlowGraph.process is the number of frames actually pulled.
+        while (framesAvailableInWrappingBuffer > 0 && framesLeftInByteBuffer > 0) {
+            const int32_t framesToWriteFromByteBuffer = std::min(flowgraph::kDefaultBufferSize,
+                    framesLeftInByteBuffer);
+
+            const int32_t numBytesToWriteFromByteBuffer = getBytesPerFrame() *
+                    framesToWriteFromByteBuffer;
+
+            //ALOGD("%s() framesLeftInByteBuffer %d, framesAvailableInWrappingBuffer %d"
+            //      "framesToWriteFromByteBuffer %d, numBytesToWriteFromByteBuffer %d"
+            //      , __func__, framesLeftInByteBuffer, framesAvailableInWrappingBuffer,
+            //      framesToWriteFromByteBuffer, numBytesToWriteFromByteBuffer);
+
+            const int32_t framesActuallyWrittenToWrappingBuffer = mFlowGraph.process(
+                    (void *)byteBuffer,
+                    framesToWriteFromByteBuffer,
+                    (void *)currentWrappingBuffer,
+                    framesAvailableInWrappingBuffer);
+
+            byteBuffer += numBytesToWriteFromByteBuffer;
+            framesLeftInByteBuffer -= framesToWriteFromByteBuffer;
+            const int32_t numBytesActuallyWrittenToWrappingBuffer =
+                    framesActuallyWrittenToWrappingBuffer * getBytesPerDeviceFrame();
+            currentWrappingBuffer += numBytesActuallyWrittenToWrappingBuffer;
+            framesAvailableInWrappingBuffer -= framesActuallyWrittenToWrappingBuffer;
+            framesWrittenToAudioEndpoint += framesActuallyWrittenToWrappingBuffer;
+
+            //ALOGD("%s() numBytesActuallyWrittenToWrappingBuffer %d, framesLeftInByteBuffer %d"
+            //      "framesActuallyWrittenToWrappingBuffer %d, numBytesToWriteFromByteBuffer %d"
+            //      "framesWrittenToAudioEndpoint %d"
+            //      , __func__, numBytesActuallyWrittenToWrappingBuffer, framesLeftInByteBuffer,
+            //      framesActuallyWrittenToWrappingBuffer, numBytesToWriteFromByteBuffer,
+            //      framesWrittenToAudioEndpoint);
         }
         partIndex++;
     }
-    int32_t framesWritten = numFrames - framesLeft;
-    mAudioEndpoint->advanceWriteIndex(framesWritten);
+    //ALOGD("%s() framesWrittenToAudioEndpoint %d, numFrames %d"
+    //              "framesLeftInByteBuffer %d"
+    //              , __func__, framesWrittenToAudioEndpoint, numFrames,
+    //              framesLeftInByteBuffer);
 
-    return framesWritten;
+    // The audio endpoint should reference the number of frames written to the wrapping buffer.
+    mAudioEndpoint->advanceWriteIndex(framesWrittenToAudioEndpoint);
+
+    // The internal code should use the number of frames read from the app.
+    return numFrames - framesLeftInByteBuffer;
 }
 
 int64_t AudioStreamInternalPlay::getFramesRead() {
@@ -284,7 +329,6 @@
     return mLastFramesWritten;
 }
 
-
 // Render audio in the application callback and then write the data to the stream.
 void *AudioStreamInternalPlay::callbackLoop() {
     ALOGD("%s() entering >>>>>>>>>>>>>>>", __func__);
diff --git a/media/libaaudio/src/client/AudioStreamInternalPlay.h b/media/libaaudio/src/client/AudioStreamInternalPlay.h
index e761807..b51b5d0 100644
--- a/media/libaaudio/src/client/AudioStreamInternalPlay.h
+++ b/media/libaaudio/src/client/AudioStreamInternalPlay.h
@@ -21,7 +21,6 @@
 #include <aaudio/AAudio.h>
 
 #include "binding/AAudioServiceInterface.h"
-#include "client/AAudioFlowGraph.h"
 #include "client/AudioStreamInternal.h"
 
 using android::sp;
@@ -89,13 +88,11 @@
      * Asynchronous write with data conversion.
      * @param buffer
      * @param numFrames
-     * @return fdrames written or negative error
+     * @return frames written or negative error
      */
     aaudio_result_t writeNowWithConversion(const void *buffer,
                                            int32_t numFrames);
 
-    AAudioFlowGraph          mFlowGraph;
-
 };
 
 } /* namespace aaudio */
diff --git a/media/libaaudio/src/core/AAudioAudio.cpp b/media/libaaudio/src/core/AAudioAudio.cpp
index 8a13a6f..1e27a81 100644
--- a/media/libaaudio/src/core/AAudioAudio.cpp
+++ b/media/libaaudio/src/core/AAudioAudio.cpp
@@ -571,13 +571,15 @@
 AAUDIO_API int64_t AAudioStream_getFramesWritten(AAudioStream* stream)
 {
     AudioStream *audioStream = convertAAudioStreamToAudioStream(stream);
-    return audioStream->getFramesWritten();
+    return audioStream->getFramesWritten() * audioStream->getSampleRate() /
+            audioStream->getDeviceSampleRate();
 }
 
 AAUDIO_API int64_t AAudioStream_getFramesRead(AAudioStream* stream)
 {
     AudioStream *audioStream = convertAAudioStreamToAudioStream(stream);
-    return audioStream->getFramesRead();
+    return audioStream->getFramesRead() * audioStream->getSampleRate() /
+            audioStream->getDeviceSampleRate();
 }
 
 AAUDIO_API aaudio_result_t AAudioStream_getTimestamp(AAudioStream* stream,
diff --git a/media/libaaudio/src/core/AudioStream.cpp b/media/libaaudio/src/core/AudioStream.cpp
index 56ef1e6..e0fd325 100644
--- a/media/libaaudio/src/core/AudioStream.cpp
+++ b/media/libaaudio/src/core/AudioStream.cpp
@@ -134,7 +134,8 @@
             .set(AMEDIAMETRICS_PROP_ENCODINGHARDWARE,
                     android::toString(getHardwareFormat()).c_str())
             .set(AMEDIAMETRICS_PROP_CHANNELCOUNTHARDWARE, (int32_t)getHardwareSamplesPerFrame())
-            .set(AMEDIAMETRICS_PROP_SAMPLERATEHARDWARE, (int32_t)getHardwareSampleRate());
+            .set(AMEDIAMETRICS_PROP_SAMPLERATEHARDWARE, (int32_t)getHardwareSampleRate())
+            .set(AMEDIAMETRICS_PROP_SAMPLERATECLIENT, (int32_t)getSampleRate());
 
         if (getDirection() == AAUDIO_DIRECTION_OUTPUT) {
             item.set(AMEDIAMETRICS_PROP_PLAYERIID, mPlayerBase->getPlayerIId());
diff --git a/media/libaaudio/src/core/AudioStream.h b/media/libaaudio/src/core/AudioStream.h
index 9b4b734..f2f5cac 100644
--- a/media/libaaudio/src/core/AudioStream.h
+++ b/media/libaaudio/src/core/AudioStream.h
@@ -204,10 +204,18 @@
         return mBufferCapacity;
     }
 
+    virtual int32_t getDeviceBufferCapacity() const {
+        return mDeviceBufferCapacity;
+    }
+
     virtual int32_t getFramesPerBurst() const {
         return mFramesPerBurst;
     }
 
+    virtual int32_t getDeviceFramesPerBurst() const {
+        return mDeviceFramesPerBurst;
+    }
+
     virtual int32_t getXRunCount() const {
         return AAUDIO_ERROR_UNIMPLEMENTED;
     }
@@ -224,6 +232,10 @@
         return mSampleRate;
     }
 
+    aaudio_result_t getDeviceSampleRate() const {
+        return mDeviceSampleRate;
+    }
+
     aaudio_result_t getHardwareSampleRate() const {
         return mHardwareSampleRate;
     }
@@ -240,6 +252,10 @@
         return mSamplesPerFrame;
     }
 
+    aaudio_result_t getDeviceSamplesPerFrame() const {
+        return mDeviceSamplesPerFrame;
+    }
+
     aaudio_result_t getHardwareSamplesPerFrame() const {
         return mHardwareSamplesPerFrame;
     }
@@ -322,10 +338,10 @@
     }
 
     /**
-     * This is only valid after setChannelMask() and setDeviceFormat() have been called.
+     * This is only valid after setDeviceSamplesPerFrame() and setDeviceFormat() have been called.
      */
     int32_t getBytesPerDeviceFrame() const {
-        return getSamplesPerFrame() * audio_bytes_per_sample(getDeviceFormat());
+        return getDeviceSamplesPerFrame() * audio_bytes_per_sample(getDeviceFormat());
     }
 
     virtual int64_t getFramesWritten() = 0;
@@ -365,6 +381,11 @@
         mSamplesPerFrame = AAudioConvert_channelMaskToCount(channelMask);
     }
 
+    void setDeviceSamplesPerFrame(int32_t deviceSamplesPerFrame) {
+        mDeviceSamplesPerFrame = deviceSamplesPerFrame;
+    }
+
+
     /**
      * @return true if data callback has been specified
      */
@@ -542,6 +563,11 @@
     }
 
     // This should not be called after the open() call.
+    void setDeviceSampleRate(int32_t deviceSampleRate) {
+        mDeviceSampleRate = deviceSampleRate;
+    }
+
+    // This should not be called after the open() call.
     void setHardwareSampleRate(int32_t hardwareSampleRate) {
         mHardwareSampleRate = hardwareSampleRate;
     }
@@ -552,11 +578,21 @@
     }
 
     // This should not be called after the open() call.
+    void setDeviceFramesPerBurst(int32_t deviceFramesPerBurst) {
+        mDeviceFramesPerBurst = deviceFramesPerBurst;
+    }
+
+    // This should not be called after the open() call.
     void setBufferCapacity(int32_t bufferCapacity) {
         mBufferCapacity = bufferCapacity;
     }
 
     // This should not be called after the open() call.
+    void setDeviceBufferCapacity(int32_t deviceBufferCapacity) {
+        mDeviceBufferCapacity = deviceBufferCapacity;
+    }
+
+    // This should not be called after the open() call.
     void setSharingMode(aaudio_sharing_mode_t sharingMode) {
         mSharingMode = sharingMode;
     }
@@ -721,9 +757,11 @@
 
     // These do not change after open().
     int32_t                     mSamplesPerFrame = AAUDIO_UNSPECIFIED;
+    int32_t                     mDeviceSamplesPerFrame = AAUDIO_UNSPECIFIED;
     int32_t                     mHardwareSamplesPerFrame = AAUDIO_UNSPECIFIED;
     aaudio_channel_mask_t       mChannelMask = AAUDIO_UNSPECIFIED;
     int32_t                     mSampleRate = AAUDIO_UNSPECIFIED;
+    int32_t                     mDeviceSampleRate = AAUDIO_UNSPECIFIED;
     int32_t                     mHardwareSampleRate = AAUDIO_UNSPECIFIED;
     int32_t                     mDeviceId = AAUDIO_UNSPECIFIED;
     aaudio_sharing_mode_t       mSharingMode = AAUDIO_SHARING_MODE_SHARED;
@@ -732,7 +770,9 @@
     audio_format_t              mHardwareFormat = AUDIO_FORMAT_DEFAULT;
     aaudio_performance_mode_t   mPerformanceMode = AAUDIO_PERFORMANCE_MODE_NONE;
     int32_t                     mFramesPerBurst = 0;
+    int32_t                     mDeviceFramesPerBurst = 0;
     int32_t                     mBufferCapacity = 0;
+    int32_t                     mDeviceBufferCapacity = 0;
 
     aaudio_usage_t              mUsage           = AAUDIO_UNSPECIFIED;
     aaudio_content_type_t       mContentType     = AAUDIO_UNSPECIFIED;
diff --git a/media/libaaudio/src/core/VersionExperiment.txt b/media/libaaudio/src/core/VersionExperiment.txt
deleted file mode 100644
index 071239b..0000000
--- a/media/libaaudio/src/core/VersionExperiment.txt
+++ /dev/null
@@ -1,55 +0,0 @@
-
-// TODO Experiment with versioning. This may be removed or changed dramatically.
-// Please ignore for now. Do not review.
-#define OBOE_VERSION_EXPERIMENT  0
-#if OBOE_VERSION_EXPERIMENT
-
-#define OBOE_EARLIEST_SUPPORTED_VERSION  1
-#define OBOE_CURRENT_VERSION  2
-
-typedef struct OboeInterface_s {
-    int32_t size; // do not use size_t because its size can vary
-    int32_t version;
-    int32_t reserved1;
-    void *  reserved2;
-    oboe_result_t (*createStreamBuilder)(OboeStreamBuilder *);
-} OboeInterface_t;
-
-OboeInterface_t s_oboe_template = {
-        .size = sizeof(OboeInterface_t),
-        .version = OBOE_CURRENT_VERSION,
-        .reserved1 = 0,
-        .reserved2 = NULL,
-        .createStreamBuilder = Oboe_createStreamBuilder
-};
-
-oboe_result_t Oboe_Unimplemented(OboeInterface_t *oboe) {
-    (void) oboe;
-    return OBOE_ERROR_UNIMPLEMENTED;
-}
-
-typedef oboe_result_t (*OboeFunction_t)(OboeInterface_t *oboe);
-
-int32_t Oboe_Initialize(OboeInterface_t *oboe, uint32_t flags) {
-    if (oboe->version < OBOE_EARLIEST_SUPPORTED_VERSION) {
-        return OBOE_ERROR_INCOMPATIBLE;
-    }
-    // Fill in callers vector table.
-    uint8_t *start = (uint8_t*)&oboe->reserved1;
-    uint8_t *end;
-    if (oboe->size <= s_oboe_template.size) {
-        end = ((uint8_t *)oboe) + oboe->size;
-    } else {
-        end = ((uint8_t *)oboe) + s_oboe_template.size;
-        // Assume the rest of the structure is vectors.
-        // Point them all to OboeInternal_Unimplemented()
-        // Point to first vector past end of the known structure.
-        OboeFunction_t *next = (OboeFunction_t*)end;
-        while ((((uint8_t *)next) - ((uint8_t *)oboe)) < oboe->size) {
-            *next++ = Oboe_Unimplemented;
-        }
-    }
-    memcpy(&oboe->reserved1, &s_oboe_template.reserved1, end - start);
-    return OBOE_OK;
-}
-#endif /* OBOE_VERSION_EXPERIMENT -------------------------- */
diff --git a/media/libaaudio/src/fifo/FifoControllerBase.cpp b/media/libaaudio/src/fifo/FifoControllerBase.cpp
index ad6d041..e79bf96 100644
--- a/media/libaaudio/src/fifo/FifoControllerBase.cpp
+++ b/media/libaaudio/src/fifo/FifoControllerBase.cpp
@@ -21,7 +21,8 @@
 #include <stdint.h>
 #include "FifoControllerBase.h"
 
-using namespace android;  // TODO just import names needed
+using android::FifoControllerBase;
+using android::fifo_frames_t;
 
 FifoControllerBase::FifoControllerBase(fifo_frames_t capacity, fifo_frames_t threshold)
         : mCapacity(capacity)
diff --git a/media/libaaudio/src/flowgraph/resampler/MultiChannelResampler.cpp b/media/libaaudio/src/flowgraph/resampler/MultiChannelResampler.cpp
index a3ce58c..611ddcd 100644
--- a/media/libaaudio/src/flowgraph/resampler/MultiChannelResampler.cpp
+++ b/media/libaaudio/src/flowgraph/resampler/MultiChannelResampler.cpp
@@ -135,10 +135,9 @@
     int coefficientIndex = 0;
     double phase = 0.0; // ranges from 0.0 to 1.0, fraction between samples
     // Stretch the sinc function for low pass filtering.
-    const float cutoffScaler = normalizedCutoff *
-            ((outputRate < inputRate)
-             ? ((float)outputRate / inputRate)
-             : ((float)inputRate / outputRate));
+    const float cutoffScaler = (outputRate < inputRate)
+             ? (normalizedCutoff * (float)outputRate / inputRate)
+             : 1.0f; // Do not filter when upsampling.
     const int numTapsHalf = getNumTaps() / 2; // numTaps must be even.
     const float numTapsHalfInverse = 1.0f / numTapsHalf;
     for (int i = 0; i < numRows; i++) {
diff --git a/media/libaaudio/src/flowgraph/resampler/MultiChannelResampler.h b/media/libaaudio/src/flowgraph/resampler/MultiChannelResampler.h
index 717f3fd..9e47335 100644
--- a/media/libaaudio/src/flowgraph/resampler/MultiChannelResampler.h
+++ b/media/libaaudio/src/flowgraph/resampler/MultiChannelResampler.h
@@ -111,6 +111,9 @@
          * Set lower to reduce aliasing.
          * Default is 0.70.
          *
+         * Note that this value is ignored when upsampling, which is when
+         * the outputRate is higher than the inputRate.
+         *
          * @param normalizedCutoff anti-aliasing filter cutoff
          * @return address of this builder for chaining calls
          */
@@ -227,6 +230,10 @@
 
     /**
      * Generate the filter coefficients in optimal order.
+     *
+     * Note that normalizedCutoff is ignored when upsampling, which is when
+     * the outputRate is higher than the inputRate.
+     *
      * @param inputRate sample rate of the input stream
      * @param outputRate  sample rate of the output stream
      * @param numRows number of rows in the array that contain a set of tap coefficients
diff --git a/media/libaaudio/src/legacy/AudioStreamRecord.cpp b/media/libaaudio/src/legacy/AudioStreamRecord.cpp
index e760dab..fe4bf2c 100644
--- a/media/libaaudio/src/legacy/AudioStreamRecord.cpp
+++ b/media/libaaudio/src/legacy/AudioStreamRecord.cpp
@@ -208,6 +208,12 @@
     setBufferCapacity(getBufferCapacityFromDevice());
     setFramesPerBurst(getFramesPerBurstFromDevice());
 
+    // Use the same values for device values.
+    setDeviceSamplesPerFrame(getSamplesPerFrame());
+    setDeviceSampleRate(mAudioRecord->getSampleRate());
+    setDeviceBufferCapacity(getBufferCapacityFromDevice());
+    setDeviceFramesPerBurst(getFramesPerBurstFromDevice());
+
     setHardwareSamplesPerFrame(mAudioRecord->getHalChannelCount());
     setHardwareSampleRate(mAudioRecord->getHalSampleRate());
     setHardwareFormat(mAudioRecord->getHalFormat());
diff --git a/media/libaaudio/src/legacy/AudioStreamTrack.cpp b/media/libaaudio/src/legacy/AudioStreamTrack.cpp
index 67ee42e..59fdabc 100644
--- a/media/libaaudio/src/legacy/AudioStreamTrack.cpp
+++ b/media/libaaudio/src/legacy/AudioStreamTrack.cpp
@@ -203,6 +203,12 @@
     setBufferCapacity(getBufferCapacityFromDevice());
     setFramesPerBurst(getFramesPerBurstFromDevice());
 
+    // Use the same values for device values.
+    setDeviceSamplesPerFrame(getSamplesPerFrame());
+    setDeviceSampleRate(mAudioTrack->getSampleRate());
+    setDeviceBufferCapacity(getBufferCapacityFromDevice());
+    setDeviceFramesPerBurst(getFramesPerBurstFromDevice());
+
     setHardwareSamplesPerFrame(mAudioTrack->getHalChannelCount());
     setHardwareSampleRate(mAudioTrack->getHalSampleRate());
     setHardwareFormat(mAudioTrack->getHalFormat());
diff --git a/media/libaaudio/src/utility/AAudioUtilities.cpp b/media/libaaudio/src/utility/AAudioUtilities.cpp
index e8324a8..0cbf79d 100644
--- a/media/libaaudio/src/utility/AAudioUtilities.cpp
+++ b/media/libaaudio/src/utility/AAudioUtilities.cpp
@@ -383,11 +383,10 @@
                 return AUDIO_CHANNEL_OUT_7POINT1POINT2;
             case AAUDIO_CHANNEL_7POINT1POINT4:
                 return AUDIO_CHANNEL_OUT_7POINT1POINT4;
-            // TODO: add 9point1point4 and 9point1point6 when they are added in audio-hal-enums.h
-            // case AAUDIO_CHANNEL_9POINT1POINT4:
-            //     return AUDIO_CHANNEL_OUT_9POINT1POINT4;
-            // case AAUDIO_CHANNEL_9POINT1POINT6:
-            //     return AUDIO_CHANNEL_OUT_9POINT1POINT6;
+            case AAUDIO_CHANNEL_9POINT1POINT4:
+                return AUDIO_CHANNEL_OUT_9POINT1POINT4;
+            case AAUDIO_CHANNEL_9POINT1POINT6:
+                return AUDIO_CHANNEL_OUT_9POINT1POINT6;
             default:
                 ALOGE("%s() %#x unrecognized", __func__, channelMask);
                 return AUDIO_CHANNEL_INVALID;
@@ -465,11 +464,10 @@
                 return AAUDIO_CHANNEL_7POINT1POINT2;
             case AUDIO_CHANNEL_OUT_7POINT1POINT4:
                 return AAUDIO_CHANNEL_7POINT1POINT4;
-            // TODO: add 9point1point4 and 9point1point6 when they are added in audio-hal-enums.h
-            // case AUDIO_CHANNEL_OUT_9POINT1POINT4:
-            //     return AAUDIO_CHANNEL_9POINT1POINT4;
-            // case AUDIO_CHANNEL_OUT_9POINT1POINT6:
-            //     return AAUDIO_CHANNEL_9POINT1POINT6;
+            case AUDIO_CHANNEL_OUT_9POINT1POINT4:
+                return AAUDIO_CHANNEL_9POINT1POINT4;
+            case AUDIO_CHANNEL_OUT_9POINT1POINT6:
+                return AAUDIO_CHANNEL_9POINT1POINT6;
             default:
                 ALOGE("%s() %#x unrecognized", __func__, channelMask);
                 return AAUDIO_CHANNEL_INVALID;
diff --git a/media/libaaudio/src/utility/AudioClock.h b/media/libaaudio/src/utility/AudioClock.h
index d5d4ef4..37f5b39 100644
--- a/media/libaaudio/src/utility/AudioClock.h
+++ b/media/libaaudio/src/utility/AudioClock.h
@@ -33,7 +33,7 @@
 public:
     static int64_t getNanoseconds(clockid_t clockId = CLOCK_MONOTONIC) {
         struct timespec time;
-        int result = clock_gettime(clockId, &time);
+        const int result = clock_gettime(clockId, &time);
         if (result < 0) {
             return -errno;
         }
@@ -56,7 +56,7 @@
             time.tv_sec = nanoTime / AAUDIO_NANOS_PER_SECOND;
             // Calculate the fractional nanoseconds. Avoids expensive % operation.
             time.tv_nsec = nanoTime - (time.tv_sec * AAUDIO_NANOS_PER_SECOND);
-            int err = clock_nanosleep(clockId, TIMER_ABSTIME, &time, nullptr);
+            const int err = clock_nanosleep(clockId, TIMER_ABSTIME, &time, nullptr);
             switch (err) {
             case EINTR:
                 return 1;
@@ -86,7 +86,7 @@
             // Calculate the fractional nanoseconds. Avoids expensive % operation.
             time.tv_nsec = nanoseconds - (time.tv_sec * AAUDIO_NANOS_PER_SECOND);
             const int flags = 0; // documented as relative sleep
-            int err = clock_nanosleep(clockId, flags, &time, nullptr);
+            const int err = clock_nanosleep(clockId, flags, &time, nullptr);
             switch (err) {
             case EINTR:
                 return 1;
diff --git a/media/libaaudio/src/utility/MonotonicCounter.h b/media/libaaudio/src/utility/MonotonicCounter.h
index 51eb69b..b58634f 100644
--- a/media/libaaudio/src/utility/MonotonicCounter.h
+++ b/media/libaaudio/src/utility/MonotonicCounter.h
@@ -104,7 +104,7 @@
      */
     void roundUp64(int32_t period) {
         if (period > 0) {
-            int64_t numPeriods = (mCounter64 + period - 1) / period;
+            const int64_t numPeriods = (mCounter64 + period - 1) / period;
             mCounter64 = numPeriods * period;
         }
     }
diff --git a/media/libaaudio/tests/Android.bp b/media/libaaudio/tests/Android.bp
index 24041bc..0cfdfb2 100644
--- a/media/libaaudio/tests/Android.bp
+++ b/media/libaaudio/tests/Android.bp
@@ -145,6 +145,7 @@
     srcs: ["test_flowgraph.cpp"],
     shared_libs: [
         "libaaudio_internal",
+        "libaudioutils",
         "libbinder",
         "libcutils",
         "libutils",
diff --git a/media/libaaudio/tests/test_flowgraph.cpp b/media/libaaudio/tests/test_flowgraph.cpp
index 6f75f5a..7eb8b0d 100644
--- a/media/libaaudio/tests/test_flowgraph.cpp
+++ b/media/libaaudio/tests/test_flowgraph.cpp
@@ -25,6 +25,8 @@
 
 #include <gtest/gtest.h>
 
+#include <aaudio/AAudio.h>
+#include "client/AAudioFlowGraph.h"
 #include "flowgraph/ClipToRange.h"
 #include "flowgraph/Limiter.h"
 #include "flowgraph/MonoBlend.h"
@@ -37,8 +39,18 @@
 #include "flowgraph/SinkI32.h"
 #include "flowgraph/SourceI16.h"
 #include "flowgraph/SourceI24.h"
+#include "flowgraph/resampler/IntegerRatio.h"
 
 using namespace FLOWGRAPH_OUTER_NAMESPACE::flowgraph;
+using namespace RESAMPLER_OUTER_NAMESPACE::resampler;
+
+using TestFlowgraphResamplerParams = std::tuple<int32_t, int32_t, MultiChannelResampler::Quality>;
+
+enum {
+    PARAM_SOURCE_SAMPLE_RATE = 0,
+    PARAM_SINK_SAMPLE_RATE,
+    PARAM_RESAMPLER_QUALITY
+};
 
 constexpr int kBytesPerI24Packed = 3;
 
@@ -394,3 +406,240 @@
         EXPECT_NEAR(expected[i], output[i], tolerance);
     }
 }
+
+TEST(test_flowgraph, module_sinki16_multiple_reads) {
+    static constexpr int kNumSamples = 8;
+    std::array<int16_t, kNumSamples + 10> output; // larger than input
+
+    SourceFloat sourceFloat{1};
+    SinkI16 sinkI16{1};
+
+    sourceFloat.setData(kInputFloat.data(), kNumSamples);
+    sourceFloat.output.connect(&sinkI16.input);
+
+    output.fill(777);
+
+    // Read the first half of the data
+    int32_t numRead = sinkI16.read(output.data(), kNumSamples / 2);
+    ASSERT_EQ(kNumSamples / 2, numRead);
+    for (int i = 0; i < numRead; i++) {
+        EXPECT_EQ(kExpectedI16.at(i), output.at(i)) << ", i = " << i;
+    }
+
+    // Read the rest of the data
+    numRead = sinkI16.read(output.data(), output.size());
+    ASSERT_EQ(kNumSamples / 2, numRead);
+    for (int i = 0; i < numRead; i++) {
+        EXPECT_EQ(kExpectedI16.at(i + kNumSamples / 2), output.at(i)) << ", i = " << i;
+    }
+}
+
+void checkSampleRateConversionVariedSizes(int32_t sourceSampleRate,
+                    int32_t sinkSampleRate,
+                    MultiChannelResampler::Quality resamplerQuality) {
+    AAudioFlowGraph flowgraph;
+    aaudio_result_t result = flowgraph.configure(AUDIO_FORMAT_PCM_FLOAT /* sourceFormat */,
+            1 /* sourceChannelCount */,
+            sourceSampleRate,
+            AUDIO_FORMAT_PCM_FLOAT /* sinkFormat */,
+            1 /* sinkChannelCount */,
+            sinkSampleRate,
+            false /* useMonoBlend */,
+            false /* useVolumeRamps */,
+            0.0f /* audioBalance */,
+            resamplerQuality);
+
+    IntegerRatio ratio(sourceSampleRate, sinkSampleRate);
+    ratio.reduce();
+
+    ASSERT_EQ(AAUDIO_OK, result);
+
+    const int inputSize = ratio.getNumerator();
+    const int outputSize = ratio.getDenominator();
+    float input[inputSize];
+    float output[outputSize];
+
+    for (int i = 0; i < inputSize; i++) {
+        input[i] = i * 1.0f / inputSize;
+    }
+
+    int inputUsed = 0;
+    int outputRead = 0;
+    int curInputSize = 1;
+
+    // Process the data with larger and larger input buffer sizes.
+    while (inputUsed < inputSize) {
+        outputRead += flowgraph.process((void *) (input + inputUsed),
+                curInputSize,
+                (void *) (output + outputRead),
+                outputSize - outputRead);
+        inputUsed += curInputSize;
+        curInputSize = std::min(curInputSize + 5, inputSize - inputUsed);
+    }
+
+    ASSERT_EQ(outputSize, outputRead);
+
+    for (int i = 1; i < outputSize; i++) {
+        // The first values of the flowgraph will be close to zero.
+        // Besides those, the values should be strictly increasing.
+        if (output[i - 1] > 0.01f) {
+            EXPECT_GT(output[i], output[i - 1]);
+        }
+    }
+}
+
+TEST(test_flowgraph, flowgraph_varied_sizes_all) {
+    const int rates[] = {8000, 11025, 22050, 32000, 44100, 48000, 64000, 88200, 96000};
+    const MultiChannelResampler::Quality qualities[] =
+    {
+        MultiChannelResampler::Quality::Fastest,
+        MultiChannelResampler::Quality::Low,
+        MultiChannelResampler::Quality::Medium,
+        MultiChannelResampler::Quality::High,
+        MultiChannelResampler::Quality::Best
+    };
+    for (int srcRate : rates) {
+        for (int destRate : rates) {
+            for (auto quality : qualities) {
+                if (srcRate != destRate) {
+                    checkSampleRateConversionVariedSizes(srcRate, destRate, quality);
+                }
+            }
+        }
+    }
+}
+
+void checkSampleRateConversionPullLater(int32_t sourceSampleRate,
+                    int32_t sinkSampleRate,
+                    MultiChannelResampler::Quality resamplerQuality) {
+    AAudioFlowGraph flowgraph;
+    aaudio_result_t result = flowgraph.configure(AUDIO_FORMAT_PCM_FLOAT /* sourceFormat */,
+            1 /* sourceChannelCount */,
+            sourceSampleRate,
+            AUDIO_FORMAT_PCM_FLOAT /* sinkFormat */,
+            1 /* sinkChannelCount */,
+            sinkSampleRate,
+            false /* useMonoBlend */,
+            false /* useVolumeRamps */,
+            0.0f /* audioBalance */,
+            resamplerQuality);
+
+    IntegerRatio ratio(sourceSampleRate, sinkSampleRate);
+    ratio.reduce();
+
+    ASSERT_EQ(AAUDIO_OK, result);
+
+    const int inputSize = ratio.getNumerator();
+    const int outputSize = ratio.getDenominator();
+    float input[inputSize];
+    float output[outputSize];
+
+    for (int i = 0; i < inputSize; i++) {
+        input[i] = i * 1.0f / inputSize;
+    }
+
+    // Read half the data with process.
+    int outputRead = flowgraph.process((void *) input,
+            inputSize,
+            (void *) output,
+            outputSize / 2);
+
+    ASSERT_EQ(outputSize / 2, outputRead);
+
+    // Now read the other half of the data with pull.
+    outputRead += flowgraph.pull(
+            (void *) (output + outputRead),
+            outputSize - outputRead);
+
+    ASSERT_EQ(outputSize, outputRead);
+    for (int i = 1; i < outputSize; i++) {
+        // The first values of the flowgraph will be close to zero.
+        // Besides those, the values should be strictly increasing.
+        if (output[i - 1] > 0.01f) {
+            EXPECT_GT(output[i], output[i - 1]);
+        }
+    }
+}
+
+// TODO: b/289508408 - Remove non-parameterized tests if they get noisy.
+TEST(test_flowgraph, flowgraph_pull_later_all) {
+    const int rates[] = {8000, 11025, 22050, 32000, 44100, 48000, 64000, 88200, 96000};
+    const MultiChannelResampler::Quality qualities[] =
+    {
+        MultiChannelResampler::Quality::Fastest,
+        MultiChannelResampler::Quality::Low,
+        MultiChannelResampler::Quality::Medium,
+        MultiChannelResampler::Quality::High,
+        MultiChannelResampler::Quality::Best
+    };
+    for (int srcRate : rates) {
+        for (int destRate : rates) {
+            for (auto quality : qualities) {
+                if (srcRate != destRate) {
+                    checkSampleRateConversionPullLater(srcRate, destRate, quality);
+                }
+            }
+        }
+    }
+}
+
+class TestFlowgraphSampleRateConversion : public ::testing::Test,
+                        public ::testing::WithParamInterface<TestFlowgraphResamplerParams> {
+};
+
+const char* resamplerQualityToString(MultiChannelResampler::Quality quality) {
+    switch (quality) {
+        case MultiChannelResampler::Quality::Fastest: return "FASTEST";
+        case MultiChannelResampler::Quality::Low: return "LOW";
+        case MultiChannelResampler::Quality::Medium: return "MEDIUM";
+        case MultiChannelResampler::Quality::High: return "HIGH";
+        case MultiChannelResampler::Quality::Best: return "BEST";
+    }
+    return "UNKNOWN";
+}
+
+static std::string getTestName(
+        const ::testing::TestParamInfo<TestFlowgraphResamplerParams>& info) {
+    return std::string()
+            + std::to_string(std::get<PARAM_SOURCE_SAMPLE_RATE>(info.param))
+            + "__" + std::to_string(std::get<PARAM_SINK_SAMPLE_RATE>(info.param))
+            + "__" + resamplerQualityToString(std::get<PARAM_RESAMPLER_QUALITY>(info.param));
+}
+
+TEST_P(TestFlowgraphSampleRateConversion, test_flowgraph_pull_later) {
+    checkSampleRateConversionPullLater(std::get<PARAM_SOURCE_SAMPLE_RATE>(GetParam()),
+            std::get<PARAM_SINK_SAMPLE_RATE>(GetParam()),
+            std::get<PARAM_RESAMPLER_QUALITY>(GetParam()));
+}
+
+TEST_P(TestFlowgraphSampleRateConversion, test_flowgraph_varied_sizes) {
+    checkSampleRateConversionVariedSizes(std::get<PARAM_SOURCE_SAMPLE_RATE>(GetParam()),
+            std::get<PARAM_SINK_SAMPLE_RATE>(GetParam()),
+            std::get<PARAM_RESAMPLER_QUALITY>(GetParam()));
+}
+
+INSTANTIATE_TEST_SUITE_P(
+        test_flowgraph,
+        TestFlowgraphSampleRateConversion,
+        ::testing::Values(
+                TestFlowgraphResamplerParams({8000, 11025, MultiChannelResampler::Quality::Best}),
+                TestFlowgraphResamplerParams({8000, 48000, MultiChannelResampler::Quality::Best}),
+                TestFlowgraphResamplerParams({8000, 44100, MultiChannelResampler::Quality::Best}),
+                TestFlowgraphResamplerParams({11025, 24000, MultiChannelResampler::Quality::Best}),
+                TestFlowgraphResamplerParams({11025, 48000,
+                        MultiChannelResampler::Quality::Fastest}),
+                TestFlowgraphResamplerParams({11025, 48000, MultiChannelResampler::Quality::Low}),
+                TestFlowgraphResamplerParams({11025, 48000,
+                        MultiChannelResampler::Quality::Medium}),
+                TestFlowgraphResamplerParams({11025, 48000, MultiChannelResampler::Quality::High}),
+                TestFlowgraphResamplerParams({11025, 48000, MultiChannelResampler::Quality::Best}),
+                TestFlowgraphResamplerParams({11025, 44100, MultiChannelResampler::Quality::Best}),
+                TestFlowgraphResamplerParams({11025, 88200, MultiChannelResampler::Quality::Best}),
+                TestFlowgraphResamplerParams({16000, 48000, MultiChannelResampler::Quality::Best}),
+                TestFlowgraphResamplerParams({44100, 48000, MultiChannelResampler::Quality::Low}),
+                TestFlowgraphResamplerParams({44100, 48000, MultiChannelResampler::Quality::Best}),
+                TestFlowgraphResamplerParams({48000, 11025, MultiChannelResampler::Quality::Best}),
+                TestFlowgraphResamplerParams({48000, 44100, MultiChannelResampler::Quality::Best}),
+                TestFlowgraphResamplerParams({44100, 11025, MultiChannelResampler::Quality::Best})),
+        &getTestName
+);
diff --git a/media/libaaudio/tests/test_resampler.cpp b/media/libaaudio/tests/test_resampler.cpp
index 1e4f59c..13e4a20 100644
--- a/media/libaaudio/tests/test_resampler.cpp
+++ b/media/libaaudio/tests/test_resampler.cpp
@@ -101,14 +101,20 @@
         }
     }
 
+    // Flush out remaining frames from the flowgraph
+    while (!mcResampler->isWriteNeeded()) {
+        mcResampler->readNextFrame(output);
+        output++;
+        numRead++;
+    }
+
     ASSERT_LE(numRead, kNumOutputSamples);
     // Some frames are lost priming the FIR filter.
-    const int kMaxAlgorithmicFrameLoss = 16;
+    const int kMaxAlgorithmicFrameLoss = 5;
     EXPECT_GT(numRead, kNumOutputSamples - kMaxAlgorithmicFrameLoss);
 
     int sinkZeroCrossingCount = countZeroCrossingsWithHysteresis(outputBuffer.get(), numRead);
-    // Some cycles may get chopped off at the end.
-    const int kMaxZeroCrossingDelta = 3;
+    const int kMaxZeroCrossingDelta = std::max(sinkRate / sourceRate / 2, 1);
     EXPECT_LE(abs(sourceZeroCrossingCount - sinkZeroCrossingCount), kMaxZeroCrossingDelta);
 
     // Detect glitches by looking for spikes in the second derivative.
@@ -136,8 +142,7 @@
 
 
 TEST(test_resampler, resampler_scan_all) {
-    // TODO Add 64000, 88200, 96000 when they work. Failing now.
-    const int rates[] = {8000, 11025, 22050, 32000, 44100, 48000};
+    const int rates[] = {8000, 11025, 22050, 32000, 44100, 48000, 64000, 88200, 96000};
     const MultiChannelResampler::Quality qualities[] =
     {
         MultiChannelResampler::Quality::Fastest,
@@ -193,10 +198,9 @@
     checkResampler(11025, 44100, MultiChannelResampler::Quality::Best);
 }
 
-// TODO This fails because the output is very low.
-//TEST(test_resampler, resampler_11025_88200_best) {
-//    checkResampler(11025, 88200, MultiChannelResampler::Quality::Best);
-//}
+TEST(test_resampler, resampler_11025_88200_best) {
+    checkResampler(11025, 88200, MultiChannelResampler::Quality::Best);
+}
 
 TEST(test_resampler, resampler_16000_48000_best) {
     checkResampler(16000, 48000, MultiChannelResampler::Quality::Best);
diff --git a/media/libaudioclient/AudioSystem.cpp b/media/libaudioclient/AudioSystem.cpp
index 7cec2e8..871318f 100644
--- a/media/libaudioclient/AudioSystem.cpp
+++ b/media/libaudioclient/AudioSystem.cpp
@@ -132,12 +132,10 @@
                 binder = gAudioFlingerBinder;
             } else {
                 sp<IServiceManager> sm = defaultServiceManager();
-                do {
-                    binder = sm->getService(String16(IAudioFlinger::DEFAULT_SERVICE_NAME));
-                    if (binder != nullptr) break;
-                    ALOGW("AudioFlinger not published, waiting...");
-                    usleep(500000); // 0.5 s
-                } while (true);
+                binder = sm->waitForService(String16(IAudioFlinger::DEFAULT_SERVICE_NAME));
+                if (binder == nullptr) {
+                    return nullptr;
+                }
             }
             binder->linkToDeath(gAudioFlingerClient);
             const auto afs = interface_cast<media::IAudioFlingerService>(binder);
@@ -870,14 +868,10 @@
         Mutex::Autolock _l(gLockAPS);
         if (gAudioPolicyService == 0) {
             sp<IServiceManager> sm = defaultServiceManager();
-            sp<IBinder> binder;
-            do {
-                binder = sm->getService(String16("media.audio_policy"));
-                if (binder != 0)
-                    break;
-                ALOGW("AudioPolicyService not published, waiting...");
-                usleep(500000); // 0.5 s
-            } while (true);
+            sp<IBinder> binder = sm->waitForService(String16("media.audio_policy"));
+            if (binder == nullptr) {
+                return nullptr;
+            }
             if (gAudioPolicyServiceClient == NULL) {
                 gAudioPolicyServiceClient = new AudioPolicyServiceClient();
             }
@@ -2093,8 +2087,7 @@
         return BAD_VALUE;
     }
 
-    const sp<IAudioPolicyService>
-            & aps = AudioSystem::get_audio_policy_service();
+    const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
     if (aps == 0) return PERMISSION_DENIED;
 
     std::vector<AudioFormatDescription> formatsAidl;
diff --git a/media/libaudioclient/IAudioFlinger.cpp b/media/libaudioclient/IAudioFlinger.cpp
index 7caaaaf..4bd12b8 100644
--- a/media/libaudioclient/IAudioFlinger.cpp
+++ b/media/libaudioclient/IAudioFlinger.cpp
@@ -646,7 +646,7 @@
     return result.value_or(0);
 }
 
-uint32_t AudioFlingerClientAdapter::getPrimaryOutputSamplingRate() {
+uint32_t AudioFlingerClientAdapter::getPrimaryOutputSamplingRate() const {
     auto result = [&]() -> ConversionResult<uint32_t> {
         int32_t aidlRet;
         RETURN_IF_ERROR(statusTFromBinderStatus(
@@ -657,7 +657,7 @@
     return result.value_or(0);
 }
 
-size_t AudioFlingerClientAdapter::getPrimaryOutputFrameCount() {
+size_t AudioFlingerClientAdapter::getPrimaryOutputFrameCount() const {
     auto result = [&]() -> ConversionResult<size_t> {
         int64_t aidlRet;
         RETURN_IF_ERROR(statusTFromBinderStatus(
@@ -672,7 +672,7 @@
     return statusTFromBinderStatus(mDelegate->setLowRamDevice(isLowRamDevice, totalMemory));
 }
 
-status_t AudioFlingerClientAdapter::getAudioPort(struct audio_port_v7* port) {
+status_t AudioFlingerClientAdapter::getAudioPort(struct audio_port_v7* port) const {
     media::AudioPortFw portAidl = VALUE_OR_RETURN_STATUS(
             legacy2aidl_audio_port_v7_AudioPortFw(*port));
     media::AudioPortFw aidlRet;
@@ -705,7 +705,7 @@
 }
 
 status_t AudioFlingerClientAdapter::listAudioPatches(unsigned int* num_patches,
-                                                     struct audio_patch* patches) {
+                                                     struct audio_patch* patches) const {
     std::vector<media::AudioPatchFw> aidlRet;
     int32_t maxPatches = VALUE_OR_RETURN_STATUS(convertIntegral<int32_t>(*num_patches));
     RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(
@@ -753,7 +753,8 @@
 }
 
 status_t
-AudioFlingerClientAdapter::getMicrophones(std::vector<media::MicrophoneInfoFw>* microphones) {
+AudioFlingerClientAdapter::getMicrophones(
+        std::vector<media::MicrophoneInfoFw>* microphones) const {
     std::vector<media::MicrophoneInfoFw> aidlRet;
     RETURN_STATUS_IF_ERROR(statusTFromBinderStatus(mDelegate->getMicrophones(&aidlRet)));
     if (microphones != nullptr) {
@@ -788,7 +789,7 @@
     return statusTFromBinderStatus(mDelegate->getMmapPolicyInfos(policyType, policyInfos));
 }
 
-int32_t AudioFlingerClientAdapter::getAAudioMixerBurstCount() {
+int32_t AudioFlingerClientAdapter::getAAudioMixerBurstCount() const {
     auto result = [&]() -> ConversionResult<int32_t> {
         int32_t aidlRet;
         RETURN_IF_ERROR(statusTFromBinderStatus(mDelegate->getAAudioMixerBurstCount(&aidlRet)));
@@ -798,7 +799,7 @@
     return result.value_or(0);
 }
 
-int32_t AudioFlingerClientAdapter::getAAudioHardwareBurstMinUsec() {
+int32_t AudioFlingerClientAdapter::getAAudioHardwareBurstMinUsec() const {
     auto result = [&]() -> ConversionResult<int32_t> {
         int32_t aidlRet;
         RETURN_IF_ERROR(statusTFromBinderStatus(
@@ -829,7 +830,7 @@
 }
 
 status_t AudioFlingerClientAdapter::getSupportedLatencyModes(
-        audio_io_handle_t output, std::vector<audio_latency_mode_t>* modes) {
+        audio_io_handle_t output, std::vector<audio_latency_mode_t>* modes) const {
     if (modes == nullptr) {
         return BAD_VALUE;
     }
@@ -851,7 +852,7 @@
     return statusTFromBinderStatus(mDelegate->setBluetoothVariableLatencyEnabled(enabled));
 }
 
-status_t AudioFlingerClientAdapter::isBluetoothVariableLatencyEnabled(bool* enabled) {
+status_t AudioFlingerClientAdapter::isBluetoothVariableLatencyEnabled(bool* enabled) const {
     if (enabled == nullptr) {
         return BAD_VALUE;
     }
@@ -862,7 +863,7 @@
     return NO_ERROR;
 }
 
-status_t AudioFlingerClientAdapter::supportsBluetoothVariableLatency(bool* support) {
+status_t AudioFlingerClientAdapter::supportsBluetoothVariableLatency(bool* support) const {
     if (support == nullptr) {
         return BAD_VALUE;
     }
@@ -875,7 +876,7 @@
 
 status_t AudioFlingerClientAdapter::getSoundDoseInterface(
         const sp<media::ISoundDoseCallback> &callback,
-        sp<media::ISoundDose>* soundDose) {
+        sp<media::ISoundDose>* soundDose) const {
     return statusTFromBinderStatus(mDelegate->getSoundDoseInterface(callback, soundDose));
 }
 
diff --git a/media/libaudioclient/aidl/fuzzer/Android.bp b/media/libaudioclient/aidl/fuzzer/Android.bp
new file mode 100644
index 0000000..67258d9
--- /dev/null
+++ b/media/libaudioclient/aidl/fuzzer/Android.bp
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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: "libaudioclient_aidl_fuzzer_defaults",
+    static_libs: [
+        "android.hardware.audio.common@7.0-enums",
+        "effect-aidl-cpp",
+        "liblog",
+        "libcgrouprc",
+        "libcgrouprc_format",
+        "libjsoncpp",
+        "libmediametricsservice",
+        "libmedia_helper",
+        "libprocessgroup",
+        "shared-file-region-aidl-cpp",
+        "libfakeservicemanager"
+    ],
+    shared_libs: [
+        "libaudioclient",
+        "libaudioflinger",
+        "libmediautils",
+        "libnblog",
+        "libaudioprocessing",
+        "libnbaio",
+        "libpowermanager",
+        "libvibrator",
+        "packagemanager_aidl-cpp",
+        "android.hardware.audio.common-util",
+        "audioclient-types-aidl-cpp",
+        "audioflinger-aidl-cpp",
+        "audiopolicy-aidl-cpp",
+        "audiopolicy-types-aidl-cpp",
+        "av-types-aidl-cpp",
+        "capture_state_listener-aidl-cpp",
+        "libaudioclient_aidl_conversion",
+        "libaudiofoundation",
+        "libaudiomanager",
+        "libaudiopolicy",
+        "libaudioutils",
+        "libdl",
+        "libxml2",
+        "mediametricsservice-aidl-cpp",
+        "framework-permission-aidl-cpp",
+        "libvndksupport",
+        "libmediametrics",
+        "libfakeservicemanager",
+        "libactivitymanager_aidl",
+        "libheadtracking",
+        "libaudiopolicyservice",
+        "libsensorprivacy",
+        "libaudiopolicymanagerdefault",
+        "libaudiohal",
+        "libhidlbase",
+        "libpermission",
+        "libaudiohal@7.0",
+    ],
+    header_libs: [
+        "libaudiopolicymanager_interface_headers",
+        "libbinder_headers",
+        "libaudiofoundation_headers",
+        "libmedia_headers",
+        "libaudiohal_headers",
+        "libaudioflinger_headers",
+        "mediautils_headers",
+    ],
+     fuzz_config: {
+        cc: [
+            "android-media-fuzzing-reports@google.com",
+        ],
+        componentid: 155276,
+        hotlists: ["4593311"],
+        description: "The fuzzer targets the APIs of libaudioflinger",
+        vector: "local_no_privileges_required",
+        service_privilege: "privileged",
+        users: "multi_user",
+        fuzzed_code_usage: "shipped",
+    },
+}
+
+cc_fuzz {
+    name: "audioflinger_aidl_fuzzer",
+    srcs: ["audioflinger_aidl_fuzzer.cpp"],
+    defaults: [
+        "libaudioclient_aidl_fuzzer_defaults",
+        "service_fuzzer_defaults"
+    ],
+}
diff --git a/media/libaudioclient/aidl/fuzzer/audioflinger_aidl_fuzzer.cpp b/media/libaudioclient/aidl/fuzzer/audioflinger_aidl_fuzzer.cpp
new file mode 100644
index 0000000..fac5f53
--- /dev/null
+++ b/media/libaudioclient/aidl/fuzzer/audioflinger_aidl_fuzzer.cpp
@@ -0,0 +1,218 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <AudioFlinger.h>
+#include <ISchedulingPolicyService.h>
+#include <fakeservicemanager/FakeServiceManager.h>
+#include <android-base/logging.h>
+#include <android/binder_interface_utils.h>
+#include <android/binder_process.h>
+#include <android/media/IAudioPolicyService.h>
+#include <binder/IActivityManager.h>
+#include <binder/IPermissionController.h>
+#include <binder/IServiceManager.h>
+#include <binder/PermissionController.h>
+#include <fuzzbinder/libbinder_driver.h>
+#include <fuzzer/FuzzedDataProvider.h>
+#include <media/IAudioFlinger.h>
+#include <mediautils/SchedulingPolicyService.h>
+#include <sensorprivacy/SensorPrivacyManager.h>
+#include <service/AudioPolicyService.h>
+
+using namespace android;
+using namespace android::binder;
+using android::fuzzService;
+
+static sp<media::IAudioFlingerService> gAudioFlingerService;
+
+class FuzzerSchedulingPolicyService : public BnInterface<ISchedulingPolicyService> {
+    int32_t requestPriority(int32_t /*pid_t*/, int32_t /*tid*/, int32_t /*prio*/, bool /*isForApp*/,
+                            bool /*asynchronous*/) {
+        return 0;
+    }
+
+    int32_t requestCpusetBoost(bool /*enable*/, const sp<IBinder>& /*client*/) { return 0; }
+};
+
+class FuzzerPermissionController : public BnInterface<IPermissionController> {
+  public:
+    bool checkPermission(const String16& /*permission*/, int32_t /*pid*/, int32_t /*uid*/) {
+        return true;
+    }
+    int32_t noteOp(const String16& /*op*/, int32_t /*uid*/, const String16& /*packageName*/) {
+        return 0;
+    }
+    void getPackagesForUid(const uid_t /*uid*/, Vector<String16>& /*packages*/) {}
+    bool isRuntimePermission(const String16& /*permission*/) { return true; }
+    int32_t getPackageUid(const String16& /*package*/, int /*flags*/) { return 0; }
+};
+
+class FuzzerSensorPrivacyManager : public BnInterface<hardware::ISensorPrivacyManager> {
+  public:
+    Status supportsSensorToggle(int32_t /*toggleType*/, int32_t /*sensor*/,
+                                bool* /*_aidl_return*/) override {
+        return Status::fromStatusT(UNKNOWN_TRANSACTION);
+    }
+    Status addSensorPrivacyListener(
+            const sp<hardware::ISensorPrivacyListener>& /*listener*/) override {
+        return Status::fromStatusT(::android::UNKNOWN_TRANSACTION);
+    }
+    Status addToggleSensorPrivacyListener(
+            const sp<hardware::ISensorPrivacyListener>& /*listener*/) override {
+        return Status::fromStatusT(UNKNOWN_TRANSACTION);
+    }
+    Status removeSensorPrivacyListener(
+            const sp<hardware::ISensorPrivacyListener>& /*listener*/) override {
+        return Status::fromStatusT(::android::UNKNOWN_TRANSACTION);
+    }
+    Status removeToggleSensorPrivacyListener(
+            const sp<hardware::ISensorPrivacyListener>& /*listener*/) override {
+        return Status::fromStatusT(::android::UNKNOWN_TRANSACTION);
+    }
+    Status isSensorPrivacyEnabled(bool* /*_aidl_return*/) override {
+        return Status::fromStatusT(UNKNOWN_TRANSACTION);
+    }
+    Status isCombinedToggleSensorPrivacyEnabled(int32_t /*sensor*/,
+                                                bool* /*_aidl_return*/) override {
+        return Status::fromStatusT(UNKNOWN_TRANSACTION);
+    }
+    Status isToggleSensorPrivacyEnabled(int32_t /*toggleType*/, int32_t /*sensor*/,
+                                        bool* /*_aidl_return*/) override {
+        return Status::fromStatusT(UNKNOWN_TRANSACTION);
+    }
+    Status setSensorPrivacy(bool /*enable*/) override {
+        return Status::fromStatusT(UNKNOWN_TRANSACTION);
+    }
+    Status setToggleSensorPrivacy(int32_t /*userId*/, int32_t /*source*/, int32_t /*sensor*/,
+                                  bool /*enable*/) override {
+        return Status::fromStatusT(UNKNOWN_TRANSACTION);
+    }
+    Status setToggleSensorPrivacyForProfileGroup(int32_t /*userId*/, int32_t /*source*/,
+                                                 int32_t /*sensor*/, bool /*enable*/) override {
+        return Status::fromStatusT(UNKNOWN_TRANSACTION);
+    }
+};
+
+class FuzzerActivityManager : public BnInterface<IActivityManager> {
+  public:
+    int32_t openContentUri(const String16& /*stringUri*/) override { return 0; }
+
+    status_t registerUidObserver(const sp<IUidObserver>& /*observer*/, const int32_t /*event*/,
+                                 const int32_t /*cutpoint*/,
+                                 const String16& /*callingPackage*/) override {
+        return OK;
+    }
+
+    status_t unregisterUidObserver(const sp<IUidObserver>& /*observer*/) override { return OK; }
+
+    bool isUidActive(const uid_t /*uid*/, const String16& /*callingPackage*/) override {
+        return true;
+    }
+
+    int32_t getUidProcessState(const uid_t /*uid*/, const String16& /*callingPackage*/) override {
+        return ActivityManager::PROCESS_STATE_UNKNOWN;
+    }
+
+    status_t checkPermission(const String16& /*permission*/, const pid_t /*pid*/,
+                             const uid_t /*uid*/, int32_t* /*outResult*/) override {
+        return NO_ERROR;
+    }
+
+    status_t registerUidObserverForUids(const sp<IUidObserver>& /*observer*/ ,
+                                        const int32_t /*event*/ ,
+                                        const int32_t /*cutpoint*/ ,
+                                        const String16& /*callingPackage*/ ,
+                                        const int32_t uids[] ,
+                                        size_t /*nUids*/ ,
+                                        /*out*/ sp<IBinder>& /*observerToken*/ ) {
+        (void)uids;
+        return OK;
+    }
+
+    status_t addUidToObserver(const sp<IBinder>& /*observerToken*/ ,
+                              const String16& /*callingPackage*/ ,
+                              int32_t /*uid*/ ) override {
+        return NO_ERROR;
+    }
+
+    status_t removeUidFromObserver(const sp<IBinder>& /*observerToken*/ ,
+                                   const String16& /*callingPackage*/ ,
+                                   int32_t /*uid*/ ) override {
+        return NO_ERROR;
+    }
+
+    status_t logFgsApiBegin(int32_t /*apiType*/ , int32_t /*appUid*/ ,
+                            int32_t /*appPid*/ ) override {
+        return NO_ERROR;
+    }
+    status_t logFgsApiEnd(int32_t /*apiType*/ , int32_t /*appUid*/ ,
+                          int32_t /*appPid*/ ) override {
+        return NO_ERROR;
+    }
+    status_t logFgsApiStateChanged(int32_t /*apiType*/ , int32_t /*state*/ ,
+                                   int32_t /*appUid*/ ,
+                                   int32_t /*appPid*/ ) override {
+        return NO_ERROR;
+    }
+};
+
+extern "C" int LLVMFuzzerInitialize(int* /* argc */, char*** /* argv */) {
+    /* Create a FakeServiceManager instance and add required services */
+    sp<FakeServiceManager> fakeServiceManager = new FakeServiceManager();
+    setDefaultServiceManager(fakeServiceManager);
+    ABinderProcess_setThreadPoolMaxThreadCount(0);
+    sp<FuzzerActivityManager> am = new FuzzerActivityManager();
+    fakeServiceManager->addService(String16("activity"), IInterface::asBinder(am));
+
+    sp<FuzzerSensorPrivacyManager> sensorPrivacyManager = new FuzzerSensorPrivacyManager();
+    fakeServiceManager->addService(String16("sensor_privacy"),
+                                   IInterface::asBinder(sensorPrivacyManager));
+    sp<FuzzerPermissionController> permissionController = new FuzzerPermissionController();
+    fakeServiceManager->addService(String16("permission"),
+                                   IInterface::asBinder(permissionController));
+
+    sp<FuzzerSchedulingPolicyService> schedulingService = new FuzzerSchedulingPolicyService();
+    fakeServiceManager->addService(String16("scheduling_policy"),
+                                   IInterface::asBinder(schedulingService));
+
+    const auto audioFlingerObj = sp<AudioFlinger>::make();
+    const auto afAdapter = sp<AudioFlingerServerAdapter>::make(audioFlingerObj);
+
+    fakeServiceManager->addService(String16(IAudioFlinger::DEFAULT_SERVICE_NAME),
+                                   IInterface::asBinder(afAdapter), false /* allowIsolated */,
+                                   IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT);
+
+    const auto audioPolicyService = sp<AudioPolicyService>::make();
+    fakeServiceManager->addService(String16("media.audio_policy"), audioPolicyService,
+                                   false /* allowIsolated */,
+                                   IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT);
+
+    sp<IBinder> binder =
+            fakeServiceManager->getService(String16(IAudioFlinger::DEFAULT_SERVICE_NAME));
+    gAudioFlingerService = interface_cast<media::IAudioFlingerService>(binder);
+    return 0;
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+    if (!gAudioFlingerService) {
+        return 0;
+    }
+
+    fuzzService(media::IAudioFlingerService::asBinder(gAudioFlingerService),
+                FuzzedDataProvider(data, size));
+
+    return 0;
+}
diff --git a/media/libaudioclient/include/media/IAudioFlinger.h b/media/libaudioclient/include/media/IAudioFlinger.h
index 2e2ef65..3c96862 100644
--- a/media/libaudioclient/include/media/IAudioFlinger.h
+++ b/media/libaudioclient/include/media/IAudioFlinger.h
@@ -303,8 +303,8 @@
     // helpers for android.media.AudioManager.getProperty(), see description there for meaning
     // FIXME move these APIs to AudioPolicy to permit a more accurate implementation
     // that looks on primary device for a stream with fast flag, primary flag, or first one.
-    virtual uint32_t getPrimaryOutputSamplingRate() = 0;
-    virtual size_t getPrimaryOutputFrameCount() = 0;
+    virtual uint32_t getPrimaryOutputSamplingRate() const = 0;
+    virtual size_t getPrimaryOutputFrameCount() const = 0;
 
     // Intended for AudioService to inform AudioFlinger of device's low RAM attribute,
     // and should be called at most once.  For a definition of what "low RAM" means, see
@@ -313,7 +313,7 @@
     virtual status_t setLowRamDevice(bool isLowRamDevice, int64_t totalMemory) = 0;
 
     /* Get attributes for a given audio port */
-    virtual status_t getAudioPort(struct audio_port_v7 *port) = 0;
+    virtual status_t getAudioPort(struct audio_port_v7* port) const = 0;
 
     /* Create an audio patch between several source and sink ports */
     virtual status_t createAudioPatch(const struct audio_patch *patch,
@@ -324,7 +324,7 @@
 
     /* List existing audio patches */
     virtual status_t listAudioPatches(unsigned int *num_patches,
-                                      struct audio_patch *patches) = 0;
+                                      struct audio_patch* patches) const = 0;
     /* Set audio port configuration */
     virtual status_t setAudioPortConfig(const struct audio_port_config *config) = 0;
 
@@ -341,7 +341,7 @@
     virtual size_t frameCountHAL(audio_io_handle_t ioHandle) const = 0;
 
     /* List available microphones and their characteristics */
-    virtual status_t getMicrophones(std::vector<media::MicrophoneInfoFw> *microphones) = 0;
+    virtual status_t getMicrophones(std::vector<media::MicrophoneInfoFw>* microphones) const = 0;
 
     virtual status_t setAudioHalPids(const std::vector<pid_t>& pids) = 0;
 
@@ -357,9 +357,9 @@
             media::audio::common::AudioMMapPolicyType policyType,
             std::vector<media::audio::common::AudioMMapPolicyInfo> *policyInfos) = 0;
 
-    virtual int32_t getAAudioMixerBurstCount() = 0;
+    virtual int32_t getAAudioMixerBurstCount() const = 0;
 
-    virtual int32_t getAAudioHardwareBurstMinUsec() = 0;
+    virtual int32_t getAAudioHardwareBurstMinUsec() const = 0;
 
     virtual status_t setDeviceConnectedState(const struct audio_port_v7 *port,
                                              media::DeviceConnectedState state) = 0;
@@ -370,18 +370,18 @@
             audio_io_handle_t output, audio_latency_mode_t mode) = 0;
 
     virtual status_t getSupportedLatencyModes(audio_io_handle_t output,
-            std::vector<audio_latency_mode_t>* modes) = 0;
+            std::vector<audio_latency_mode_t>* modes) const = 0;
 
     virtual status_t getSoundDoseInterface(const sp<media::ISoundDoseCallback>& callback,
-                                           sp<media::ISoundDose>* soundDose) = 0;
+                                           sp<media::ISoundDose>* soundDose) const = 0;
 
     virtual status_t invalidateTracks(const std::vector<audio_port_handle_t>& portIds) = 0;
 
     virtual status_t setBluetoothVariableLatencyEnabled(bool enabled) = 0;
 
-    virtual status_t isBluetoothVariableLatencyEnabled(bool* enabled) = 0;
+    virtual status_t isBluetoothVariableLatencyEnabled(bool* enabled) const = 0;
 
-    virtual status_t supportsBluetoothVariableLatency(bool* support) = 0;
+    virtual status_t supportsBluetoothVariableLatency(bool* support) const = 0;
 
     virtual status_t getAudioPolicyConfig(media::AudioPolicyConfig* output) = 0;
 };
@@ -459,22 +459,22 @@
                             audio_session_t sessionId,
                             bool suspended) override;
     audio_module_handle_t loadHwModule(const char* name) override;
-    uint32_t getPrimaryOutputSamplingRate() override;
-    size_t getPrimaryOutputFrameCount() override;
+    uint32_t getPrimaryOutputSamplingRate() const override;
+    size_t getPrimaryOutputFrameCount() const override;
     status_t setLowRamDevice(bool isLowRamDevice, int64_t totalMemory) override;
-    status_t getAudioPort(struct audio_port_v7* port) override;
+    status_t getAudioPort(struct audio_port_v7* port) const override;
     status_t createAudioPatch(const struct audio_patch* patch,
                               audio_patch_handle_t* handle) override;
     status_t releaseAudioPatch(audio_patch_handle_t handle) override;
     status_t listAudioPatches(unsigned int* num_patches,
-                              struct audio_patch* patches) override;
+                              struct audio_patch* patches) const override;
     status_t setAudioPortConfig(const struct audio_port_config* config) override;
     audio_hw_sync_t getAudioHwSyncForSession(audio_session_t sessionId) override;
     status_t systemReady() override;
     status_t audioPolicyReady() override;
 
     size_t frameCountHAL(audio_io_handle_t ioHandle) const override;
-    status_t getMicrophones(std::vector<media::MicrophoneInfoFw>* microphones) override;
+    status_t getMicrophones(std::vector<media::MicrophoneInfoFw>* microphones) const override;
     status_t setAudioHalPids(const std::vector<pid_t>& pids) override;
     status_t setVibratorInfos(const std::vector<media::AudioVibratorInfo>& vibratorInfos) override;
     status_t updateSecondaryOutputs(
@@ -482,20 +482,20 @@
     status_t getMmapPolicyInfos(
             media::audio::common::AudioMMapPolicyType policyType,
             std::vector<media::audio::common::AudioMMapPolicyInfo> *policyInfos) override;
-    int32_t getAAudioMixerBurstCount() override;
-    int32_t getAAudioHardwareBurstMinUsec() override;
+    int32_t getAAudioMixerBurstCount() const override;
+    int32_t getAAudioHardwareBurstMinUsec() const override;
     status_t setDeviceConnectedState(const struct audio_port_v7 *port,
                                      media::DeviceConnectedState state) override;
     status_t setSimulateDeviceConnections(bool enabled) override;
     status_t setRequestedLatencyMode(audio_io_handle_t output,
             audio_latency_mode_t mode) override;
     status_t getSupportedLatencyModes(
-            audio_io_handle_t output, std::vector<audio_latency_mode_t>* modes) override;
+            audio_io_handle_t output, std::vector<audio_latency_mode_t>* modes) const override;
     status_t setBluetoothVariableLatencyEnabled(bool enabled) override;
-    status_t isBluetoothVariableLatencyEnabled(bool* enabled) override;
-    status_t supportsBluetoothVariableLatency(bool* support) override;
+    status_t isBluetoothVariableLatencyEnabled(bool* enabled) const override;
+    status_t supportsBluetoothVariableLatency(bool* support) const override;
     status_t getSoundDoseInterface(const sp<media::ISoundDoseCallback>& callback,
-                                   sp<media::ISoundDose>* soundDose) override;
+                                   sp<media::ISoundDose>* soundDose) const override;
     status_t invalidateTracks(const std::vector<audio_port_handle_t>& portIds) override;
     status_t getAudioPolicyConfig(media::AudioPolicyConfig* output) override;
 
diff --git a/media/libaudioclient/tests/audiorouting_tests.cpp b/media/libaudioclient/tests/audiorouting_tests.cpp
index 19d1abc..e6916cc 100644
--- a/media/libaudioclient/tests/audiorouting_tests.cpp
+++ b/media/libaudioclient/tests/audiorouting_tests.cpp
@@ -53,7 +53,7 @@
         ASSERT_NE(nullptr, ap);
         ASSERT_EQ(OK, ap->loadResource("/data/local/tmp/bbb_2ch_24kHz_s16le.raw"))
                 << "Unable to open Resource";
-        EXPECT_EQ(OK, ap->create()) << "track creation failed";
+        ASSERT_EQ(OK, ap->create()) << "track creation failed";
         sp<OnAudioDeviceUpdateNotifier> cb = sp<OnAudioDeviceUpdateNotifier>::make();
         EXPECT_EQ(OK, ap->getAudioTrackHandle()->addAudioDeviceCallback(cb));
         EXPECT_EQ(OK, ap->start()) << "audio track start failed";
@@ -87,7 +87,7 @@
     sp<AudioCapture> capture = sp<AudioCapture>::make(
             AUDIO_SOURCE_REMOTE_SUBMIX, 48000, AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_IN_STEREO);
     ASSERT_NE(nullptr, capture);
-    EXPECT_EQ(OK, capture->create()) << "record creation failed";
+    ASSERT_EQ(OK, capture->create()) << "record creation failed";
     sp<OnAudioDeviceUpdateNotifier> cbCapture = sp<OnAudioDeviceUpdateNotifier>::make();
     EXPECT_EQ(OK, capture->getAudioRecordHandle()->addAudioDeviceCallback(cbCapture));
 
@@ -98,7 +98,7 @@
     ASSERT_NE(nullptr, playback);
     ASSERT_EQ(OK, playback->loadResource("/data/local/tmp/bbb_2ch_24kHz_s16le.raw"))
             << "Unable to open Resource";
-    EXPECT_EQ(OK, playback->create()) << "track creation failed";
+    ASSERT_EQ(OK, playback->create()) << "track creation failed";
     sp<OnAudioDeviceUpdateNotifier> cbPlayback = sp<OnAudioDeviceUpdateNotifier>::make();
     EXPECT_EQ(OK, playback->getAudioTrackHandle()->addAudioDeviceCallback(cbPlayback));
 
@@ -180,7 +180,7 @@
     ASSERT_NE(nullptr, playback);
     ASSERT_EQ(OK, playback->loadResource("/data/local/tmp/bbb_2ch_24kHz_s16le.raw"))
             << "Unable to open Resource";
-    EXPECT_EQ(OK, playback->create()) << "track creation failed";
+    ASSERT_EQ(OK, playback->create()) << "track creation failed";
     sp<OnAudioDeviceUpdateNotifier> cbPlayback = sp<OnAudioDeviceUpdateNotifier>::make();
     EXPECT_EQ(OK, playback->getAudioTrackHandle()->addAudioDeviceCallback(cbPlayback));
 
@@ -188,7 +188,7 @@
     sp<AudioCapture> captureA = sp<AudioCapture>::make(
             AUDIO_SOURCE_REMOTE_SUBMIX, 48000, AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_IN_STEREO);
     ASSERT_NE(nullptr, captureA);
-    EXPECT_EQ(OK, captureA->create()) << "record creation failed";
+    ASSERT_EQ(OK, captureA->create()) << "record creation failed";
     sp<OnAudioDeviceUpdateNotifier> cbCaptureA = sp<OnAudioDeviceUpdateNotifier>::make();
     EXPECT_EQ(OK, captureA->getAudioRecordHandle()->addAudioDeviceCallback(cbCaptureA));
 
@@ -199,7 +199,7 @@
             AUDIO_SOURCE_REMOTE_SUBMIX, 48000, AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_IN_STEREO,
             AUDIO_INPUT_FLAG_NONE, AUDIO_SESSION_ALLOCATE, AudioRecord::TRANSFER_CALLBACK, &attr);
     ASSERT_NE(nullptr, captureB);
-    EXPECT_EQ(OK, captureB->create()) << "record creation failed";
+    ASSERT_EQ(OK, captureB->create()) << "record creation failed";
     sp<OnAudioDeviceUpdateNotifier> cbCaptureB = sp<OnAudioDeviceUpdateNotifier>::make();
     EXPECT_EQ(OK, captureB->getAudioRecordHandle()->addAudioDeviceCallback(cbCaptureB));
 
diff --git a/media/libeffects/visualizer/aidl/VisualizerContext.cpp b/media/libeffects/visualizer/aidl/VisualizerContext.cpp
index 5d0d08d..a1726ad 100644
--- a/media/libeffects/visualizer/aidl/VisualizerContext.cpp
+++ b/media/libeffects/visualizer/aidl/VisualizerContext.cpp
@@ -223,8 +223,7 @@
         deltaSamples = kMaxCaptureBufSize;
     }
 
-    int32_t capturePoint;
-    //capturePoint = (int32_t)mCaptureIdx - deltaSamples;
+    int32_t capturePoint, captureSamples = mCaptureSamples;
     __builtin_sub_overflow((int32_t) mCaptureIdx, deltaSamples, &capturePoint);
     // a negative capturePoint means we wrap the buffer.
     if (capturePoint < 0) {
@@ -232,13 +231,14 @@
         if (size > mCaptureSamples) {
             size = mCaptureSamples;
         }
+        // first part of two stages copy, capture to the end of buffer and reset the size/point
         result.insert(result.end(), &mCaptureBuf[kMaxCaptureBufSize + capturePoint],
                         &mCaptureBuf[kMaxCaptureBufSize + capturePoint + size]);
-        mCaptureSamples -= size;
+        captureSamples -= size;
         capturePoint = 0;
     }
     result.insert(result.end(), &mCaptureBuf[capturePoint],
-                    &mCaptureBuf[capturePoint + mCaptureSamples]);
+                  &mCaptureBuf[capturePoint + captureSamples]);
     mLastCaptureIdx = mCaptureIdx;
     return result;
 }
diff --git a/media/libheif/HeifDecoderImpl.cpp b/media/libheif/HeifDecoderImpl.cpp
index 2ba1fc3..6834b7d 100644
--- a/media/libheif/HeifDecoderImpl.cpp
+++ b/media/libheif/HeifDecoderImpl.cpp
@@ -476,35 +476,37 @@
 }
 
 bool HeifDecoderImpl::setOutputColor(HeifColorFormat heifColor) {
-    if (heifColor == (HeifColorFormat)mOutputColor) {
-        return true;
-    }
-
+    android_pixel_format_t outputColor;
     switch(heifColor) {
         case kHeifColorFormat_RGB565:
         {
-            mOutputColor = HAL_PIXEL_FORMAT_RGB_565;
+            outputColor = HAL_PIXEL_FORMAT_RGB_565;
             break;
         }
         case kHeifColorFormat_RGBA_8888:
         {
-            mOutputColor = HAL_PIXEL_FORMAT_RGBA_8888;
+            outputColor = HAL_PIXEL_FORMAT_RGBA_8888;
             break;
         }
         case kHeifColorFormat_BGRA_8888:
         {
-            mOutputColor = HAL_PIXEL_FORMAT_BGRA_8888;
+            outputColor = HAL_PIXEL_FORMAT_BGRA_8888;
             break;
         }
         case kHeifColorFormat_RGBA_1010102:
         {
-            mOutputColor = HAL_PIXEL_FORMAT_RGBA_1010102;
+            outputColor = HAL_PIXEL_FORMAT_RGBA_1010102;
             break;
         }
         default:
             ALOGE("Unsupported output color format %d", heifColor);
             return false;
     }
+    if (outputColor == mOutputColor) {
+        return true;
+    }
+
+    mOutputColor = outputColor;
 
     if (mFrameDecoded) {
         return reinit(nullptr);
diff --git a/media/libmedia/IMediaDeathNotifier.cpp b/media/libmedia/IMediaDeathNotifier.cpp
index c43ef66..f498453 100644
--- a/media/libmedia/IMediaDeathNotifier.cpp
+++ b/media/libmedia/IMediaDeathNotifier.cpp
@@ -38,16 +38,10 @@
     Mutex::Autolock _l(sServiceLock);
     if (sMediaPlayerService == 0) {
         sp<IServiceManager> sm = defaultServiceManager();
-        sp<IBinder> binder;
-        do {
-            binder = sm->getService(String16("media.player"));
-            if (binder != 0) {
-                break;
-            }
-            ALOGW("Media player service not published, waiting...");
-            usleep(500000); // 0.5 s
-        } while (true);
-
+        sp<IBinder> binder = sm->waitForService(String16("media.player"));
+        if (binder == nullptr) {
+            return nullptr;
+        }
         if (sDeathNotifier == NULL) {
             sDeathNotifier = new DeathNotifier();
         }
diff --git a/media/libmedia/mediametadataretriever.cpp b/media/libmedia/mediametadataretriever.cpp
index 2ae76b3..40fd022 100644
--- a/media/libmedia/mediametadataretriever.cpp
+++ b/media/libmedia/mediametadataretriever.cpp
@@ -41,14 +41,10 @@
     if (sService == 0) {
         sp<IServiceManager> sm = defaultServiceManager();
         sp<IBinder> binder;
-        do {
-            binder = sm->getService(String16("media.player"));
-            if (binder != 0) {
-                break;
-            }
-            ALOGW("MediaPlayerService not published, waiting...");
-            usleep(500000); // 0.5 s
-        } while (true);
+        binder = sm->waitForService(String16("media.player"));
+        if (binder == nullptr) {
+            return nullptr;
+        }
         if (sDeathNotifier == NULL) {
             sDeathNotifier = new DeathNotifier();
         }
diff --git a/media/libmediametrics/include/MediaMetricsConstants.h b/media/libmediametrics/include/MediaMetricsConstants.h
index f80a467..26aa375 100644
--- a/media/libmediametrics/include/MediaMetricsConstants.h
+++ b/media/libmediametrics/include/MediaMetricsConstants.h
@@ -184,6 +184,7 @@
 #define AMEDIAMETRICS_PROP_PLAYERIID      "playerIId"      // int32 (-1 invalid/unset IID)
 #define AMEDIAMETRICS_PROP_ROUTEDDEVICEID "routedDeviceId" // int32
 #define AMEDIAMETRICS_PROP_SAMPLERATE     "sampleRate"     // int32
+#define AMEDIAMETRICS_PROP_SAMPLERATECLIENT "sampleRateClient" // int32
 #define AMEDIAMETRICS_PROP_SAMPLERATEHARDWARE "sampleRateHardware" // int32
 #define AMEDIAMETRICS_PROP_SELECTEDDEVICEID "selectedDeviceId" // int32
 #define AMEDIAMETRICS_PROP_SELECTEDMICDIRECTION "selectedMicDirection" // int32
diff --git a/media/libnbaio/Android.bp b/media/libnbaio/Android.bp
index 89e9806..434ae00 100644
--- a/media/libnbaio/Android.bp
+++ b/media/libnbaio/Android.bp
@@ -49,7 +49,7 @@
     defaults: ["libnbaio_mono_defaults"],
 }
 
-cc_library_shared {
+cc_library {
     name: "libnbaio",
     defaults: ["libnbaio_mono_defaults"],
     srcs: [
diff --git a/media/libstagefright/CameraSource.cpp b/media/libstagefright/CameraSource.cpp
index 967c316..4441121 100644
--- a/media/libstagefright/CameraSource.cpp
+++ b/media/libstagefright/CameraSource.cpp
@@ -32,6 +32,7 @@
 #include <media/stagefright/MetaData.h>
 #include <camera/Camera.h>
 #include <camera/CameraParameters.h>
+#include <camera/StringUtils.h>
 #include <gui/Surface.h>
 #include <utils/String8.h>
 #include <cutils/properties.h>
@@ -146,7 +147,7 @@
 
 status_t CameraSource::isCameraAvailable(
     const sp<hardware::ICamera>& camera, const sp<ICameraRecordingProxy>& proxy,
-    int32_t cameraId, const String16& clientName, uid_t clientUid, pid_t clientPid) {
+    int32_t cameraId, const std::string& clientName, uid_t clientUid, pid_t clientPid) {
 
     if (camera == 0) {
         mCamera = Camera::connect(cameraId, clientName, clientUid, clientPid,
@@ -535,7 +536,7 @@
     status_t err = OK;
 
     if ((err = isCameraAvailable(camera, proxy, cameraId,
-            clientName, clientUid, clientPid)) != OK) {
+            toStdString(clientName), clientUid, clientPid)) != OK) {
         ALOGE("Camera connection could not be established.");
         return err;
     }
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
index a58343f..a0d56f8 100644
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -31,7 +31,6 @@
 #include "include/SoftwareRenderer.h"
 
 #include <android/api-level.h>
-#include <android/binder_manager.h>
 #include <android/content/pm/IPackageManagerNative.h>
 #include <android/hardware/cas/native/1.0/IDescrambler.h>
 #include <android/hardware/media/omx/1.0/IGraphicBufferSource.h>
@@ -74,7 +73,6 @@
 #include <media/stagefright/MediaCodec.h>
 #include <media/stagefright/MediaCodecConstants.h>
 #include <media/stagefright/MediaCodecList.h>
-#include <media/stagefright/MediaCodecConstants.h>
 #include <media/stagefright/MediaDefs.h>
 #include <media/stagefright/MediaErrors.h>
 #include <media/stagefright/OMXClient.h>
diff --git a/media/libstagefright/include/media/stagefright/CameraSource.h b/media/libstagefright/include/media/stagefright/CameraSource.h
index e8770ed..fcd17b9 100644
--- a/media/libstagefright/include/media/stagefright/CameraSource.h
+++ b/media/libstagefright/include/media/stagefright/CameraSource.h
@@ -259,7 +259,7 @@
     status_t isCameraAvailable(const sp<hardware::ICamera>& camera,
                                const sp<ICameraRecordingProxy>& proxy,
                                int32_t cameraId,
-                               const String16& clientName,
+                               const std::string& clientName,
                                uid_t clientUid,
                                pid_t clientPid);
 
diff --git a/media/libstagefright/rtsp/fuzzer/Android.bp b/media/libstagefright/rtsp/fuzzer/Android.bp
new file mode 100644
index 0000000..8e10b0c
--- /dev/null
+++ b/media/libstagefright/rtsp/fuzzer/Android.bp
@@ -0,0 +1,64 @@
+/*
+* Copyright (C) 2023 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at:
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+cc_defaults {
+    name: "libstagefright_rtsp_fuzzer_defaults",
+    shared_libs: [
+        "liblog",
+        "libmedia",
+        "libutils",
+        "libstagefright_foundation",
+    ],
+    static_libs: [
+        "libdatasource",
+        "libstagefright_rtsp",
+    ],
+    header_libs: [
+        "libstagefright_rtsp_headers",
+    ],
+    fuzz_config:{
+        cc: [
+            "android-media-fuzzing-reports@google.com",
+        ],
+        componentid: 155276,
+    },
+}
+
+cc_fuzz {
+    name: "sdploader_fuzzer",
+    srcs: [
+        "sdploader_fuzzer.cpp",
+    ],
+    defaults: [
+        "libstagefright_rtsp_fuzzer_defaults",
+    ]
+}
+
+cc_fuzz {
+    name: "rtp_writer_fuzzer",
+    srcs: [
+        "rtp_writer_fuzzer.cpp",
+    ],
+    defaults: [
+        "libstagefright_rtsp_fuzzer_defaults",
+    ],
+    shared_libs:[
+        "libandroid_net",
+        "libbase",
+        "libstagefright",
+        "libcutils",
+    ],
+}
diff --git a/media/libstagefright/rtsp/fuzzer/README.md b/media/libstagefright/rtsp/fuzzer/README.md
new file mode 100644
index 0000000..657fb48
--- /dev/null
+++ b/media/libstagefright/rtsp/fuzzer/README.md
@@ -0,0 +1,64 @@
+# Fuzzers for libstagefright_rtsp
+
+## Table of contents
++ [sdploader_fuzzer](#SDPLoader)
++ [rtp_writer_fuzzer](#ARTPWriter)
+
+# <a name="SDPLoader"></a> Fuzzer for SDPLoader
+
+SDPLoader supports the following parameters:
+1. Flag (parameter name: "flags")
+2. URL (parameter name: "url")
+3. Header (parameter name: "headers")
+
+| Parameter| Valid Values| Configured Value|
+|------------- |-------------| ----- |
+|`flags`| `UINT32_MIN`  to  `UINT32_MAX` |Value obtained from FuzzedDataProvider|
+|`url`| `String` |Value obtained from FuzzedDataProvider|
+|`headers`| `String` |Value obtained from FuzzedDataProvider|
+
+#### Steps to run
+1. Build the fuzzer
+```
+  $ mm -j$(nproc) sdploader_fuzzer
+```
+2. Run on device
+```
+  $ adb sync data
+  $ adb shell /data/fuzz/arm64/sdploader_fuzzer/sdploader_fuzzer
+```
+
+# <a name="ARTPWriter"></a> Fuzzer for ARTPWriter
+
+ARTPWriter supports the following parameters:
+1. File descriptor (parameter name: "fd")
+2. Local Ip (parameter name: "localIp")
+3. Local Port (parameter name: "localPort")
+4. Remote Ip (parameter name: "remoteIp")
+5. Remote Port (parameter name: "remotePort")
+6. Sequence No (parameter name: "seqNo")
+7. OpponentID (parameter name: "opponentID")
+8. Bit Rate (parameter name: "bitrate")
+9. kKeyMIMETypeArray (parameter name: "mimeType")
+
+| Parameter| Valid Values| Configured Value|
+|------------- |-------------| ----- |
+|`localIp`| `String` |Value obtained from FuzzedDataProvider|
+|`localPort`| `UINT32_MIN`  to  `UINT32_MAX` |Value obtained from FuzzedDataProvider|
+|`remoteIp`| `String` |Value obtained from FuzzedDataProvider|
+|`remotePort`| `UINT32_MIN`  to  `UINT32_MAX` |Value obtained from FuzzedDataProvider|
+|`seqNo`| `0`  to  `10000000` |Value obtained from FuzzedDataProvider|
+|`opponentID`| `UINT32_MIN`  to  `UINT32_MAX` |Value obtained from FuzzedDataProvider|
+|`bitrate`| `UINT32_MIN`  to  `UINT32_MAX` |Value obtained from FuzzedDataProvider|
+|`mimeType`| 0. `MEDIA_MIMETYPE_VIDEO_AVC`<br> 1. `MEDIA_MIMETYPE_VIDEO_HEVC`<br> 2. `MEDIA_MIMETYPE_VIDEO_H263`<br> 3. `MEDIA_MIMETYPE_AUDIO_AMR_NB`<br> 4. `MEDIA_MIMETYPE_AUDIO_AMR_WB`|Value obtained from FuzzedDataProvider|
+
+#### Steps to run
+1. Build the fuzzer
+```
+  $ mm -j$(nproc) rtp_writer_fuzzer
+```
+2. Run on device
+```
+  $ adb sync data
+  $ adb shell /data/fuzz/arm64/rtp_writer_fuzzer/rtp_writer_fuzzer
+```
diff --git a/media/libstagefright/rtsp/fuzzer/rtp_writer_fuzzer.cpp b/media/libstagefright/rtsp/fuzzer/rtp_writer_fuzzer.cpp
new file mode 100644
index 0000000..8d9f923
--- /dev/null
+++ b/media/libstagefright/rtsp/fuzzer/rtp_writer_fuzzer.cpp
@@ -0,0 +1,184 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <fuzzer/FuzzedDataProvider.h>
+#include <media/stagefright/MediaBuffer.h>
+#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/rtsp/ARTPWriter.h>
+
+constexpr int32_t kMinSize = 0;
+constexpr int32_t kMaxSize = 65536;
+constexpr int32_t kMaxTime = 1000;
+constexpr int32_t kMaxBytes = 128;
+constexpr int32_t kAMRNBFrameSizes[] = {13, 14, 16, 18, 20, 21, 27, 32};
+constexpr int32_t kAMRWBFrameSizes[] = {18, 24, 33, 37, 41, 47, 51, 59, 61};
+constexpr int32_t kAMRIndexOffset = 8;
+
+using namespace android;
+
+const char* kKeyMimeTypeArray[] = {MEDIA_MIMETYPE_VIDEO_AVC, MEDIA_MIMETYPE_VIDEO_HEVC,
+                                   MEDIA_MIMETYPE_VIDEO_H263, MEDIA_MIMETYPE_AUDIO_AMR_NB,
+                                   MEDIA_MIMETYPE_AUDIO_AMR_WB};
+
+struct TestMediaSource : public MediaSource {
+  public:
+    TestMediaSource(FuzzedDataProvider& mFdp) : mTestMetaData(new MetaData) {
+        int32_t vectorSize = 0;
+        mAllowRead = mFdp.ConsumeBool();
+        mKeySps = mFdp.ConsumeIntegral<int32_t>();
+        mKeyVps = mFdp.ConsumeIntegral<int32_t>();
+        mKeyPps = mFdp.ConsumeIntegral<int32_t>();
+        mKeyTime = mFdp.ConsumeIntegralInRange<int64_t>(kMinSize, kMaxTime);
+
+        mMimeType = mFdp.PickValueInArray(kKeyMimeTypeArray);
+        mTestMetaData->setCString(kKeyMIMEType, mMimeType);
+        if (mMimeType == MEDIA_MIMETYPE_AUDIO_AMR_NB) {
+            int32_t index =
+                    mFdp.ConsumeIntegralInRange<int32_t>(kMinSize, std::size(kAMRNBFrameSizes) - 1);
+            vectorSize = kAMRNBFrameSizes[index];
+            mData.push_back(kAMRIndexOffset * index);
+        } else if (mMimeType == MEDIA_MIMETYPE_AUDIO_AMR_WB) {
+            int32_t index =
+                    mFdp.ConsumeIntegralInRange<int32_t>(kMinSize, std::size(kAMRWBFrameSizes) - 1);
+            vectorSize = kAMRWBFrameSizes[index];
+            mData.push_back(kAMRIndexOffset * index);
+        } else if (mMimeType == MEDIA_MIMETYPE_VIDEO_H263) {
+            // Required format for H263 media data
+            mData.push_back(0);
+            mData.push_back(0);
+            vectorSize = mFdp.ConsumeIntegralInRange<int32_t>(kMinSize, kMaxSize);
+        } else {
+            vectorSize = mFdp.ConsumeIntegralInRange<int32_t>(kMinSize, kMaxSize);
+        }
+        for (size_t idx = mData.size(); idx < vectorSize; ++idx) {
+            mData.push_back(mFdp.ConsumeIntegral<uint8_t>());
+        }
+    }
+    virtual status_t start(MetaData* /*params*/) { return OK; }
+    virtual status_t stop() { return OK; }
+    virtual sp<MetaData> getFormat() { return mTestMetaData; }
+    virtual status_t read(MediaBufferBase** buffer, const ReadOptions* /*options*/) {
+        if (!mAllowRead) {
+            return -1;
+        }
+        *buffer = new MediaBuffer(mData.data() /*data*/, mData.size() /*size*/);
+        if (mKeySps) {
+            (*buffer)->meta_data().setInt32(kKeySps, mKeySps);
+        }
+        if (mKeyVps) {
+            (*buffer)->meta_data().setInt32(kKeyVps, mKeyVps);
+        }
+        if (mKeyPps) {
+            (*buffer)->meta_data().setInt32(kKeyPps, mKeyPps);
+        }
+        (*buffer)->meta_data().setInt64(kKeyTime, mKeyTime);
+        return OK;
+    }
+
+  private:
+    int32_t mKeySps;
+    int32_t mKeyVps;
+    int32_t mKeyPps;
+    int64_t mKeyTime;
+    bool mAllowRead;
+    const char* mMimeType;
+    sp<MetaData> mTestMetaData;
+    std::vector<uint8_t> mData;
+};
+
+class ARTPWriterFuzzer {
+  public:
+    ARTPWriterFuzzer(const uint8_t* data, size_t size)
+        : mDataSourceFd(memfd_create("InputFile", MFD_ALLOW_SEALING)), mFdp(data, size) {}
+    ~ARTPWriterFuzzer() { close(mDataSourceFd); }
+    void process();
+
+  private:
+    void createARTPWriter();
+    const int32_t mDataSourceFd;
+    FuzzedDataProvider mFdp;
+    sp<ARTPWriter> mArtpWriter;
+};
+
+void ARTPWriterFuzzer::createARTPWriter() {
+    String8 localIp = String8(mFdp.ConsumeRandomLengthString(kMaxBytes).c_str());
+    String8 remoteIp = String8(mFdp.ConsumeRandomLengthString(kMaxBytes).c_str());
+    mArtpWriter = sp<ARTPWriter>::make(
+            mDataSourceFd, localIp, mFdp.ConsumeIntegral<uint16_t>() /* localPort */, remoteIp,
+            mFdp.ConsumeIntegral<uint16_t>() /* remotePort */,
+            mFdp.ConsumeIntegralInRange<uint32_t>(kMinSize, kMaxSize) /* seqNo */);
+}
+
+void ARTPWriterFuzzer::process() {
+    if (mFdp.ConsumeBool()) {
+        mArtpWriter = sp<ARTPWriter>::make(mDataSourceFd);
+        if (mArtpWriter->getSequenceNum() > kMaxSize) {
+            createARTPWriter();
+        }
+    } else {
+        createARTPWriter();
+    }
+
+    mArtpWriter->addSource(sp<TestMediaSource>::make(mFdp) /* source */);
+
+    while (mFdp.remaining_bytes()) {
+        auto invokeRTPWriterFuzzer = mFdp.PickValueInArray<const std::function<void()>>({
+                [&]() {
+                    sp<MetaData> metaData = sp<MetaData>::make();
+                    if (mFdp.ConsumeBool()) {
+                        metaData->setInt32(kKeySelfID, mFdp.ConsumeIntegral<int32_t>());
+                    }
+                    if (mFdp.ConsumeBool()) {
+                        metaData->setInt32(kKeyPayloadType, mFdp.ConsumeIntegral<int32_t>());
+                    }
+                    if (mFdp.ConsumeBool()) {
+                        metaData->setInt32(kKeyRtpExtMap, mFdp.ConsumeIntegral<int32_t>());
+                    }
+                    if (mFdp.ConsumeBool()) {
+                        metaData->setInt32(kKeyRtpCvoDegrees, mFdp.ConsumeIntegral<int32_t>());
+                    }
+                    if (mFdp.ConsumeBool()) {
+                        metaData->setInt32(kKeyRtpDscp, mFdp.ConsumeIntegral<int32_t>());
+                    }
+                    if (mFdp.ConsumeBool()) {
+                        metaData->setInt64(kKeySocketNetwork, mFdp.ConsumeIntegral<int64_t>());
+                    }
+                    mArtpWriter->start(metaData.get() /*param*/);
+                },
+                [&]() {
+                    mArtpWriter->setTMMBNInfo(mFdp.ConsumeIntegral<uint32_t>() /* opponentID */,
+                                              mFdp.ConsumeIntegral<uint32_t>() /* bitrate */);
+                },
+                [&]() { mArtpWriter->stop(); },
+                [&]() {
+                    mArtpWriter->updateCVODegrees(mFdp.ConsumeIntegral<int32_t>() /* cvoDegrees */);
+                },
+                [&]() {
+                    mArtpWriter->updatePayloadType(
+                            mFdp.ConsumeIntegral<int32_t>() /* payloadType */);
+                },
+
+        });
+        invokeRTPWriterFuzzer();
+    }
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+    ARTPWriterFuzzer artpWriterFuzzer(data, size);
+    artpWriterFuzzer.process();
+    return 0;
+}
diff --git a/media/libstagefright/rtsp/fuzzer/sdploader_fuzzer.cpp b/media/libstagefright/rtsp/fuzzer/sdploader_fuzzer.cpp
new file mode 100644
index 0000000..748e5b6
--- /dev/null
+++ b/media/libstagefright/rtsp/fuzzer/sdploader_fuzzer.cpp
@@ -0,0 +1,141 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <datasource/HTTPBase.h>
+#include <fuzzer/FuzzedDataProvider.h>
+#include <media/MediaHTTPConnection.h>
+#include <media/MediaHTTPService.h>
+#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/rtsp/SDPLoader.h>
+
+using namespace android;
+
+constexpr int32_t kMinCapacity = 0;
+constexpr int32_t kMaxCapacity = 1000;
+constexpr int32_t kMaxStringLength = 20;
+constexpr int32_t kMaxBytes = 128;
+enum { kWhatLoad = 'load' };
+
+struct FuzzAHandler : public AHandler {
+  public:
+    FuzzAHandler(std::function<void()> signalEosFunction) : mSignalEosFunction(signalEosFunction) {}
+
+  protected:
+    void onMessageReceived(const sp<AMessage>& msg) override {
+        switch (msg->what()) {
+            case kWhatLoad: {
+                mSignalEosFunction();
+                break;
+            }
+        }
+        return;
+    }
+
+  private:
+    std::function<void()> mSignalEosFunction;
+};
+
+struct FuzzMediaHTTPConnection : public MediaHTTPConnection {
+  public:
+    FuzzMediaHTTPConnection(FuzzedDataProvider* fdp) : mFdp(fdp) {
+        mSize = mFdp->ConsumeIntegralInRange(kMinCapacity, kMaxCapacity);
+        mData = mFdp->ConsumeBytes<uint8_t>(mSize);
+        mSize = mData.size();
+    }
+    virtual bool connect(const char* /* uri */,
+                         const KeyedVector<String8, String8>* /* headers */) {
+        return mFdp->ConsumeBool();
+    }
+    virtual void disconnect() { return; }
+    virtual ssize_t readAt(off64_t offset, void* data, size_t size) {
+        if ((size + offset <= mData.size()) && (offset >= 0)) {
+           memcpy(data, mData.data() + offset, size);
+           return size;
+        }
+        return 0;
+    }
+    virtual off64_t getSize() { return mSize; }
+    virtual status_t getMIMEType(String8* /*mimeType*/) {return mFdp->ConsumeIntegral<status_t>();}
+    virtual status_t getUri(String8* /*uri*/) {return mFdp->ConsumeIntegral<status_t>();}
+
+  private:
+    FuzzedDataProvider* mFdp = nullptr;
+    std::vector<uint8_t> mData;
+    size_t mSize = 0;
+};
+
+struct FuzzMediaHTTPService : public MediaHTTPService {
+  public:
+    FuzzMediaHTTPService(FuzzedDataProvider* fdp) : mFdp(fdp) {}
+    virtual sp<MediaHTTPConnection> makeHTTPConnection() {
+        mediaHTTPConnection = sp<FuzzMediaHTTPConnection>::make(mFdp);
+        return mediaHTTPConnection;
+    }
+
+  private:
+    sp<FuzzMediaHTTPConnection> mediaHTTPConnection = nullptr;
+    FuzzedDataProvider* mFdp = nullptr;
+};
+
+class SDPLoaderFuzzer {
+  public:
+    SDPLoaderFuzzer(const uint8_t* data, size_t size) : mFdp(data, size) {}
+    void process();
+
+  private:
+    void signalEos();
+
+    bool mEosReached = false;
+    std::mutex mMsgPostCompleteMutex;
+    std::condition_variable mConditionalVariable;
+    FuzzedDataProvider mFdp;
+};
+
+void SDPLoaderFuzzer::signalEos() {
+    mEosReached = true;
+    mConditionalVariable.notify_one();
+    return;
+}
+
+void SDPLoaderFuzzer::process() {
+    sp<FuzzAHandler> handler = sp<FuzzAHandler>::make(std::bind(&SDPLoaderFuzzer::signalEos, this));
+    sp<ALooper> looper = sp<ALooper>::make();
+    looper->start();
+    looper->registerHandler(handler);
+    const sp<AMessage> notify = sp<AMessage>::make(kWhatLoad, handler);
+    sp<SDPLoader> sdpLoader =
+            sp<SDPLoader>::make(notify, mFdp.ConsumeIntegral<uint32_t>() /* flags */,
+                                sp<FuzzMediaHTTPService>::make(&mFdp) /* httpService */);
+
+    KeyedVector<String8, String8> headers;
+    for (size_t idx = 0; idx < mFdp.ConsumeIntegralInRange<size_t>(kMinCapacity, kMaxCapacity);
+         ++idx) {
+        headers.add(String8(mFdp.ConsumeRandomLengthString(kMaxBytes).c_str()) /* key */,
+                    String8(mFdp.ConsumeRandomLengthString(kMaxBytes).c_str()) /* value */);
+    }
+
+    sdpLoader->load(mFdp.ConsumeRandomLengthString(kMaxBytes).c_str() /* url */, &headers);
+
+    std::unique_lock waitForMsgPostComplete(mMsgPostCompleteMutex);
+    mConditionalVariable.wait(waitForMsgPostComplete, [this] { return mEosReached; });
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+    SDPLoaderFuzzer sdpLoaderFuzzer(data, size);
+    sdpLoaderFuzzer.process();
+    return 0;
+}
diff --git a/media/module/extractors/mp4/MPEG4Extractor.cpp b/media/module/extractors/mp4/MPEG4Extractor.cpp
index 38cf29d..184e4f4 100644
--- a/media/module/extractors/mp4/MPEG4Extractor.cpp
+++ b/media/module/extractors/mp4/MPEG4Extractor.cpp
@@ -2007,7 +2007,7 @@
             uint8_t mhac_header[mhac_header_size];
             off64_t data_offset = *offset;
 
-            if (chunk_size < sizeof(mhac_header)) {
+            if (mLastTrack == NULL || chunk_size < sizeof(mhac_header)) {
                 return ERROR_MALFORMED;
             }
 
diff --git a/media/mtp/MtpFfsHandle.cpp b/media/mtp/MtpFfsHandle.cpp
index 2ffd775..ef8c9aa 100644
--- a/media/mtp/MtpFfsHandle.cpp
+++ b/media/mtp/MtpFfsHandle.cpp
@@ -297,6 +297,10 @@
 }
 
 void MtpFfsHandle::close() {
+    auto timeout = std::chrono::seconds(2);
+    std::unique_lock lk(m);
+    cv.wait_for(lk, timeout ,[this]{return child_threads==0;});
+
     io_destroy(mCtx);
     closeEndpoints();
     closeConfig();
@@ -669,6 +673,11 @@
     char *temp = new char[me.length];
     memcpy(temp, me.data, me.length);
     me.data = temp;
+
+    std::unique_lock lk(m);
+    child_threads++;
+    lk.unlock();
+
     std::thread t([this, me]() { return this->doSendEvent(me); });
     t.detach();
     return 0;
@@ -680,6 +689,11 @@
     if (static_cast<unsigned>(ret) != length)
         PLOG(ERROR) << "Mtp error sending event thread!";
     delete[] reinterpret_cast<char*>(me.data);
+
+    std::unique_lock lk(m);
+    child_threads--;
+    lk.unlock();
+    cv.notify_one();
 }
 
 } // namespace android
diff --git a/media/mtp/MtpFfsHandle.h b/media/mtp/MtpFfsHandle.h
index e552e03..51cdef0 100644
--- a/media/mtp/MtpFfsHandle.h
+++ b/media/mtp/MtpFfsHandle.h
@@ -60,6 +60,10 @@
     bool mCanceled;
     bool mBatchCancel;
 
+    std::mutex m;
+    std::condition_variable cv;
+    std::atomic<int> child_threads{0};
+
     android::base::unique_fd mControl;
     // "in" from the host's perspective => sink for mtp server
     android::base::unique_fd mBulkIn;
diff --git a/media/mtp/MtpPacket.cpp b/media/mtp/MtpPacket.cpp
index f069a83..5faaac2 100644
--- a/media/mtp/MtpPacket.cpp
+++ b/media/mtp/MtpPacket.cpp
@@ -92,24 +92,46 @@
 }
 
 uint16_t MtpPacket::getUInt16(int offset) const {
-    return ((uint16_t)mBuffer[offset + 1] << 8) | (uint16_t)mBuffer[offset];
+    if ((unsigned long)(offset+2) <= mBufferSize) {
+        return ((uint16_t)mBuffer[offset + 1] << 8) | (uint16_t)mBuffer[offset];
+    }
+    else {
+        ALOGE("offset for buffer read is greater than buffer size!");
+        abort();
+    }
 }
 
 uint32_t MtpPacket::getUInt32(int offset) const {
-    return ((uint32_t)mBuffer[offset + 3] << 24) | ((uint32_t)mBuffer[offset + 2] << 16) |
-           ((uint32_t)mBuffer[offset + 1] << 8)  | (uint32_t)mBuffer[offset];
+    if ((unsigned long)(offset+4) <= mBufferSize) {
+        return ((uint32_t)mBuffer[offset + 3] << 24) | ((uint32_t)mBuffer[offset + 2] << 16) |
+               ((uint32_t)mBuffer[offset + 1] << 8)  | (uint32_t)mBuffer[offset];
+    }
+    else {
+        ALOGE("offset for buffer read is greater than buffer size!");
+        abort();
+    }
 }
 
 void MtpPacket::putUInt16(int offset, uint16_t value) {
-    mBuffer[offset++] = (uint8_t)(value & 0xFF);
-    mBuffer[offset++] = (uint8_t)((value >> 8) & 0xFF);
+    if ((unsigned long)(offset+2) <= mBufferSize) {
+        mBuffer[offset++] = (uint8_t)(value & 0xFF);
+        mBuffer[offset++] = (uint8_t)((value >> 8) & 0xFF);
+    }
+    else {
+        ALOGE("offset for buffer write is greater than buffer size!");
+    }
 }
 
 void MtpPacket::putUInt32(int offset, uint32_t value) {
-    mBuffer[offset++] = (uint8_t)(value & 0xFF);
-    mBuffer[offset++] = (uint8_t)((value >> 8) & 0xFF);
-    mBuffer[offset++] = (uint8_t)((value >> 16) & 0xFF);
-    mBuffer[offset++] = (uint8_t)((value >> 24) & 0xFF);
+    if ((unsigned long)(offset+4) <= mBufferSize) {
+        mBuffer[offset++] = (uint8_t)(value & 0xFF);
+        mBuffer[offset++] = (uint8_t)((value >> 8) & 0xFF);
+        mBuffer[offset++] = (uint8_t)((value >> 16) & 0xFF);
+        mBuffer[offset++] = (uint8_t)((value >> 24) & 0xFF);
+    }
+    else {
+        ALOGE("offset for buffer write is greater than buffer size!");
+    }
 }
 
 uint16_t MtpPacket::getContainerCode() const {
diff --git a/media/ndk/NdkImageReader.cpp b/media/ndk/NdkImageReader.cpp
index 067c8f4..0f7d98b 100644
--- a/media/ndk/NdkImageReader.cpp
+++ b/media/ndk/NdkImageReader.cpp
@@ -570,6 +570,9 @@
     }
 }
 
+// The LL-NDK API is now deprecated. New devices will no longer have the token
+// manager service installed, so createHalToken will return false and this
+// will return AMEDIA_ERROR_UNKNOWN on those devices.
 media_status_t AImageReader::getWindowNativeHandle(native_handle **handle) {
     if (mWindowHandle != nullptr) {
         *handle = mWindowHandle;
diff --git a/media/ndk/fuzzer/Android.bp b/media/ndk/fuzzer/Android.bp
index a3d6a96..ba92b19 100644
--- a/media/ndk/fuzzer/Android.bp
+++ b/media/ndk/fuzzer/Android.bp
@@ -56,6 +56,14 @@
             "android-media-fuzzing-reports@google.com",
         ],
         componentid: 155276,
+        hotlists: [
+            "4593311",
+        ],
+        description: "The fuzzer targets the APIs of libmediandk library",
+        vector: "local_no_privileges_required",
+        service_privilege: "privileged",
+        users: "multi_user",
+        fuzzed_code_usage: "shipped",
     },
 }
 
@@ -63,6 +71,11 @@
     name: "ndk_crypto_fuzzer",
     srcs: ["ndk_crypto_fuzzer.cpp"],
     defaults: ["libmediandk_fuzzer_defaults"],
+    fuzz_config: {
+        libfuzzer_options: [
+            "max_len=10000",
+        ],
+    },
 }
 
 cc_fuzz {
@@ -116,3 +129,16 @@
     header_libs: ["libnativewindow_headers",],
     defaults: ["libmediandk_fuzzer_defaults",],
 }
+
+cc_fuzz {
+    name: "ndk_async_codec_fuzzer",
+    srcs: [
+           "ndk_async_codec_fuzzer.cpp",
+           "NdkMediaCodecFuzzerBase.cpp",
+          ],
+    header_libs: [
+           "libnativewindow_headers",
+           "libutils_headers",
+          ],
+    defaults: ["libmediandk_fuzzer_defaults",],
+}
diff --git a/media/ndk/fuzzer/README.md b/media/ndk/fuzzer/README.md
index 0fd08b0..7f6bdd7 100644
--- a/media/ndk/fuzzer/README.md
+++ b/media/ndk/fuzzer/README.md
@@ -8,6 +8,7 @@
 + [ndk_drm_fuzzer](#NdkDrm)
 + [ndk_mediamuxer_fuzzer](#NdkMediaMuxer)
 + [ndk_sync_codec_fuzzer](#NdkSyncCodec)
++ [ndk_async_codec_fuzzer](#NdkAsyncCodec)
 
 # <a name="NdkCrypto"></a> Fuzzer for NdkCrypto
 
@@ -156,3 +157,16 @@
   $ adb sync data
   $ adb shell /data/fuzz/arm64/ndk_sync_codec_fuzzer/ndk_sync_codec_fuzzer
 ```
+
+# <a name="NdkAsyncCodec"></a>Fuzzer for NdkAsyncCodec
+
+#### Steps to run
+1. Build the fuzzer
+```
+  $ mm -j$(nproc) ndk_async_codec_fuzzer
+```
+2. Run on device
+```
+  $ adb sync data
+  $ adb shell /data/fuzz/arm64/ndk_async_codec_fuzzer/ndk_sync_codec_fuzzer
+```
diff --git a/media/ndk/fuzzer/ndk_async_codec_fuzzer.cpp b/media/ndk/fuzzer/ndk_async_codec_fuzzer.cpp
new file mode 100644
index 0000000..28a38fe
--- /dev/null
+++ b/media/ndk/fuzzer/ndk_async_codec_fuzzer.cpp
@@ -0,0 +1,441 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <NdkMediaCodecFuzzerBase.h>
+#include <media/NdkMediaFormatPriv.h>
+#include <mutex>
+#include <queue>
+#include <thread>
+
+using namespace android;
+using namespace std;
+
+constexpr int32_t kMaxCryptoInfoAPIs = 3;
+constexpr int32_t kMaxNdkCodecAPIs = 5;
+
+template <typename T>
+class CallBackQueue {
+  public:
+    void push(T elem) {
+        bool needsNotify = false;
+        {
+            unique_lock<mutex> lock(mMutex);
+            needsNotify = mQueue.empty();
+            mQueue.push(std::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;
+    std::queue<T> mQueue;
+    std::condition_variable mQueueNotEmptyCondition;
+};
+
+class CallBackHandle {
+  public:
+    CallBackHandle() : mSawError(false), mIsDone(false) {}
+
+    virtual ~CallBackHandle() {}
+
+    void ioThread();
+
+    // Implementation in child class (Decoder/Encoder)
+    virtual void invokeInputBufferAPI(AMediaCodec* codec, int32_t index) {
+        (void)codec;
+        (void)index;
+    }
+    virtual void onFormatChanged(AMediaCodec* codec, AMediaFormat* format) {
+        (void)codec;
+        (void)format;
+    }
+    virtual void receiveError(void) {}
+    virtual void invokeOutputBufferAPI(AMediaCodec* codec, int32_t index,
+                                       AMediaCodecBufferInfo* bufferInfo) {
+        (void)codec;
+        (void)index;
+        (void)bufferInfo;
+    }
+
+    // Keep a queue of all function callbacks.
+    typedef function<void()> IOTask;
+    CallBackQueue<IOTask> mIOQueue;
+    bool mSawError;
+    bool mIsDone;
+};
+
+void CallBackHandle::ioThread() {
+    while (!mIsDone && !mSawError) {
+        auto task = mIOQueue.pop();
+        task();
+    }
+}
+
+static void onAsyncInputAvailable(AMediaCodec* codec, void* userdata, int32_t index) {
+    CallBackHandle* self = (CallBackHandle*)userdata;
+    self->mIOQueue.push([self, codec, index]() { self->invokeInputBufferAPI(codec, index); });
+}
+
+static void onAsyncOutputAvailable(AMediaCodec* codec, void* userdata, int32_t index,
+                                   AMediaCodecBufferInfo* bufferInfo) {
+    CallBackHandle* self = (CallBackHandle*)userdata;
+    AMediaCodecBufferInfo bufferInfoCopy = *bufferInfo;
+    self->mIOQueue.push([self, codec, index, bufferInfoCopy]() {
+        AMediaCodecBufferInfo bc = bufferInfoCopy;
+        self->invokeOutputBufferAPI(codec, index, &bc);
+    });
+}
+
+static void onAsyncFormatChanged(AMediaCodec* codec, void* userdata, AMediaFormat* format) {
+    (void)codec;
+    (void)userdata;
+    (void)format;
+};
+
+static void onAsyncError(AMediaCodec* codec, void* userdata, media_status_t err, int32_t actionCode,
+                         const char* detail) {
+    CallBackHandle* self = (CallBackHandle*)userdata;
+    self->mSawError = true;
+    self->receiveError();
+    (void)codec;
+    (void)err;
+    (void)actionCode;
+    (void)detail;
+};
+
+class NdkAsyncCodecFuzzer : public NdkMediaCodecFuzzerBase, public CallBackHandle {
+  public:
+    NdkAsyncCodecFuzzer(const uint8_t* data, size_t size)
+        : NdkMediaCodecFuzzerBase(), mFdp(data, size) {
+        setFdp(&mFdp);
+        mStopCodec = false;
+        mSawInputEOS = false;
+        mSignalledError = false;
+        mIsEncoder = false;
+        mNumOfFrames = 0;
+        mNumInputFrames = 0;
+    };
+    ~NdkAsyncCodecFuzzer() {
+        mIOThreadPool->stop();
+        delete (mIOThreadPool);
+    };
+
+    void process();
+
+    static void codecOnFrameRendered(AMediaCodec* codec, void* userdata, int64_t mediaTimeUs,
+                                     int64_t systemNano) {
+        (void)codec;
+        (void)userdata;
+        (void)mediaTimeUs;
+        (void)systemNano;
+    };
+    class ThreadPool {
+      public:
+        void start();
+        void queueJob(const std::function<void()>& job);
+        void stop();
+
+      private:
+        void ThreadLoop();
+        bool mShouldTerminate = false;
+        std::vector<std::thread> mThreads;
+        std::mutex mQueueMutex;
+        std::condition_variable mQueueMutexCondition;
+        std::queue<std::function<void()>> mJobs;
+    };
+
+  private:
+    FuzzedDataProvider mFdp;
+    AMediaCodec* mCodec = nullptr;
+    void invokeCodecCryptoInfoAPI();
+    void invokekAsyncCodecAPIs(bool isEncoder);
+    void invokeAsyncCodeConfigAPI();
+    void invokeInputBufferAPI(AMediaCodec* codec, int32_t bufferIndex);
+    void invokeOutputBufferAPI(AMediaCodec* codec, int32_t bufferIndex,
+                               AMediaCodecBufferInfo* bufferInfo);
+    void invokeFormatAPI(AMediaCodec* codec);
+    void receiveError();
+    bool mStopCodec;
+    bool mSawInputEOS;
+    bool mSignalledError;
+    int32_t mNumOfFrames;
+    int32_t mNumInputFrames;
+    mutable Mutex mMutex;
+    bool mIsEncoder;
+    ThreadPool* mIOThreadPool = new ThreadPool();
+};
+
+void NdkAsyncCodecFuzzer::ThreadPool::start() {
+    const uint32_t numThreads = std::thread::hardware_concurrency();
+    mThreads.resize(numThreads);
+    for (uint32_t i = 0; i < numThreads; ++i) {
+        mThreads.at(i) = std::thread(&ThreadPool::ThreadLoop, this);
+    }
+}
+
+void NdkAsyncCodecFuzzer::ThreadPool::ThreadLoop() {
+    while (true) {
+        std::function<void()> job;
+        {
+            std::unique_lock<std::mutex> lock(mQueueMutex);
+            mQueueMutexCondition.wait(lock, [this] { return !mJobs.empty() || mShouldTerminate; });
+            if (mShouldTerminate) {
+                return;
+            }
+            job = mJobs.front();
+            mJobs.pop();
+        }
+        job();
+    }
+}
+
+void NdkAsyncCodecFuzzer::ThreadPool::queueJob(const std::function<void()>& job) {
+    {
+        std::unique_lock<std::mutex> lock(mQueueMutex);
+        mJobs.push(job);
+    }
+    mQueueMutexCondition.notify_one();
+}
+
+void NdkAsyncCodecFuzzer::ThreadPool::stop() {
+    {
+        std::unique_lock<std::mutex> lock(mQueueMutex);
+        mShouldTerminate = true;
+    }
+    mQueueMutexCondition.notify_all();
+    for (std::thread& active_thread : mThreads) {
+        active_thread.join();
+    }
+    mThreads.clear();
+}
+
+void NdkAsyncCodecFuzzer::receiveError(void) {
+    mSignalledError = true;
+}
+
+void NdkAsyncCodecFuzzer::invokeInputBufferAPI(AMediaCodec* codec, int32_t bufferIndex) {
+    size_t bufferSize = 0;
+    Mutex::Autolock autoLock(mMutex);
+    if (mSignalledError) {
+        CallBackHandle::mSawError = true;
+        return;
+    }
+    if (mStopCodec || bufferIndex < 0 || mSawInputEOS) {
+        return;
+    }
+
+    uint8_t* buffer = AMediaCodec_getInputBuffer(codec, bufferIndex, &bufferSize);
+    if (buffer) {
+        std::vector<uint8_t> bytesRead = mFdp.ConsumeBytes<uint8_t>(
+                std::min(mFdp.ConsumeIntegralInRange<size_t>(kMinBytes, kMaxBytes), bufferSize));
+        memcpy(buffer, bytesRead.data(), bytesRead.size());
+        bufferSize = bytesRead.size();
+    } else {
+        mSignalledError = true;
+        return;
+    }
+
+    uint32_t flag = 0;
+    if (!bufferSize || mNumInputFrames == mNumOfFrames) {
+        flag |= AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM;
+        mSawInputEOS = true;
+    }
+    AMediaCodec_queueInputBuffer(codec, bufferIndex, 0 /* offset */, bufferSize, 0 /* time */,
+                                 flag);
+    mNumInputFrames++;
+}
+
+void NdkAsyncCodecFuzzer::invokeOutputBufferAPI(AMediaCodec* codec, int32_t bufferIndex,
+                                                AMediaCodecBufferInfo* bufferInfo) {
+    size_t bufferSize = 0;
+    Mutex::Autolock autoLock(mMutex);
+
+    if (mSignalledError) {
+        CallBackHandle::mSawError = true;
+        return;
+    }
+
+    if (mStopCodec || bufferIndex < 0 || mIsDone) {
+        return;
+    }
+
+    if (!mIsEncoder) {
+        (void)AMediaCodec_getOutputBuffer(codec, bufferIndex, &bufferSize);
+    }
+    AMediaCodec_releaseOutputBuffer(codec, bufferIndex, mFdp.ConsumeBool());
+    mIsDone = (0 != (bufferInfo->flags & AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM));
+}
+
+void NdkAsyncCodecFuzzer::invokeFormatAPI(AMediaCodec* codec) {
+    AMediaFormat* codecFormat = nullptr;
+    if (mFdp.ConsumeBool()) {
+        codecFormat = AMediaCodec_getInputFormat(codec);
+    } else {
+        codecFormat = AMediaCodec_getOutputFormat(codec);
+    }
+    if (codecFormat) {
+        AMediaFormat_delete(codecFormat);
+    }
+}
+
+void NdkAsyncCodecFuzzer::invokekAsyncCodecAPIs(bool isEncoder) {
+    ANativeWindow* nativeWindow = nullptr;
+
+    if (mFdp.ConsumeBool()) {
+        AMediaCodec_createInputSurface(mCodec, &nativeWindow);
+    }
+
+    if (AMEDIA_OK == AMediaCodec_configure(mCodec, getCodecFormat(), nativeWindow,
+                                           nullptr /* crypto */,
+                                           (isEncoder ? AMEDIACODEC_CONFIGURE_FLAG_ENCODE : 0))) {
+        mNumOfFrames = mFdp.ConsumeIntegralInRange<size_t>(kMinIterations, kMaxIterations);
+        // Configure codecs to run in async mode.
+        AMediaCodecOnAsyncNotifyCallback callBack = {onAsyncInputAvailable, onAsyncOutputAvailable,
+                                                     onAsyncFormatChanged, onAsyncError};
+        AMediaCodec_setAsyncNotifyCallback(mCodec, callBack, this);
+        mIOThreadPool->queueJob([this] { CallBackHandle::ioThread(); });
+
+        AMediaCodec_start(mCodec);
+        sleep(5);
+        int32_t count = 0;
+        while (++count <= mNumOfFrames) {
+            int32_t ndkcodecAPI =
+                    mFdp.ConsumeIntegralInRange<size_t>(kMinAPICase, kMaxNdkCodecAPIs);
+            switch (ndkcodecAPI) {
+                case 0: {  // get input and output Format
+                    invokeFormatAPI(mCodec);
+                    break;
+                }
+                case 1: {
+                    AMediaCodec_signalEndOfInputStream(mCodec);
+                    mSawInputEOS = true;
+                    break;
+                }
+                case 2: {  // set parameters
+                    // Create a new parameter and set
+                    AMediaFormat* params = AMediaFormat_new();
+                    AMediaFormat_setInt32(
+                            params, "video-bitrate",
+                            mFdp.ConsumeIntegralInRange<size_t>(kMinIntKeyValue, kMaxIntKeyValue));
+                    AMediaCodec_setParameters(mCodec, params);
+                    AMediaFormat_delete(params);
+                    break;
+                }
+                case 3: {  // flush codec
+                    AMediaCodec_flush(mCodec);
+                    if (mFdp.ConsumeBool()) {
+                        AMediaCodec_start(mCodec);
+                    }
+                    break;
+                }
+                case 4: {
+                    char* name = nullptr;
+                    AMediaCodec_getName(mCodec, &name);
+                    AMediaCodec_releaseName(mCodec, name);
+                    break;
+                }
+                case 5:
+                default: {
+                    std::vector<uint8_t> userData = mFdp.ConsumeBytes<uint8_t>(
+                            mFdp.ConsumeIntegralInRange<size_t>(kMinBytes, kMaxBytes));
+                    AMediaCodecOnFrameRendered callback = codecOnFrameRendered;
+                    AMediaCodec_setOnFrameRenderedCallback(mCodec, callback, userData.data());
+                    break;
+                }
+            }
+        }
+        {
+            Mutex::Autolock autoLock(mMutex);
+            mStopCodec = 1;
+            AMediaCodec_stop(mCodec);
+        }
+    }
+
+    if (nativeWindow) {
+        ANativeWindow_release(nativeWindow);
+    }
+}
+
+void NdkAsyncCodecFuzzer::invokeAsyncCodeConfigAPI() {
+    mIOThreadPool->start();
+
+    while (mFdp.remaining_bytes() > 0) {
+        mIsEncoder = mFdp.ConsumeBool();
+        mCodec = createCodec(mIsEncoder, mFdp.ConsumeBool() /* isCodecForClient */);
+        if (mCodec) {
+            invokekAsyncCodecAPIs(mIsEncoder);
+            AMediaCodec_delete(mCodec);
+        }
+    }
+    mIOThreadPool->stop();
+}
+
+void NdkAsyncCodecFuzzer::invokeCodecCryptoInfoAPI() {
+    while (mFdp.remaining_bytes() > 0) {
+        AMediaCodecCryptoInfo* cryptoInfo = getAMediaCodecCryptoInfo();
+        int32_t ndkCryptoInfoAPI =
+                mFdp.ConsumeIntegralInRange<size_t>(kMinAPICase, kMaxCryptoInfoAPIs);
+        switch (ndkCryptoInfoAPI) {
+            case 0: {
+                size_t sizes[kMaxCryptoKey];
+                AMediaCodecCryptoInfo_getEncryptedBytes(cryptoInfo, sizes);
+                break;
+            }
+            case 1: {
+                size_t sizes[kMaxCryptoKey];
+                AMediaCodecCryptoInfo_getClearBytes(cryptoInfo, sizes);
+                break;
+            }
+            case 2: {
+                uint8_t bytes[kMaxCryptoKey];
+                AMediaCodecCryptoInfo_getIV(cryptoInfo, bytes);
+                break;
+            }
+            case 3:
+            default: {
+                uint8_t bytes[kMaxCryptoKey];
+                AMediaCodecCryptoInfo_getKey(cryptoInfo, bytes);
+                break;
+            }
+        }
+        AMediaCodecCryptoInfo_delete(cryptoInfo);
+    }
+}
+
+void NdkAsyncCodecFuzzer::process() {
+    if (mFdp.ConsumeBool()) {
+        invokeCodecCryptoInfoAPI();
+    } else {
+        invokeAsyncCodeConfigAPI();
+    }
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+    NdkAsyncCodecFuzzer ndkAsyncCodecFuzzer(data, size);
+    ndkAsyncCodecFuzzer.process();
+    return 0;
+}
diff --git a/media/ndk/fuzzer/ndk_crypto_fuzzer.cpp b/media/ndk/fuzzer/ndk_crypto_fuzzer.cpp
index 2b22f0f..a759ae7 100644
--- a/media/ndk/fuzzer/ndk_crypto_fuzzer.cpp
+++ b/media/ndk/fuzzer/ndk_crypto_fuzzer.cpp
@@ -20,10 +20,12 @@
 constexpr size_t kMaxString = 256;
 constexpr size_t kMinBytes = 0;
 constexpr size_t kMaxBytes = 1000;
+constexpr size_t kMaxRuns = 100;
 
 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
     FuzzedDataProvider fdp(data, size);
     AMediaUUID uuid = {};
+    size_t apiCount = 0;
     int32_t maxLen = fdp.ConsumeIntegralInRange<size_t>(kMinBytes, (size_t)sizeof(AMediaUUID));
     for (size_t idx = 0; idx < maxLen; ++idx) {
         uuid[idx] = fdp.ConsumeIntegral<uint8_t>();
@@ -31,7 +33,14 @@
     std::vector<uint8_t> initData =
             fdp.ConsumeBytes<uint8_t>(fdp.ConsumeIntegralInRange<size_t>(kMinBytes, kMaxBytes));
     AMediaCrypto* crypto = AMediaCrypto_new(uuid, initData.data(), initData.size());
-    while (fdp.remaining_bytes()) {
+    /*
+     * The AMediaCrypto_isCryptoSchemeSupported API doesn't consume any input bytes,
+     * so when PickValueInArray() selects it repeatedly, only one byte is consumed by 'fdp'.
+     * As a result, on larger inputs, AMediaCrypto_isCryptoSchemeSupported can run a large
+     * number of times, potentially causing a timeout crash.
+     * Therefore, to prevent this issue, while loop is limited to kMaxRuns.
+     */
+    while (fdp.remaining_bytes() && ++apiCount <= kMaxRuns) {
         auto invokeNdkCryptoFuzzer = fdp.PickValueInArray<const std::function<void()>>({
                 [&]() {
                     AMediaCrypto_requiresSecureDecoderComponent(
diff --git a/media/ndk/fuzzer/ndk_mediaformat_fuzzer.cpp b/media/ndk/fuzzer/ndk_mediaformat_fuzzer.cpp
index c19ea13..23e2eaf 100644
--- a/media/ndk/fuzzer/ndk_mediaformat_fuzzer.cpp
+++ b/media/ndk/fuzzer/ndk_mediaformat_fuzzer.cpp
@@ -18,6 +18,7 @@
 #include <fcntl.h>
 #include <fuzzer/FuzzedDataProvider.h>
 #include <media/NdkMediaFormat.h>
+#include <media/stagefright/foundation/AMessage.h>
 #include <sys/mman.h>
 #include <unistd.h>
 #include <utils/Log.h>
@@ -176,11 +177,13 @@
 constexpr size_t kMaxBytes = 1000;
 constexpr size_t kMinChoice = 0;
 constexpr size_t kMaxChoice = 9;
+const size_t kMaxIteration = android::AMessage::maxAllowedEntries();
 
 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
     FuzzedDataProvider fdp(data, size);
     AMediaFormat* mediaFormat = AMediaFormat_new();
-    while (fdp.remaining_bytes()) {
+    std::vector<std::string> nameCollection;
+    while (fdp.remaining_bytes() && nameCollection.size() < kMaxIteration) {
         const char* name = nullptr;
         std::string nameString;
         if (fdp.ConsumeBool()) {
@@ -190,6 +193,11 @@
                             : fdp.ConsumeRandomLengthString(
                                       fdp.ConsumeIntegralInRange<size_t>(kMinBytes, kMaxBytes));
             name = nameString.c_str();
+            std::vector<std::string>::iterator it =
+                    find(nameCollection.begin(), nameCollection.end(), name);
+            if (it == nameCollection.end()) {
+                nameCollection.push_back(name);
+            }
         }
         switch (fdp.ConsumeIntegralInRange<int32_t>(kMinChoice, kMaxChoice)) {
             case 0: {
diff --git a/media/ndk/include/media/NdkImageReader.h b/media/ndk/include/media/NdkImageReader.h
index b6dcaae..48a0a82 100644
--- a/media/ndk/include/media/NdkImageReader.h
+++ b/media/ndk/include/media/NdkImageReader.h
@@ -540,9 +540,11 @@
  *
  * @return AMEDIA_OK if the method call succeeds.
  *         AMEDIA_ERROR_INVALID_PARAMETER if reader or handle are NULL.
- *         AMEDIA_ERROR_UNKNOWN if some other error is encountered.
+ *         AMEDIA_ERROR_UNKNOWN if some other error is encountered or
+ *         the device no longer has android.hidl.token service to
+ *         satisfy the request because it is deprecated.
  */
-media_status_t AImageReader_getWindowNativeHandle(
+[[deprecated]] media_status_t AImageReader_getWindowNativeHandle(
     AImageReader *reader, /* out */native_handle_t **handle);
 #endif
 
diff --git a/media/utils/Android.bp b/media/utils/Android.bp
index 7abb0b6..07dac5e 100644
--- a/media/utils/Android.bp
+++ b/media/utils/Android.bp
@@ -179,3 +179,8 @@
     local_include_dirs: ["include"],
     export_include_dirs: ["include"],
 }
+
+cc_library_headers {
+    name: "mediautils_headers",
+    export_include_dirs: ["include", "."],
+}
diff --git a/media/utils/tests/Android.bp b/media/utils/tests/Android.bp
index 0689083..3fdc6eb 100644
--- a/media/utils/tests/Android.bp
+++ b/media/utils/tests/Android.bp
@@ -200,7 +200,10 @@
     name: "timerthread_tests",
 
     defaults: ["libmediautils_tests_defaults"],
-
+    // TODO(b/270180838)
+    test_options: {
+        unit_test: false,
+    },
     srcs: [
         "TimerThread-test.cpp",
     ],
diff --git a/services/audioflinger/Android.bp b/services/audioflinger/Android.bp
index 17e6d15..7663250 100644
--- a/services/audioflinger/Android.bp
+++ b/services/audioflinger/Android.bp
@@ -138,30 +138,8 @@
     ],
 }
 
-cc_library_shared {
-    name: "libaudioflinger",
-
-    defaults: [
-        "latest_android_media_audio_common_types_cpp_shared",
-        "latest_android_hardware_audio_core_sounddose_ndk_shared",
-        "audioflinger_flags_defaults",
-    ],
-
-    srcs: [
-        "AudioFlinger.cpp",
-        "DeviceEffectManager.cpp",
-        "Effects.cpp",
-        "MelReporter.cpp",
-        "PatchCommandThread.cpp",
-        "PatchPanel.cpp",
-        "Threads.cpp",
-        "Tracks.cpp",
-    ],
-
-    include_dirs: [
-        "frameworks/av/services/audiopolicy",
-        "frameworks/av/services/medialog",
-    ],
+cc_defaults {
+    name: "libaudioflinger_dependencies",
 
     shared_libs: [
         "audioflinger-aidl-cpp",
@@ -177,7 +155,6 @@
         "libaudiofoundation",
         "libaudiohal",
         "libaudioprocessing",
-        "libaudiospdif",
         "libaudioutils",
         "libcutils",
         "libutils",
@@ -186,7 +163,6 @@
         "libbinder_ndk",
         "libaudioclient",
         "libaudiomanager",
-        "libmedialogservice",
         "libmediametrics",
         "libmediautils",
         "libnbaio",
@@ -202,6 +178,40 @@
     ],
 
     static_libs: [
+        "libmedialogservice",
+        "libaudiospdif",
+    ],
+}
+
+
+cc_library {
+    name: "libaudioflinger",
+
+    defaults: [
+        "libaudioflinger_dependencies",
+        "latest_android_media_audio_common_types_cpp_shared",
+        "latest_android_hardware_audio_core_sounddose_ndk_shared",
+        "audioflinger_flags_defaults",
+    ],
+
+    srcs: [
+        "AudioFlinger.cpp",
+        "Client.cpp",
+        "DeviceEffectManager.cpp",
+        "Effects.cpp",
+        "MelReporter.cpp",
+        "PatchCommandThread.cpp",
+        "PatchPanel.cpp",
+        "Threads.cpp",
+        "Tracks.cpp",
+    ],
+
+    include_dirs: [
+        "frameworks/av/services/audiopolicy",
+        "frameworks/av/services/medialog",
+    ],
+
+    static_libs: [
         "libcpustats",
         "libpermission",
     ],
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 262f6f4..1e59bf8 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -15,7 +15,6 @@
 ** limitations under the License.
 */
 
-
 #define LOG_TAG "AudioFlinger"
 //#define LOG_NDEBUG 0
 
@@ -23,71 +22,44 @@
 #define AUDIO_ARRAYS_STATIC_CHECK 1
 
 #include "Configuration.h"
-#include <dirent.h>
-#include <math.h>
-#include <signal.h>
-#include <string>
-#include <sys/time.h>
-#include <sys/resource.h>
-#include <thread>
-
-#include <android-base/stringprintf.h>
-#include <android/media/IAudioPolicyService.h>
-#include <android/os/IExternalVibratorService.h>
-#include <binder/IPCThreadState.h>
-#include <binder/IServiceManager.h>
-#include <utils/Log.h>
-#include <utils/Trace.h>
-#include <binder/Parcel.h>
-#include <media/audiohal/AudioHalVersionInfo.h>
-#include <media/audiohal/DeviceHalInterface.h>
-#include <media/audiohal/DevicesFactoryHalInterface.h>
-#include <media/audiohal/EffectsFactoryHalInterface.h>
-#include <media/AudioParameter.h>
-#include <media/MediaMetricsItem.h>
-#include <media/TypeConverter.h>
-#include <mediautils/TimeCheck.h>
-#include <memunreachable/memunreachable.h>
-#include <utils/String16.h>
-#include <utils/threads.h>
-
-#include <cutils/atomic.h>
-#include <cutils/properties.h>
-
-#include <system/audio.h>
-#include <audiomanager/IAudioManager.h>
-
 #include "AudioFlinger.h"
 #include "EffectConfiguration.h"
+
+//#define BUFLOG_NDEBUG 0
+#include <afutils/BufLog.h>
+#include <afutils/DumpTryLock.h>
+#include <afutils/Permission.h>
 #include <afutils/PropertyUtils.h>
-
-#include <media/AudioResamplerPublic.h>
-
-#include <system/audio_effects/effect_visualizer.h>
-#include <system/audio_effects/effect_ns.h>
-#include <system/audio_effects/effect_aec.h>
-#include <system/audio_effects/effect_hapticgenerator.h>
-#include <system/audio_effects/effect_spatializer.h>
-
-#include <audio_utils/primitives.h>
-
-#include <powermanager/PowerManager.h>
-
-#include <media/IMediaLogService.h>
+#include <afutils/TypedLogger.h>
+#include <android-base/stringprintf.h>
+#include <android/media/IAudioPolicyService.h>
+#include <audiomanager/IAudioManager.h>
+#include <binder/IPCThreadState.h>
+#include <binder/IServiceManager.h>
+#include <binder/Parcel.h>
+#include <cutils/properties.h>
 #include <media/AidlConversion.h>
+#include <media/AudioParameter.h>
 #include <media/AudioValidator.h>
-#include <media/nbaio/Pipe.h>
-#include <media/nbaio/PipeReader.h>
+#include <media/IMediaLogService.h>
+#include <media/MediaMetricsItem.h>
+#include <media/TypeConverter.h>
 #include <mediautils/BatteryNotifier.h>
 #include <mediautils/MemoryLeakTrackUtil.h>
 #include <mediautils/MethodStatistics.h>
 #include <mediautils/ServiceUtilities.h>
 #include <mediautils/TimeCheck.h>
-#include <private/android_filesystem_config.h>
+#include <memunreachable/memunreachable.h>
+// required for effect matching
+#include <system/audio_effects/effect_aec.h>
+#include <system/audio_effects/effect_ns.h>
+#include <system/audio_effects/effect_spatializer.h>
+#include <system/audio_effects/effect_visualizer.h>
+#include <utils/Log.h>
 
-//#define BUFLOG_NDEBUG 0
-#include <afutils/BufLog.h>
-#include <afutils/TypedLogger.h>
+// not needed with the includes above, added to prevent transitive include dependency.
+#include <chrono>
+#include <thread>
 
 // ----------------------------------------------------------------------------
 
@@ -124,10 +96,6 @@
 
 static constexpr char kAudioServiceName[] = "audio";
 
-nsecs_t AudioFlinger::mStandbyTimeInNsecs = kDefaultStandbyTimeInNsecs;
-
-uint32_t AudioFlinger::mScreenState;
-
 // In order to avoid invalidating offloaded tracks each time a Visualizer is turned on and off
 // we define a minimum time during which a global effect is considered enabled.
 static const nsecs_t kMinGlobalEffectEnabletimeNs = seconds(7200);
@@ -148,21 +116,6 @@
     }
 }
 
-// Keep a strong reference to external vibrator service
-static sp<os::IExternalVibratorService> sExternalVibratorService;
-
-static sp<os::IExternalVibratorService> getExternalVibratorService() {
-    if (sExternalVibratorService == 0) {
-        sp<IBinder> binder = defaultServiceManager()->getService(
-            String16("external_vibrator_service"));
-        if (binder != 0) {
-            sExternalVibratorService =
-                interface_cast<os::IExternalVibratorService>(binder);
-        }
-    }
-    return sExternalVibratorService;
-}
-
 // Creates association between Binder code to name for IAudioFlinger.
 #define IAUDIOFLINGER_BINDER_METHOD_MACRO_LIST \
 BINDER_METHOD_ENTRY(createTrack) \
@@ -269,41 +222,6 @@
     }
 };
 
-// TODO b/182392769: use attribution source util
-/* static */
-AttributionSourceState AudioFlinger::checkAttributionSourcePackage(
-        const AttributionSourceState& attributionSource) {
-    Vector<String16> packages;
-    PermissionController{}.getPackagesForUid(attributionSource.uid, packages);
-
-    AttributionSourceState checkedAttributionSource = attributionSource;
-    if (!attributionSource.packageName.has_value()
-            || attributionSource.packageName.value().size() == 0) {
-        if (!packages.isEmpty()) {
-            checkedAttributionSource.packageName =
-                std::move(legacy2aidl_String16_string(packages[0]).value());
-        }
-    } else {
-        String16 opPackageLegacy = VALUE_OR_FATAL(
-            aidl2legacy_string_view_String16(attributionSource.packageName.value_or("")));
-        if (std::find_if(packages.begin(), packages.end(),
-                [&opPackageLegacy](const auto& package) {
-                return opPackageLegacy == package; }) == packages.end()) {
-            ALOGW("The package name(%s) provided does not correspond to the uid %d",
-                    attributionSource.packageName.value_or("").c_str(), attributionSource.uid);
-        }
-    }
-    return checkedAttributionSource;
-}
-
-// ----------------------------------------------------------------------------
-
-std::string formatToString(audio_format_t format) {
-    std::string result;
-    FormatConverter::toString(format, result);
-    return result;
-}
-
 // ----------------------------------------------------------------------------
 
 void AudioFlinger::instantiate() {
@@ -328,10 +246,7 @@
       mTotalMemory(0),
       mClientSharedHeapSize(kMinimumClientSharedHeapSizeBytes),
       mGlobalEffectEnableTime(0),
-      mPatchPanel(this),
       mPatchCommandThread(sp<PatchCommandThread>::make()),
-      mDeviceEffectManager(sp<DeviceEffectManager>::make(*this)),
-      mMelReporter(sp<MelReporter>::make(*this)),
       mSystemReady(false),
       mBluetoothLatencyModesEnabled(true)
 {
@@ -388,24 +303,11 @@
 {
     Mutex::Autolock _l(mLock);
 
-    /* TODO: move all this work into an Init() function */
-    char val_str[PROPERTY_VALUE_MAX] = { 0 };
-    if (property_get("ro.audio.flinger_standbytime_ms", val_str, NULL) >= 0) {
-        uint32_t int_val;
-        if (1 == sscanf(val_str, "%u", &int_val)) {
-            mStandbyTimeInNsecs = milliseconds(int_val);
-            ALOGI("Using %u mSec as standby time.", int_val);
-        } else {
-            mStandbyTimeInNsecs = kDefaultStandbyTimeInNsecs;
-            ALOGI("Using default %u mSec as standby time.",
-                    (uint32_t)(mStandbyTimeInNsecs / 1000000));
-        }
-    }
-
     mMode = AUDIO_MODE_NORMAL;
 
     gAudioFlinger = this;  // we are already refcounted, store into atomic pointer.
-
+    mDeviceEffectManager = sp<DeviceEffectManager>::make(
+            sp<IAfDeviceEffectManagerCallback>::fromExisting(this)),
     mDevicesFactoryHalCallback = new DevicesFactoryHalCallbackImpl;
     mDevicesFactoryHal->setCallbackOnce(mDevicesFactoryHalCallback);
 
@@ -413,6 +315,9 @@
         mAAudioBurstsPerBuffer = getAAudioMixerBurstCountFromSystemProperty();
         mAAudioHwBurstMinMicros = getAAudioHardwareBurstMinUsecFromSystemProperty();
     }
+
+    mPatchPanel = IAfPatchPanel::create(sp<IAfPatchPanelCallback>::fromExisting(this));
+    mMelReporter = sp<MelReporter>::make(sp<IAfMelReporterCallback>::fromExisting(this));
 }
 
 status_t AudioFlinger::setAudioHalPids(const std::vector<pid_t>& pids) {
@@ -433,9 +338,9 @@
     for (const auto& [trackId, secondaryOutputs] : trackSecondaryOutputs) {
         size_t i = 0;
         for (; i < mPlaybackThreads.size(); ++i) {
-            PlaybackThread *thread = mPlaybackThreads.valueAt(i).get();
-            Mutex::Autolock _tl(thread->mLock);
-            sp<PlaybackThread::Track> track = thread->getTrackById_l(trackId);
+            IAfPlaybackThread* thread = mPlaybackThreads.valueAt(i).get();
+            Mutex::Autolock _tl(thread->mutex());
+            sp<IAfTrack> track = thread->getTrackById_l(trackId);
             if (track != nullptr) {
                 ALOGD("%s trackId: %u", __func__, trackId);
                 updateSecondaryOutputsForTrack_l(track.get(), thread, secondaryOutputs);
@@ -476,12 +381,12 @@
     return NO_ERROR;
 }
 
-int32_t AudioFlinger::getAAudioMixerBurstCount() {
+int32_t AudioFlinger::getAAudioMixerBurstCount() const {
     Mutex::Autolock _l(mLock);
     return mAAudioBurstsPerBuffer;
 }
 
-int32_t AudioFlinger::getAAudioHardwareBurstMinUsec() {
+int32_t AudioFlinger::getAAudioHardwareBurstMinUsec() const {
     Mutex::Autolock _l(mLock);
     return mAAudioHwBurstMinMicros;
 }
@@ -527,7 +432,7 @@
 }
 
 // getDefaultVibratorInfo_l must be called with AudioFlinger lock held.
-std::optional<media::AudioVibratorInfo> AudioFlinger::getDefaultVibratorInfo_l() {
+std::optional<media::AudioVibratorInfo> AudioFlinger::getDefaultVibratorInfo_l() const {
     if (mAudioVibratorInfos.empty()) {
         return {};
     }
@@ -580,7 +485,7 @@
                                              sp<MmapStreamInterface>& interface,
                                              audio_port_handle_t *handle)
 {
-    // TODO: Use ServiceManager to get IAudioFlinger instead of by atomic pointer.
+    // TODO(b/292281786): Use ServiceManager to get IAudioFlinger instead of by atomic pointer.
     // This allows moving oboeservice (AAudio) to a separate process in the future.
     sp<AudioFlinger> af = AudioFlinger::gAudioFlinger.load();  // either nullptr or singleton AF.
     status_t ret = NO_INIT;
@@ -638,7 +543,7 @@
                  __func__, callingUid, callingPid, clientPid);
         adjAttributionSource.pid = VALUE_OR_RETURN_STATUS(legacy2aidl_pid_t_int32_t(callingPid));
     }
-    adjAttributionSource = AudioFlinger::checkAttributionSourcePackage(
+    adjAttributionSource = afutils::checkAttributionSourcePackage(
             adjAttributionSource);
 
     if (direction == MmapStreamInterface::DIRECTION_OUTPUT) {
@@ -678,9 +583,9 @@
 
     // at this stage, a MmapThread was created when openOutput() or openInput() was called by
     // audio policy manager and we can retrieve it
-    sp<MmapThread> thread = mMmapThreads.valueFor(io);
+    const sp<IAfMmapThread> thread = mMmapThreads.valueFor(io);
     if (thread != 0) {
-        interface = new MmapThreadHandle(thread);
+        interface = IAfMmapThread::createMmapStreamInterfaceAdapter(thread);
         thread->configure(&localAttr, streamType, actualSessionId, callback, *deviceId, portId);
         *handle = portId;
         *sessionId = actualSessionId;
@@ -701,34 +606,6 @@
     return ret;
 }
 
-/* static */
-os::HapticScale AudioFlinger::onExternalVibrationStart(
-        const sp<os::ExternalVibration>& externalVibration) {
-    sp<os::IExternalVibratorService> evs = getExternalVibratorService();
-    if (evs != nullptr) {
-        int32_t ret;
-        binder::Status status = evs->onExternalVibrationStart(*externalVibration, &ret);
-        if (status.isOk()) {
-            ALOGD("%s, start external vibration with intensity as %d", __func__, ret);
-            return os::ExternalVibration::externalVibrationScaleToHapticScale(ret);
-        }
-    }
-    ALOGD("%s, start external vibration with intensity as MUTE due to %s",
-            __func__,
-            evs == nullptr ? "external vibration service not found"
-                           : "error when querying intensity");
-    return os::HapticScale::MUTE;
-}
-
-/* static */
-void AudioFlinger::onExternalVibrationStop(const sp<os::ExternalVibration>& externalVibration) {
-    sp<os::IExternalVibratorService> evs = getExternalVibratorService();
-    if (evs != 0) {
-        ALOGD("%s, stopping external vibration", __func__);
-        evs->onExternalVibrationStop(*externalVibration);
-    }
-}
-
 status_t AudioFlinger::addEffectToHal(
         const struct audio_port_config *device, const sp<EffectHalInterface>& effect) {
     AutoMutex lock(mHardwareLock);
@@ -829,10 +706,7 @@
     String8 result;
     hardware_call_state hardwareStatus = mHardwareStatus;
 
-    snprintf(buffer, SIZE, "Hardware status: %d\n"
-                           "Standby Time mSec: %u\n",
-                            hardwareStatus,
-                            (uint32_t)(mStandbyTimeInNsecs / 1000000));
+    snprintf(buffer, SIZE, "Hardware status: %d\n", hardwareStatus);
     result.append(buffer);
     write(fd, result.string(), result.size());
 
@@ -857,12 +731,6 @@
     write(fd, result.string(), result.size());
 }
 
-bool AudioFlinger::dumpTryLock(Mutex& mutex)
-{
-    status_t err = mutex.timedLock(kDumpLockTimeoutNs);
-    return err == NO_ERROR;
-}
-
 status_t AudioFlinger::dump(int fd, const Vector<String16>& args)
 NO_THREAD_SAFETY_ANALYSIS  // conditional try lock
 {
@@ -870,7 +738,7 @@
         dumpPermissionDenial(fd, args);
     } else {
         // get state of hardware lock
-        bool hardwareLocked = dumpTryLock(mHardwareLock);
+        const bool hardwareLocked = afutils::dumpTryLock(mHardwareLock);
         if (!hardwareLocked) {
             String8 result(kHardwareLockedString);
             write(fd, result.string(), result.size());
@@ -878,7 +746,7 @@
             mHardwareLock.unlock();
         }
 
-        const bool locked = dumpTryLock(mLock);
+        const bool locked = afutils::dumpTryLock(mLock);
 
         // failed to lock - AudioFlinger is probably deadlocked
         if (!locked) {
@@ -886,7 +754,7 @@
             write(fd, result.string(), result.size());
         }
 
-        bool clientLocked = dumpTryLock(mClientLock);
+        const bool clientLocked = afutils::dumpTryLock(mClientLock);
         if (!clientLocked) {
             String8 result(kClientLockedString);
             write(fd, result.string(), result.size());
@@ -934,7 +802,7 @@
             dev->dump(fd, args);
         }
 
-        mPatchPanel.dump(fd);
+        mPatchPanel->dump(fd);
 
         mDeviceEffectManager->dump(fd);
 
@@ -1036,7 +904,7 @@
     // (for which promote() is always != 0), otherwise create a new entry and Client.
     sp<Client> client = mClients.valueFor(pid).promote();
     if (client == 0) {
-        client = new Client(this, pid);
+        client = sp<Client>::make(sp<IAfClientCallback>::fromExisting(this), pid);
         mClients.add(pid, client);
     }
 
@@ -1107,7 +975,7 @@
     CreateTrackInput input = VALUE_OR_RETURN_STATUS(CreateTrackInput::fromAidl(_input));
     CreateTrackOutput output;
 
-    sp<PlaybackThread::Track> track;
+    sp<IAfTrack> track;
     sp<Client> client;
     status_t lStatus;
     audio_stream_type_t streamType;
@@ -1144,7 +1012,7 @@
         clientPid = callingPid;
         adjAttributionSource.pid = VALUE_OR_RETURN_STATUS(legacy2aidl_pid_t_int32_t(callingPid));
     }
-    adjAttributionSource = AudioFlinger::checkAttributionSourcePackage(
+    adjAttributionSource = afutils::checkAttributionSourcePackage(
             adjAttributionSource);
 
     audio_session_t sessionId = input.sessionId;
@@ -1191,7 +1059,7 @@
 
     {
         Mutex::Autolock _l(mLock);
-        PlaybackThread *thread = checkPlaybackThread_l(output.outputId);
+        IAfPlaybackThread* thread = checkPlaybackThread_l(output.outputId);
         if (thread == NULL) {
             ALOGE("no playback thread found for output handle %d", output.outputId);
             lStatus = BAD_VALUE;
@@ -1200,14 +1068,14 @@
 
         client = registerPid(clientPid);
 
-        PlaybackThread *effectThread = NULL;
+        IAfPlaybackThread* effectThread = nullptr;
         // check if an effect chain with the same session ID is present on another
         // output thread and move it here.
         for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
-            sp<PlaybackThread> t = mPlaybackThreads.valueAt(i);
+            sp<IAfPlaybackThread> t = mPlaybackThreads.valueAt(i);
             if (mPlaybackThreads.keyAt(i) != output.outputId) {
                 uint32_t sessions = t->hasAudioSession(sessionId);
-                if (sessions & ThreadBase::EFFECT_SESSION) {
+                if (sessions & IAfThreadBase::EFFECT_SESSION) {
                     effectThread = t.get();
                     break;
                 }
@@ -1242,7 +1110,7 @@
 
         if (lStatus == NO_ERROR) {
             // no risk of deadlock because AudioFlinger::mLock is held
-            Mutex::Autolock _dl(thread->mLock);
+            Mutex::Autolock _dl(thread->mutex());
             // Connect secondary outputs. Failure on a secondary output must not imped the primary
             // Any secondary output setup failure will lead to a desync between the AP and AF until
             // the track is destroyed.
@@ -1250,7 +1118,7 @@
             // move effect chain to this output thread if an effect on same session was waiting
             // for a track to be created
             if (effectThread != nullptr) {
-                Mutex::Autolock _sl(effectThread->mLock);
+                Mutex::Autolock _sl(effectThread->mutex());
                 if (moveEffectChain_l(sessionId, effectThread, thread) == NO_ERROR) {
                     effectThreadId = thread->id();
                     effectIds = thread->getEffectIds_l(sessionId);
@@ -1297,7 +1165,7 @@
         AudioSystem::moveEffectsToIo(effectIds, effectThreadId);
     }
 
-    output.audioTrack = PlaybackThread::Track::createIAudioTrackAdapter(track);
+    output.audioTrack = IAfTrack::createIAudioTrackAdapter(track);
     _output = VALUE_OR_FATAL(output.toAidl());
 
 Exit:
@@ -1310,7 +1178,7 @@
 uint32_t AudioFlinger::sampleRate(audio_io_handle_t ioHandle) const
 {
     Mutex::Autolock _l(mLock);
-    ThreadBase *thread = checkThread_l(ioHandle);
+    IAfThreadBase* const thread = checkThread_l(ioHandle);
     if (thread == NULL) {
         ALOGW("sampleRate() unknown thread %d", ioHandle);
         return 0;
@@ -1321,7 +1189,7 @@
 audio_format_t AudioFlinger::format(audio_io_handle_t output) const
 {
     Mutex::Autolock _l(mLock);
-    PlaybackThread *thread = checkPlaybackThread_l(output);
+    IAfPlaybackThread* const thread = checkPlaybackThread_l(output);
     if (thread == NULL) {
         ALOGW("format() unknown thread %d", output);
         return AUDIO_FORMAT_INVALID;
@@ -1332,7 +1200,7 @@
 size_t AudioFlinger::frameCount(audio_io_handle_t ioHandle) const
 {
     Mutex::Autolock _l(mLock);
-    ThreadBase *thread = checkThread_l(ioHandle);
+    IAfThreadBase* const thread = checkThread_l(ioHandle);
     if (thread == NULL) {
         ALOGW("frameCount() unknown thread %d", ioHandle);
         return 0;
@@ -1345,7 +1213,7 @@
 size_t AudioFlinger::frameCountHAL(audio_io_handle_t ioHandle) const
 {
     Mutex::Autolock _l(mLock);
-    ThreadBase *thread = checkThread_l(ioHandle);
+    IAfThreadBase* const thread = checkThread_l(ioHandle);
     if (thread == NULL) {
         ALOGW("frameCountHAL() unknown thread %d", ioHandle);
         return 0;
@@ -1356,7 +1224,7 @@
 uint32_t AudioFlinger::latency(audio_io_handle_t output) const
 {
     Mutex::Autolock _l(mLock);
-    PlaybackThread *thread = checkPlaybackThread_l(output);
+    IAfPlaybackThread* const thread = checkPlaybackThread_l(output);
     if (thread == NULL) {
         ALOGW("latency(): no playback thread found for output handle %d", output);
         return 0;
@@ -1585,7 +1453,7 @@
     // assigned to HALs which do not have master mute support will apply master mute
     // during the mix operation.  Threads with HALs which do support master mute
     // will simply ignore the setting.
-    Vector<VolumeInterface *> volumeInterfaces = getAllVolumeInterfaces_l();
+    std::vector<sp<VolumeInterface>> volumeInterfaces = getAllVolumeInterfaces_l();
     for (size_t i = 0; i < volumeInterfaces.size(); i++) {
         volumeInterfaces[i]->setMasterMute(muted);
     }
@@ -1661,7 +1529,7 @@
                         "AUDIO_STREAM_PATCH must have full scale volume");
 
     AutoMutex lock(mLock);
-    VolumeInterface *volumeInterface = getVolumeInterface_l(output);
+    sp<VolumeInterface> volumeInterface = getVolumeInterface_l(output);
     if (volumeInterface == NULL) {
         return BAD_VALUE;
     }
@@ -1676,7 +1544,7 @@
         return BAD_VALUE;
     }
     AutoMutex lock(mLock);
-    PlaybackThread *thread = checkPlaybackThread_l(output);
+    IAfPlaybackThread* const thread = checkPlaybackThread_l(output);
     if (thread == nullptr) {
         return BAD_VALUE;
     }
@@ -1684,12 +1552,12 @@
 }
 
 status_t AudioFlinger::getSupportedLatencyModes(audio_io_handle_t output,
-            std::vector<audio_latency_mode_t>* modes) {
+            std::vector<audio_latency_mode_t>* modes) const {
     if (output == AUDIO_IO_HANDLE_NONE) {
         return BAD_VALUE;
     }
     AutoMutex lock(mLock);
-    PlaybackThread *thread = checkPlaybackThread_l(output);
+    IAfPlaybackThread* const thread = checkPlaybackThread_l(output);
     if (thread == nullptr) {
         return BAD_VALUE;
     }
@@ -1711,7 +1579,7 @@
     return status;
 }
 
-status_t AudioFlinger::isBluetoothVariableLatencyEnabled(bool *enabled) {
+status_t AudioFlinger::isBluetoothVariableLatencyEnabled(bool* enabled) const {
     if (enabled == nullptr) {
         return BAD_VALUE;
     }
@@ -1719,7 +1587,7 @@
     return NO_ERROR;
 }
 
-status_t AudioFlinger::supportsBluetoothVariableLatency(bool* support) {
+status_t AudioFlinger::supportsBluetoothVariableLatency(bool* support) const {
     if (support == nullptr) {
         return BAD_VALUE;
     }
@@ -1735,7 +1603,7 @@
 }
 
 status_t AudioFlinger::getSoundDoseInterface(const sp<media::ISoundDoseCallback>& callback,
-                                             sp<media::ISoundDose>* soundDose) {
+                                             sp<media::ISoundDose>* soundDose) const {
     if (soundDose == nullptr) {
         return BAD_VALUE;
     }
@@ -1764,7 +1632,7 @@
 
     AutoMutex lock(mLock);
     mStreamTypes[stream].mute = muted;
-    Vector<VolumeInterface *> volumeInterfaces = getAllVolumeInterfaces_l();
+    std::vector<sp<VolumeInterface>> volumeInterfaces = getAllVolumeInterfaces_l();
     for (size_t i = 0; i < volumeInterfaces.size(); i++) {
         volumeInterfaces[i]->setStreamMute(stream, muted);
     }
@@ -1783,7 +1651,7 @@
     }
 
     AutoMutex lock(mLock);
-    VolumeInterface *volumeInterface = getVolumeInterface_l(output);
+    sp<VolumeInterface> volumeInterface = getVolumeInterface_l(output);
     if (volumeInterface == NULL) {
         return 0.0f;
     }
@@ -1820,14 +1688,15 @@
 // forwardAudioHwSyncToDownstreamPatches_l() must be called with AudioFlinger::mLock held
 void AudioFlinger::forwardParametersToDownstreamPatches_l(
         audio_io_handle_t upStream, const String8& keyValuePairs,
-        const std::function<bool(const sp<PlaybackThread>&)>& useThread)
+        const std::function<bool(const sp<IAfPlaybackThread>&)>& useThread)
 {
-    std::vector<PatchPanel::SoftwarePatch> swPatches;
-    if (mPatchPanel.getDownstreamSoftwarePatches(upStream, &swPatches) != OK) return;
+    std::vector<SoftwarePatch> swPatches;
+    if (mPatchPanel->getDownstreamSoftwarePatches(upStream, &swPatches) != OK) return;
     ALOGV_IF(!swPatches.empty(), "%s found %zu downstream patches for stream ID %d",
             __func__, swPatches.size(), upStream);
     for (const auto& swPatch : swPatches) {
-        sp<PlaybackThread> downStream = checkPlaybackThread_l(swPatch.getPlaybackThreadHandle());
+        const sp<IAfPlaybackThread> downStream =
+                checkPlaybackThread_l(swPatch.getPlaybackThreadHandle());
         if (downStream != NULL && (useThread == nullptr || useThread(downStream))) {
             downStream->setParameters(keyValuePairs);
         }
@@ -1839,7 +1708,7 @@
                                              const std::set<audio_io_handle_t>& streams)
 {
     for (const audio_io_handle_t stream : streams) {
-        PlaybackThread *playbackThread = checkPlaybackThread_l(stream);
+        IAfPlaybackThread* const playbackThread = checkPlaybackThread_l(stream);
         if (playbackThread == nullptr || !playbackThread->isMsdDevice()) {
             continue;
         }
@@ -1953,8 +1822,8 @@
         String8 screenState;
         if (param.get(String8(AudioParameter::keyScreenState), screenState) == NO_ERROR) {
             bool isOff = (screenState == AudioParameter::valueOff);
-            if (isOff != (AudioFlinger::mScreenState & 1)) {
-                AudioFlinger::mScreenState = ((AudioFlinger::mScreenState & ~1) + 2) | isOff;
+            if (isOff != (mScreenState & 1)) {
+                mScreenState = ((mScreenState & ~1) + 2) | isOff;
             }
         }
         return final_result;
@@ -1962,7 +1831,7 @@
 
     // hold a strong ref on thread in case closeOutput() or closeInput() is called
     // and the thread is exited once the lock is released
-    sp<ThreadBase> thread;
+    sp<IAfThreadBase> thread;
     {
         Mutex::Autolock _l(mLock);
         thread = checkPlaybackThread_l(ioHandle);
@@ -2011,11 +1880,11 @@
         return out_s8;
     }
 
-    ThreadBase *thread = (ThreadBase *)checkPlaybackThread_l(ioHandle);
+    IAfThreadBase* thread = checkPlaybackThread_l(ioHandle);
     if (thread == NULL) {
-        thread = (ThreadBase *)checkRecordThread_l(ioHandle);
+        thread = checkRecordThread_l(ioHandle);
         if (thread == NULL) {
-            thread = (ThreadBase *)checkMmapThread_l(ioHandle);
+            thread = checkMmapThread_l(ioHandle);
             if (thread == NULL) {
                 return String8("");
             }
@@ -2111,7 +1980,7 @@
 {
     Mutex::Autolock _l(mLock);
 
-    RecordThread *recordThread = checkRecordThread_l(ioHandle);
+    IAfRecordThread* const recordThread = checkRecordThread_l(ioHandle);
     if (recordThread != NULL) {
         return recordThread->getInputFramesLost();
     }
@@ -2151,7 +2020,7 @@
 {
     Mutex::Autolock _l(mLock);
 
-    PlaybackThread *playbackThread = checkPlaybackThread_l(output);
+    IAfPlaybackThread* const playbackThread = checkPlaybackThread_l(output);
     if (playbackThread != NULL) {
         return playbackThread->getRenderPosition(halFrames, dspFrames);
     }
@@ -2225,6 +2094,9 @@
         }
         if (removed) {
             removedEffects = purgeStaleEffects_l();
+            std::vector< sp<IAfEffectModule> > removedOrphanEffects = purgeOrphanEffectChains_l();
+            removedEffects.insert(removedEffects.end(), removedOrphanEffects.begin(),
+                    removedOrphanEffects.end());
         }
     }
     for (auto& effect : removedEffects) {
@@ -2274,10 +2146,10 @@
 }
 
 // getEffectThread_l() must be called with AudioFlinger::mLock held
-sp<AudioFlinger::ThreadBase> AudioFlinger::getEffectThread_l(audio_session_t sessionId,
+sp<IAfThreadBase> AudioFlinger::getEffectThread_l(audio_session_t sessionId,
         int effectId)
 {
-    sp<ThreadBase> thread;
+    sp<IAfThreadBase> thread;
 
     for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
         if (mPlaybackThreads.valueAt(i)->getEffect(sessionId, effectId) != 0) {
@@ -2306,27 +2178,6 @@
     return thread;
 }
 
-
-
-// ----------------------------------------------------------------------------
-
-Client::Client(const sp<AudioFlinger>& audioFlinger, pid_t pid)
-    :   RefBase(),
-        mAudioFlinger(audioFlinger),
-        mPid(pid),
-        mClientAllocator(AllocatorFactory::getClientAllocator()) {}
-
-// Client destructor must be called with AudioFlinger::mClientLock held
-Client::~Client()
-{
-    mAudioFlinger->removeClient_l(mPid);
-}
-
-AllocatorFactory::ClientAllocator& Client::allocator()
-{
-    return mClientAllocator;
-}
-
 // ----------------------------------------------------------------------------
 
 AudioFlinger::NotificationClient::NotificationClient(const sp<AudioFlinger>& audioFlinger,
@@ -2391,7 +2242,7 @@
     CreateRecordInput input = VALUE_OR_RETURN_STATUS(CreateRecordInput::fromAidl(_input));
     CreateRecordOutput output;
 
-    sp<RecordThread::RecordTrack> recordTrack;
+    sp<IAfRecordTrack> recordTrack;
     sp<Client> client;
     status_t lStatus;
     audio_session_t sessionId = input.sessionId;
@@ -2423,7 +2274,7 @@
                  __func__, callingUid, callingPid, currentPid);
         adjAttributionSource.pid = VALUE_OR_RETURN_STATUS(legacy2aidl_pid_t_int32_t(callingPid));
     }
-    adjAttributionSource = AudioFlinger::checkAttributionSourcePackage(
+    adjAttributionSource = afutils::checkAttributionSourcePackage(
             adjAttributionSource);
     // we don't yet support anything other than linear PCM
     if (!audio_is_valid_format(input.config.format) || !audio_is_linear_pcm(input.config.format)) {
@@ -2480,7 +2331,7 @@
 
     {
         Mutex::Autolock _l(mLock);
-        RecordThread *thread = checkRecordThread_l(output.inputId);
+        IAfRecordThread* const thread = checkRecordThread_l(output.inputId);
         if (thread == NULL) {
             ALOGW("createRecord() checkRecordThread_l failed, input handle %d", output.inputId);
             lStatus = FAILED_TRANSACTION;
@@ -2536,7 +2387,7 @@
         // session and move it to this thread.
         sp<IAfEffectChain> chain = getOrphanEffectChain_l(sessionId);
         if (chain != 0) {
-            Mutex::Autolock _l2(thread->mLock);
+            Mutex::Autolock _l2(thread->mutex());
             thread->addEffectChain_l(chain);
         }
         break;
@@ -2549,7 +2400,7 @@
     output.buffers = recordTrack->getBuffers();
     output.portId = portId;
 
-    output.audioRecord = RecordThread::RecordTrack::createIAudioRecordAdapter(recordTrack);
+    output.audioRecord = IAfRecordTrack::createIAudioRecordAdapter(recordTrack);
     _output = VALUE_OR_FATAL(output.toAidl());
 
 Exit:
@@ -2735,17 +2586,17 @@
 
 // ----------------------------------------------------------------------------
 
-uint32_t AudioFlinger::getPrimaryOutputSamplingRate()
+uint32_t AudioFlinger::getPrimaryOutputSamplingRate() const
 {
     Mutex::Autolock _l(mLock);
-    PlaybackThread *thread = fastPlaybackThread_l();
+    IAfPlaybackThread* const thread = fastPlaybackThread_l();
     return thread != NULL ? thread->sampleRate() : 0;
 }
 
-size_t AudioFlinger::getPrimaryOutputFrameCount()
+size_t AudioFlinger::getPrimaryOutputFrameCount() const
 {
     Mutex::Autolock _l(mLock);
-    PlaybackThread *thread = fastPlaybackThread_l();
+    IAfPlaybackThread* const thread = fastPlaybackThread_l();
     return thread != NULL ? thread->frameCountHAL() : 0;
 }
 
@@ -2870,15 +2721,15 @@
     mHwAvSyncIds.add(sessionId, value);
 
     for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
-        sp<PlaybackThread> thread = mPlaybackThreads.valueAt(i);
+        const sp<IAfPlaybackThread> thread = mPlaybackThreads.valueAt(i);
         uint32_t sessions = thread->hasAudioSession(sessionId);
-        if (sessions & ThreadBase::TRACK_SESSION) {
+        if (sessions & IAfThreadBase::TRACK_SESSION) {
             AudioParameter param = AudioParameter();
             param.addInt(String8(AudioParameter::keyStreamHwAvSync), value);
             String8 keyValuePairs = param.toString();
             thread->setParameters(keyValuePairs);
             forwardParametersToDownstreamPatches_l(thread->id(), keyValuePairs,
-                    [](const sp<PlaybackThread>& thread) { return thread->usesHwAvSync(); });
+                    [](const sp<IAfPlaybackThread>& thread) { return thread->usesHwAvSync(); });
             break;
         }
     }
@@ -2897,15 +2748,15 @@
     }
     mSystemReady = true;
     for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
-        ThreadBase *thread = (ThreadBase *)mPlaybackThreads.valueAt(i).get();
+        IAfThreadBase* const thread = mPlaybackThreads.valueAt(i).get();
         thread->systemReady();
     }
     for (size_t i = 0; i < mRecordThreads.size(); i++) {
-        ThreadBase *thread = (ThreadBase *)mRecordThreads.valueAt(i).get();
+        IAfThreadBase* const thread = mRecordThreads.valueAt(i).get();
         thread->systemReady();
     }
     for (size_t i = 0; i < mMmapThreads.size(); i++) {
-        ThreadBase *thread = (ThreadBase *)mMmapThreads.valueAt(i).get();
+        IAfThreadBase* const thread = mMmapThreads.valueAt(i).get();
         thread->systemReady();
     }
 
@@ -2930,7 +2781,7 @@
     return mAudioManager.load();
 }
 
-status_t AudioFlinger::getMicrophones(std::vector<media::MicrophoneInfoFw> *microphones)
+status_t AudioFlinger::getMicrophones(std::vector<media::MicrophoneInfoFw>* microphones) const
 {
     AutoMutex lock(mHardwareLock);
     status_t status = INVALID_OPERATION;
@@ -2957,7 +2808,8 @@
 }
 
 // setAudioHwSyncForSession_l() must be called with AudioFlinger::mLock held
-void AudioFlinger::setAudioHwSyncForSession_l(PlaybackThread *thread, audio_session_t sessionId)
+void AudioFlinger::setAudioHwSyncForSession_l(
+        IAfPlaybackThread* const thread, audio_session_t sessionId)
 {
     ssize_t index = mHwAvSyncIds.indexOfKey(sessionId);
     if (index >= 0) {
@@ -2968,7 +2820,7 @@
         String8 keyValuePairs = param.toString();
         thread->setParameters(keyValuePairs);
         forwardParametersToDownstreamPatches_l(thread->id(), keyValuePairs,
-                [](const sp<PlaybackThread>& thread) { return thread->usesHwAvSync(); });
+                [](const sp<IAfPlaybackThread>& thread) { return thread->usesHwAvSync(); });
     }
 }
 
@@ -2976,7 +2828,7 @@
 // ----------------------------------------------------------------------------
 
 
-sp<AudioFlinger::ThreadBase> AudioFlinger::openOutput_l(audio_module_handle_t module,
+sp<IAfThreadBase> AudioFlinger::openOutput_l(audio_module_handle_t module,
                                                         audio_io_handle_t *output,
                                                         audio_config_t *halConfig,
                                                         audio_config_base_t *mixerConfig,
@@ -2999,28 +2851,6 @@
     }
 
     mHardwareStatus = AUDIO_HW_OUTPUT_OPEN;
-
-    // FOR TESTING ONLY:
-    // This if statement allows overriding the audio policy settings
-    // and forcing a specific format or channel mask to the HAL/Sink device for testing.
-    if (!(flags & (AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD | AUDIO_OUTPUT_FLAG_DIRECT))) {
-        // Check only for Normal Mixing mode
-        if (kEnableExtendedPrecision) {
-            // Specify format (uncomment one below to choose)
-            //halConfig->format = AUDIO_FORMAT_PCM_FLOAT;
-            //halConfig->format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
-            //halConfig->format = AUDIO_FORMAT_PCM_32_BIT;
-            //halConfig->format = AUDIO_FORMAT_PCM_8_24_BIT;
-            // ALOGV("openOutput_l() upgrading format to %#08x", halConfig->format);
-        }
-        if (kEnableExtendedChannels) {
-            // Specify channel mask (uncomment one below to choose)
-            //halConfig->channel_mask = audio_channel_out_mask_from_count(4);  // for USB 4ch
-            //halConfig->channel_mask = audio_channel_mask_from_representation_and_bits(
-            //        AUDIO_CHANNEL_REPRESENTATION_INDEX, (1 << 4) - 1);  // another 4ch example
-        }
-    }
-
     AudioStreamOut *outputStream = NULL;
     status_t status = outHwDev->openOutputStream(
             &outputStream,
@@ -3034,43 +2864,45 @@
 
     if (status == NO_ERROR) {
         if (flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) {
-            sp<MmapPlaybackThread> thread =
-                    new MmapPlaybackThread(this, *output, outHwDev, outputStream, mSystemReady);
+            const sp<IAfMmapPlaybackThread> thread = IAfMmapPlaybackThread::create(
+                    this, *output, outHwDev, outputStream, mSystemReady);
             mMmapThreads.add(*output, thread);
             ALOGV("openOutput_l() created mmap playback thread: ID %d thread %p",
                   *output, thread.get());
             return thread;
         } else {
-            sp<PlaybackThread> thread;
+            sp<IAfPlaybackThread> thread;
             if (flags & AUDIO_OUTPUT_FLAG_BIT_PERFECT) {
-                thread = sp<BitPerfectThread>::make(this, outputStream, *output, mSystemReady);
+                thread = IAfPlaybackThread::createBitPerfectThread(
+                        this, outputStream, *output, mSystemReady);
                 ALOGV("%s() created bit-perfect output: ID %d thread %p",
                       __func__, *output, thread.get());
             } else if (flags & AUDIO_OUTPUT_FLAG_SPATIALIZER) {
-                thread = new SpatializerThread(this, outputStream, *output,
+                thread = IAfPlaybackThread::createSpatializerThread(this, outputStream, *output,
                                                     mSystemReady, mixerConfig);
                 ALOGV("openOutput_l() created spatializer output: ID %d thread %p",
                       *output, thread.get());
             } else if (flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
-                thread = new OffloadThread(this, outputStream, *output,
+                thread = IAfPlaybackThread::createOffloadThread(this, outputStream, *output,
                         mSystemReady, halConfig->offload_info);
                 ALOGV("openOutput_l() created offload output: ID %d thread %p",
                       *output, thread.get());
             } else if ((flags & AUDIO_OUTPUT_FLAG_DIRECT)
-                    || !isValidPcmSinkFormat(halConfig->format)
-                    || !isValidPcmSinkChannelMask(halConfig->channel_mask)) {
-                thread = new DirectOutputThread(this, outputStream, *output,
+                    || !IAfThreadBase::isValidPcmSinkFormat(halConfig->format)
+                    || !IAfThreadBase::isValidPcmSinkChannelMask(halConfig->channel_mask)) {
+                thread = IAfPlaybackThread::createDirectOutputThread(this, outputStream, *output,
                         mSystemReady, halConfig->offload_info);
                 ALOGV("openOutput_l() created direct output: ID %d thread %p",
                       *output, thread.get());
             } else {
-                thread = new MixerThread(this, outputStream, *output, mSystemReady);
+                thread = IAfPlaybackThread::createMixerThread(
+                        this, outputStream, *output, mSystemReady);
                 ALOGV("openOutput_l() created mixer output: ID %d thread %p",
                       *output, thread.get());
             }
             mPlaybackThreads.add(*output, thread);
             struct audio_patch patch;
-            mPatchPanel.notifyStreamOpened(outHwDev, *output, &patch);
+            mPatchPanel->notifyStreamOpened(outHwDev, *output, &patch);
             if (thread->isMsdDevice()) {
                 thread->setDownStreamPatch(&patch);
             }
@@ -3116,12 +2948,12 @@
 
     Mutex::Autolock _l(mLock);
 
-    sp<ThreadBase> thread = openOutput_l(module, &output, &halConfig,
+    const sp<IAfThreadBase> thread = openOutput_l(module, &output, &halConfig,
             &mixerConfig, deviceType, address, flags);
     if (thread != 0) {
         uint32_t latencyMs = 0;
         if ((flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) == 0) {
-            PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
+            const auto playbackThread = thread->asIAfPlaybackThread();
             latencyMs = playbackThread->latency();
 
             // notify client processes of the new output creation
@@ -3139,8 +2971,7 @@
                 mHardwareStatus = AUDIO_HW_IDLE;
             }
         } else {
-            MmapThread *mmapThread = (MmapThread *)thread.get();
-            mmapThread->ioConfigChanged(AUDIO_OUTPUT_OPENED);
+            thread->ioConfigChanged(AUDIO_OUTPUT_OPENED);
         }
         response->output = VALUE_OR_RETURN_STATUS(legacy2aidl_audio_io_handle_t_int32_t(output));
         response->config = VALUE_OR_RETURN_STATUS(
@@ -3158,8 +2989,8 @@
         audio_io_handle_t output2)
 {
     Mutex::Autolock _l(mLock);
-    MixerThread *thread1 = checkMixerThread_l(output1);
-    MixerThread *thread2 = checkMixerThread_l(output2);
+    IAfPlaybackThread* const thread1 = checkMixerThread_l(output1);
+    IAfPlaybackThread* const thread2 = checkMixerThread_l(output2);
 
     if (thread1 == NULL || thread2 == NULL) {
         ALOGW("openDuplicateOutput() wrong output mixer type for output %d or %d", output1,
@@ -3168,7 +2999,8 @@
     }
 
     audio_io_handle_t id = nextUniqueId(AUDIO_UNIQUE_ID_USE_OUTPUT);
-    DuplicatingThread *thread = new DuplicatingThread(this, thread1, id, mSystemReady);
+    const sp<IAfDuplicatingThread> thread = IAfDuplicatingThread::create(
+            this, thread1, id, mSystemReady);
     thread->addOutputTrack(thread2);
     mPlaybackThreads.add(id, thread);
     // notify client processes of the new output creation
@@ -3185,8 +3017,8 @@
 {
     // keep strong reference on the playback thread so that
     // it is not destroyed while exit() is executed
-    sp<PlaybackThread> playbackThread;
-    sp<MmapPlaybackThread> mmapThread;
+    sp<IAfPlaybackThread> playbackThread;
+    sp<IAfMmapPlaybackThread> mmapThread;
     {
         Mutex::Autolock _l(mLock);
         playbackThread = checkPlaybackThread_l(output);
@@ -3195,12 +3027,12 @@
 
             dumpToThreadLog_l(playbackThread);
 
-            if (playbackThread->type() == ThreadBase::MIXER) {
+            if (playbackThread->type() == IAfThreadBase::MIXER) {
                 for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
                     if (mPlaybackThreads.valueAt(i)->isDuplicating()) {
-                        DuplicatingThread *dupThread =
-                                (DuplicatingThread *)mPlaybackThreads.valueAt(i).get();
-                        dupThread->removeOutputTrack((MixerThread *)playbackThread.get());
+                        IAfDuplicatingThread* const dupThread =
+                                mPlaybackThreads.valueAt(i)->asIAfDuplicatingThread().get();
+                        dupThread->removeOutputTrack(playbackThread.get());
                     }
                 }
             }
@@ -3209,11 +3041,12 @@
             mPlaybackThreads.removeItem(output);
             // save all effects to the default thread
             if (mPlaybackThreads.size()) {
-                PlaybackThread *dstThread = checkPlaybackThread_l(mPlaybackThreads.keyAt(0));
+                IAfPlaybackThread* const dstThread =
+                        checkPlaybackThread_l(mPlaybackThreads.keyAt(0));
                 if (dstThread != NULL) {
                     // audioflinger lock is held so order of thread lock acquisition doesn't matter
-                    Mutex::Autolock _dl(dstThread->mLock);
-                    Mutex::Autolock _sl(playbackThread->mLock);
+                    Mutex::Autolock _dl(dstThread->mutex());
+                    Mutex::Autolock _sl(playbackThread->mutex());
                     Vector<sp<IAfEffectChain>> effectChains = playbackThread->getEffectChains_l();
                     for (size_t i = 0; i < effectChains.size(); i ++) {
                         moveEffectChain_l(effectChains[i]->sessionId(), playbackThread.get(),
@@ -3222,7 +3055,8 @@
                 }
             }
         } else {
-            mmapThread = (MmapPlaybackThread *)checkMmapThread_l(output);
+            const sp<IAfMmapThread> mt = checkMmapThread_l(output);
+            mmapThread = mt ? mt->asIAfMmapPlaybackThread().get() : nullptr;
             if (mmapThread == 0) {
                 return BAD_VALUE;
             }
@@ -3231,10 +3065,10 @@
             ALOGD("closing mmapThread %p", mmapThread.get());
         }
         ioConfigChanged(AUDIO_OUTPUT_CLOSED, sp<AudioIoDescriptor>::make(output));
-        mPatchPanel.notifyStreamClosed(output);
+        mPatchPanel->notifyStreamClosed(output);
     }
     // The thread entity (active unit of execution) is no longer running here,
-    // but the ThreadBase container still exists.
+    // but the IAfThreadBase container still exists.
 
     if (playbackThread != 0) {
         playbackThread->exit();
@@ -3252,7 +3086,7 @@
     return NO_ERROR;
 }
 
-void AudioFlinger::closeOutputFinish(const sp<PlaybackThread>& thread)
+void AudioFlinger::closeOutputFinish(const sp<IAfPlaybackThread>& thread)
 {
     AudioStreamOut *out = thread->clearOutput();
     ALOG_ASSERT(out != NULL, "out shouldn't be NULL");
@@ -3260,9 +3094,9 @@
     delete out;
 }
 
-void AudioFlinger::closeThreadInternal_l(const sp<PlaybackThread>& thread)
+void AudioFlinger::closeThreadInternal_l(const sp<IAfPlaybackThread>& thread)
 {
-    mPlaybackThreads.removeItem(thread->mId);
+    mPlaybackThreads.removeItem(thread->id());
     thread->exit();
     closeOutputFinish(thread);
 }
@@ -3270,7 +3104,7 @@
 status_t AudioFlinger::suspendOutput(audio_io_handle_t output)
 {
     Mutex::Autolock _l(mLock);
-    PlaybackThread *thread = checkPlaybackThread_l(output);
+    IAfPlaybackThread* const thread = checkPlaybackThread_l(output);
 
     if (thread == NULL) {
         return BAD_VALUE;
@@ -3285,7 +3119,7 @@
 status_t AudioFlinger::restoreOutput(audio_io_handle_t output)
 {
     Mutex::Autolock _l(mLock);
-    PlaybackThread *thread = checkPlaybackThread_l(output);
+    IAfPlaybackThread* const thread = checkPlaybackThread_l(output);
 
     if (thread == NULL) {
         return BAD_VALUE;
@@ -3314,7 +3148,7 @@
     audio_config_t config = VALUE_OR_RETURN_STATUS(
             aidl2legacy_AudioConfig_audio_config_t(request.config, true /*isInput*/));
 
-    sp<ThreadBase> thread = openInput_l(
+    const sp<IAfThreadBase> thread = openInput_l(
             VALUE_OR_RETURN_STATUS(aidl2legacy_int32_t_audio_module_handle_t(request.module)),
             &input,
             &config,
@@ -3338,7 +3172,7 @@
     return NO_INIT;
 }
 
-sp<AudioFlinger::ThreadBase> AudioFlinger::openInput_l(audio_module_handle_t module,
+sp<IAfThreadBase> AudioFlinger::openInput_l(audio_module_handle_t module,
                                                          audio_io_handle_t *input,
                                                          audio_config_t *config,
                                                          audio_devices_t devices,
@@ -3404,17 +3238,18 @@
     if (status == NO_ERROR && inStream != 0) {
         AudioStreamIn *inputStream = new AudioStreamIn(inHwDev, inStream, flags);
         if ((flags & AUDIO_INPUT_FLAG_MMAP_NOIRQ) != 0) {
-            sp<MmapCaptureThread> thread =
-                    new MmapCaptureThread(this, *input, inHwDev, inputStream, mSystemReady);
+            const sp<IAfMmapCaptureThread> thread =
+                    IAfMmapCaptureThread::create(this, *input, inHwDev, inputStream, mSystemReady);
             mMmapThreads.add(*input, thread);
             ALOGV("openInput_l() created mmap capture thread: ID %d thread %p", *input,
                     thread.get());
             return thread;
         } else {
             // 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, mSystemReady);
+            // IAfRecordThread requires both input and output device indication
+            // to forward to audio pre processing modules
+            const sp<IAfRecordThread> thread =
+                    IAfRecordThread::create(this, inputStream, *input, mSystemReady);
             mRecordThreads.add(*input, thread);
             ALOGV("openInput_l() created record thread: ID %d thread %p", *input, thread.get());
             return thread;
@@ -3434,8 +3269,8 @@
 {
     // keep strong reference on the record thread so that
     // it is not destroyed while exit() is executed
-    sp<RecordThread> recordThread;
-    sp<MmapCaptureThread> mmapThread;
+    sp<IAfRecordThread> recordThread;
+    sp<IAfMmapCaptureThread> mmapThread;
     {
         Mutex::Autolock _l(mLock);
         recordThread = checkRecordThread_l(input);
@@ -3450,8 +3285,8 @@
             // new capture on the same session
             sp<IAfEffectChain> chain;
             {
-                Mutex::Autolock _sl(recordThread->mLock);
-                Vector< sp<IAfEffectChain> > effectChains = recordThread->getEffectChains_l();
+                Mutex::Autolock _sl(recordThread->mutex());
+                const Vector<sp<IAfEffectChain>> effectChains = recordThread->getEffectChains_l();
                 // Note: maximum one chain per record thread
                 if (effectChains.size() != 0) {
                     chain = effectChains[0];
@@ -3463,12 +3298,12 @@
                 // creation of its replacement
                 size_t i;
                 for (i = 0; i < mRecordThreads.size(); i++) {
-                    sp<RecordThread> t = mRecordThreads.valueAt(i);
+                    const sp<IAfRecordThread> t = mRecordThreads.valueAt(i);
                     if (t == recordThread) {
                         continue;
                     }
                     if (t->hasAudioSession(chain->sessionId()) != 0) {
-                        Mutex::Autolock _l2(t->mLock);
+                        Mutex::Autolock _l2(t->mutex());
                         ALOGV("closeInput() found thread %d for effect session %d",
                               t->id(), chain->sessionId());
                         t->addEffectChain_l(chain);
@@ -3482,7 +3317,8 @@
             }
             mRecordThreads.removeItem(input);
         } else {
-            mmapThread = (MmapCaptureThread *)checkMmapThread_l(input);
+            const sp<IAfMmapThread> mt = checkMmapThread_l(input);
+            mmapThread = mt ? mt->asIAfMmapCaptureThread().get() : nullptr;
             if (mmapThread == 0) {
                 return BAD_VALUE;
             }
@@ -3505,7 +3341,7 @@
     return NO_ERROR;
 }
 
-void AudioFlinger::closeInputFinish(const sp<RecordThread>& thread)
+void AudioFlinger::closeInputFinish(const sp<IAfRecordThread>& thread)
 {
     thread->exit();
     AudioStreamIn *in = thread->clearInput();
@@ -3514,9 +3350,9 @@
     delete in;
 }
 
-void AudioFlinger::closeThreadInternal_l(const sp<RecordThread>& thread)
+void AudioFlinger::closeThreadInternal_l(const sp<IAfRecordThread>& thread)
 {
-    mRecordThreads.removeItem(thread->mId);
+    mRecordThreads.removeItem(thread->id());
     closeInputFinish(thread);
 }
 
@@ -3526,7 +3362,7 @@
 
     std::set<audio_port_handle_t> portIdSet(portIds.begin(), portIds.end());
     for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
-        PlaybackThread *thread = mPlaybackThreads.valueAt(i).get();
+        IAfPlaybackThread* const thread = mPlaybackThreads.valueAt(i).get();
         thread->invalidateTracks(portIdSet);
         if (portIdSet.empty()) {
             return NO_ERROR;
@@ -3646,14 +3482,15 @@
 
     ALOGV("purging stale effects");
 
-    Vector< sp<IAfEffectChain> > chains;
+    Vector<sp<IAfEffectChain>> chains;
     std::vector< sp<IAfEffectModule> > removedEffects;
 
     for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
-        sp<PlaybackThread> t = mPlaybackThreads.valueAt(i);
-        Mutex::Autolock _l(t->mLock);
-        for (size_t j = 0; j < t->mEffectChains.size(); j++) {
-            sp<IAfEffectChain> ec = t->mEffectChains[j];
+        sp<IAfPlaybackThread> t = mPlaybackThreads.valueAt(i);
+        Mutex::Autolock _l(t->mutex());
+        const Vector<sp<IAfEffectChain>> threadChains = t->getEffectChains_l();
+        for (size_t j = 0; j < threadChains.size(); j++) {
+            sp<IAfEffectChain> ec = threadChains[j];
             if (!audio_is_global_session(ec->sessionId())) {
                 chains.push(ec);
             }
@@ -3661,19 +3498,21 @@
     }
 
     for (size_t i = 0; i < mRecordThreads.size(); i++) {
-        sp<RecordThread> t = mRecordThreads.valueAt(i);
-        Mutex::Autolock _l(t->mLock);
-        for (size_t j = 0; j < t->mEffectChains.size(); j++) {
-            sp<IAfEffectChain> ec = t->mEffectChains[j];
+        sp<IAfRecordThread> t = mRecordThreads.valueAt(i);
+        Mutex::Autolock _l(t->mutex());
+        const Vector<sp<IAfEffectChain>> threadChains = t->getEffectChains_l();
+        for (size_t j = 0; j < threadChains.size(); j++) {
+            sp<IAfEffectChain> ec = threadChains[j];
             chains.push(ec);
         }
     }
 
     for (size_t i = 0; i < mMmapThreads.size(); i++) {
-        sp<MmapThread> t = mMmapThreads.valueAt(i);
-        Mutex::Autolock _l(t->mLock);
-        for (size_t j = 0; j < t->mEffectChains.size(); j++) {
-            sp<IAfEffectChain> ec = t->mEffectChains[j];
+        const sp<IAfMmapThread> t = mMmapThreads.valueAt(i);
+        Mutex::Autolock _l(t->mutex());
+        const Vector<sp<IAfEffectChain>> threadChains = t->getEffectChains_l();
+        for (size_t j = 0; j < threadChains.size(); j++) {
+            sp<IAfEffectChain> ec = threadChains[j];
             chains.push(ec);
         }
     }
@@ -3682,7 +3521,7 @@
          // clang-tidy suggests const ref
         sp<IAfEffectChain> ec = chains[i];  // NOLINT(performance-unnecessary-copy-initialization)
         int sessionid = ec->sessionId();
-        sp<ThreadBase> t = sp<ThreadBase>::cast(ec->thread().promote()); // TODO(b/288339104)
+        const auto t = ec->thread().promote();
         if (t == 0) {
             continue;
         }
@@ -3698,7 +3537,7 @@
             }
         }
         if (!found) {
-            Mutex::Autolock _l(t->mLock);
+            Mutex::Autolock _l(t->mutex());
             // remove all effects from the chain
             while (ec->numberOfEffects()) {
                 sp<IAfEffectModule> effect = ec->getEffectModule(0);
@@ -3714,8 +3553,44 @@
     return removedEffects;
 }
 
+std::vector< sp<IAfEffectModule> > AudioFlinger::purgeOrphanEffectChains_l()
+{
+    ALOGV("purging stale effects from orphan chains");
+    std::vector< sp<IAfEffectModule> > removedEffects;
+    for (size_t index = 0; index < mOrphanEffectChains.size(); index++) {
+        sp<IAfEffectChain> chain = mOrphanEffectChains.valueAt(index);
+        audio_session_t session = mOrphanEffectChains.keyAt(index);
+        if (session == AUDIO_SESSION_OUTPUT_MIX || session == AUDIO_SESSION_DEVICE
+                || session == AUDIO_SESSION_OUTPUT_STAGE) {
+            continue;
+        }
+        size_t numSessionRefs = mAudioSessionRefs.size();
+        bool found = false;
+        for (size_t k = 0; k < numSessionRefs; k++) {
+            AudioSessionRef *ref = mAudioSessionRefs.itemAt(k);
+            if (ref->mSessionid == session) {
+                ALOGV(" session %d still exists for %d with %d refs", session, ref->mPid,
+                        ref->mCnt);
+                found = true;
+                break;
+            }
+        }
+        if (!found) {
+            for (size_t i = 0; i < chain->numberOfEffects(); i++) {
+                sp<IAfEffectModule> effect = chain->getEffectModule(i);
+                removedEffects.push_back(effect);
+            }
+        }
+    }
+    for (auto& effect : removedEffects) {
+        effect->unPin();
+        updateOrphanEffectChains_l(effect);
+    }
+    return removedEffects;
+}
+
 // dumpToThreadLog_l() must be called with AudioFlinger::mLock held
-void AudioFlinger::dumpToThreadLog_l(const sp<ThreadBase> &thread)
+void AudioFlinger::dumpToThreadLog_l(const sp<IAfThreadBase> &thread)
 {
     constexpr int THREAD_DUMP_TIMEOUT_MS = 2;
     audio_utils::FdToString fdToString("- ", THREAD_DUMP_TIMEOUT_MS);
@@ -3727,9 +3602,9 @@
 }
 
 // checkThread_l() must be called with AudioFlinger::mLock held
-AudioFlinger::ThreadBase *AudioFlinger::checkThread_l(audio_io_handle_t ioHandle) const
+IAfThreadBase* AudioFlinger::checkThread_l(audio_io_handle_t ioHandle) const
 {
-    ThreadBase *thread = checkMmapThread_l(ioHandle);
+    IAfThreadBase* thread = checkMmapThread_l(ioHandle);
     if (thread == 0) {
         switch (audio_unique_id_get_use(ioHandle)) {
         case AUDIO_UNIQUE_ID_USE_OUTPUT:
@@ -3746,13 +3621,13 @@
 }
 
 // checkOutputThread_l() must be called with AudioFlinger::mLock held
-sp<AudioFlinger::ThreadBase> AudioFlinger::checkOutputThread_l(audio_io_handle_t ioHandle) const
+sp<IAfThreadBase> AudioFlinger::checkOutputThread_l(audio_io_handle_t ioHandle) const
 {
     if (audio_unique_id_get_use(ioHandle) != AUDIO_UNIQUE_ID_USE_OUTPUT) {
         return nullptr;
     }
 
-    sp<AudioFlinger::ThreadBase> thread = mPlaybackThreads.valueFor(ioHandle);
+    sp<IAfThreadBase> thread = mPlaybackThreads.valueFor(ioHandle);
     if (thread == nullptr) {
         thread = mMmapThreads.valueFor(ioHandle);
     }
@@ -3760,41 +3635,41 @@
 }
 
 // checkPlaybackThread_l() must be called with AudioFlinger::mLock held
-AudioFlinger::PlaybackThread *AudioFlinger::checkPlaybackThread_l(audio_io_handle_t output) const
+IAfPlaybackThread* AudioFlinger::checkPlaybackThread_l(audio_io_handle_t output) const
 {
     return mPlaybackThreads.valueFor(output).get();
 }
 
 // checkMixerThread_l() must be called with AudioFlinger::mLock held
-AudioFlinger::MixerThread *AudioFlinger::checkMixerThread_l(audio_io_handle_t output) const
+IAfPlaybackThread* AudioFlinger::checkMixerThread_l(audio_io_handle_t output) const
 {
-    PlaybackThread *thread = checkPlaybackThread_l(output);
-    return thread != NULL && thread->type() != ThreadBase::DIRECT ? (MixerThread *) thread : NULL;
+    IAfPlaybackThread * const thread = checkPlaybackThread_l(output);
+    return thread != nullptr && thread->type() != IAfThreadBase::DIRECT ? thread : nullptr;
 }
 
 // checkRecordThread_l() must be called with AudioFlinger::mLock held
-AudioFlinger::RecordThread *AudioFlinger::checkRecordThread_l(audio_io_handle_t input) const
+IAfRecordThread* AudioFlinger::checkRecordThread_l(audio_io_handle_t input) const
 {
     return mRecordThreads.valueFor(input).get();
 }
 
 // checkMmapThread_l() must be called with AudioFlinger::mLock held
-AudioFlinger::MmapThread *AudioFlinger::checkMmapThread_l(audio_io_handle_t io) const
+IAfMmapThread* AudioFlinger::checkMmapThread_l(audio_io_handle_t io) const
 {
     return mMmapThreads.valueFor(io).get();
 }
 
 
 // checkPlaybackThread_l() must be called with AudioFlinger::mLock held
-AudioFlinger::VolumeInterface *AudioFlinger::getVolumeInterface_l(audio_io_handle_t output) const
+sp<VolumeInterface> AudioFlinger::getVolumeInterface_l(audio_io_handle_t output) const
 {
-    VolumeInterface *volumeInterface = mPlaybackThreads.valueFor(output).get();
+    sp<VolumeInterface> volumeInterface = mPlaybackThreads.valueFor(output).get();
     if (volumeInterface == nullptr) {
-        MmapThread *mmapThread = mMmapThreads.valueFor(output).get();
+        IAfMmapThread* const mmapThread = mMmapThreads.valueFor(output).get();
         if (mmapThread != nullptr) {
             if (mmapThread->isOutput()) {
-                MmapPlaybackThread *mmapPlaybackThread =
-                        static_cast<MmapPlaybackThread *>(mmapThread);
+                IAfMmapPlaybackThread* const mmapPlaybackThread =
+                        mmapThread->asIAfMmapPlaybackThread().get();
                 volumeInterface = mmapPlaybackThread;
             }
         }
@@ -3802,17 +3677,17 @@
     return volumeInterface;
 }
 
-Vector <AudioFlinger::VolumeInterface *> AudioFlinger::getAllVolumeInterfaces_l() const
+std::vector<sp<VolumeInterface>> AudioFlinger::getAllVolumeInterfaces_l() const
 {
-    Vector <VolumeInterface *> volumeInterfaces;
+    std::vector<sp<VolumeInterface>> volumeInterfaces;
     for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
-        volumeInterfaces.add(mPlaybackThreads.valueAt(i).get());
+        volumeInterfaces.push_back(mPlaybackThreads.valueAt(i).get());
     }
     for (size_t i = 0; i < mMmapThreads.size(); i++) {
         if (mMmapThreads.valueAt(i)->isOutput()) {
-            MmapPlaybackThread *mmapPlaybackThread =
-                    static_cast<MmapPlaybackThread *>(mMmapThreads.valueAt(i).get());
-            volumeInterfaces.add(mmapPlaybackThread);
+            IAfMmapPlaybackThread* const mmapPlaybackThread =
+                    mMmapThreads.valueAt(i)->asIAfMmapPlaybackThread().get();
+            volumeInterfaces.push_back(mmapPlaybackThread);
         }
     }
     return volumeInterfaces;
@@ -3839,14 +3714,14 @@
     // TODO Use a floor after wraparound.  This may need a mutex.
 }
 
-AudioFlinger::PlaybackThread *AudioFlinger::primaryPlaybackThread_l() const
+IAfPlaybackThread* 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();
+        IAfPlaybackThread* const thread = mPlaybackThreads.valueAt(i).get();
         if(thread->isDuplicating()) {
             continue;
         }
@@ -3860,7 +3735,7 @@
 
 DeviceTypeSet AudioFlinger::primaryOutputDevice_l() const
 {
-    PlaybackThread *thread = primaryPlaybackThread_l();
+    IAfPlaybackThread* const thread = primaryPlaybackThread_l();
 
     if (thread == NULL) {
         return {};
@@ -3869,12 +3744,12 @@
     return thread->outDeviceTypes();
 }
 
-AudioFlinger::PlaybackThread *AudioFlinger::fastPlaybackThread_l() const
+IAfPlaybackThread* AudioFlinger::fastPlaybackThread_l() const
 {
     size_t minFrameCount = 0;
-    PlaybackThread *minThread = NULL;
+    IAfPlaybackThread* minThread = nullptr;
     for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
-        PlaybackThread *thread = mPlaybackThreads.valueAt(i).get();
+        IAfPlaybackThread* const thread = mPlaybackThreads.valueAt(i).get();
         if (!thread->isDuplicating()) {
             size_t frameCount = thread->frameCountHAL();
             if (frameCount != 0 && (minFrameCount == 0 || frameCount < minFrameCount ||
@@ -3888,9 +3763,9 @@
     return minThread;
 }
 
-AudioFlinger::ThreadBase *AudioFlinger::hapticPlaybackThread_l() const {
+IAfThreadBase* AudioFlinger::hapticPlaybackThread_l() const {
     for (size_t i  = 0; i < mPlaybackThreads.size(); ++i) {
-        PlaybackThread *thread = mPlaybackThreads.valueAt(i).get();
+        IAfPlaybackThread* const thread = mPlaybackThreads.valueAt(i).get();
         if (thread->hapticChannelMask() != AUDIO_CHANNEL_NONE) {
             return thread;
         }
@@ -3899,12 +3774,12 @@
 }
 
 void AudioFlinger::updateSecondaryOutputsForTrack_l(
-        PlaybackThread::Track* track,
-        PlaybackThread* thread,
+        IAfTrack* track,
+        IAfPlaybackThread* thread,
         const std::vector<audio_io_handle_t> &secondaryOutputs) const {
     TeePatches teePatches;
     for (audio_io_handle_t secondaryOutput : secondaryOutputs) {
-        PlaybackThread *secondaryThread = checkPlaybackThread_l(secondaryOutput);
+        IAfPlaybackThread* const secondaryThread = checkPlaybackThread_l(secondaryOutput);
         if (secondaryThread == nullptr) {
             ALOGE("no playback thread found for secondary output %d", thread->id());
             continue;
@@ -3930,10 +3805,10 @@
         // The frameCount should also not be smaller than the secondary thread min frame
         // count
         size_t minFrameCount = AudioSystem::calculateMinFrameCount(
-                    [&] { Mutex::Autolock _l(secondaryThread->mLock);
+                    [&] { Mutex::Autolock _l(secondaryThread->mutex());
                           return secondaryThread->latency_l(); }(),
-                    secondaryThread->mNormalFrameCount,
-                    secondaryThread->mSampleRate,
+                    secondaryThread->frameCount(), // normal frame count
+                    secondaryThread->sampleRate(),
                     track->sampleRate(),
                     track->getSpeed());
         frameCount = std::max(frameCount, minFrameCount);
@@ -3946,7 +3821,7 @@
             // use an index mask here to create the PatchRecord.
             inChannelMask = audio_channel_mask_out_to_in_index_mask(track->channelMask());
         }
-        sp patchRecord = new RecordThread::PatchRecord(nullptr /* thread */,
+        sp<IAfPatchRecord> patchRecord = IAfPatchRecord::create(nullptr /* thread */,
                                                        track->sampleRate(),
                                                        inChannelMask,
                                                        track->format(),
@@ -3966,7 +3841,7 @@
         // for now, we exclude fast tracks by removing the Fast flag.
         const audio_output_flags_t outputFlags =
                 (audio_output_flags_t)(track->getOutputFlags() & ~AUDIO_OUTPUT_FLAG_FAST);
-        sp patchTrack = new PlaybackThread::PatchTrack(secondaryThread,
+        sp<IAfPatchTrack> patchTrack = IAfPatchTrack::create(secondaryThread,
                                                        track->streamType(),
                                                        track->sampleRate(),
                                                        track->channelMask(),
@@ -3996,7 +3871,7 @@
                                     audio_session_t triggerSession,
                                     audio_session_t listenerSession,
                                     const audioflinger::SyncEventCallback& callBack,
-                                    const wp<RefBase>& cookie)
+                                    const wp<IAfTrackBase>& cookie)
 {
     Mutex::Autolock _l(mLock);
 
@@ -4157,7 +4032,7 @@
         adjAttributionSource.pid = VALUE_OR_RETURN_STATUS(legacy2aidl_pid_t_int32_t(callingPid));
         currentPid = callingPid;
     }
-    adjAttributionSource = AudioFlinger::checkAttributionSourcePackage(adjAttributionSource);
+    adjAttributionSource = afutils::checkAttributionSourcePackage(adjAttributionSource);
 
     ALOGV("createEffect pid %d, effectClient %p, priority %d, sessionId %d, io %d, factory %p",
           adjAttributionSource.pid, effectClient.get(), priority, sessionId, io,
@@ -4182,7 +4057,7 @@
             lStatus = BAD_VALUE;
             goto Exit;
         }
-        PlaybackThread *thread = checkPlaybackThread_l(io);
+        IAfPlaybackThread* const thread = checkPlaybackThread_l(io);
         if (thread == nullptr) {
             ALOGE("%s: invalid output %d specified for AUDIO_SESSION_OUTPUT_STAGE", __func__, io);
             lStatus = BAD_VALUE;
@@ -4279,7 +4154,7 @@
             sp<Client> client = registerPid(currentPid);
             ALOGV("%s device type %#x address %s", __func__, device.mType, device.getAddress());
             handle = mDeviceEffectManager->createEffect_l(
-                    &descOut, device, client, effectClient, mPatchPanel.patches_l(),
+                    &descOut, device, client, effectClient, mPatchPanel->patches_l(),
                     &enabledOut, &lStatus, probe, request.notifyFramesProcessed);
             if (lStatus != NO_ERROR && lStatus != ALREADY_EXISTS) {
                 // remove local strong reference to Client with mClientLock held
@@ -4351,7 +4226,7 @@
                 }
                 const uint32_t sessionType =
                         mPlaybackThreads.valueAt(i)->hasAudioSession(sessionId);
-                if ((sessionType & ThreadBase::EFFECT_SESSION) != 0) {
+                if ((sessionType & IAfThreadBase::EFFECT_SESSION) != 0) {
                     ALOGE("%s: effect %s io %d denied because session %d effect exists on io %d",
                           __func__, descOut.name, (int) io, (int) sessionId, (int) checkIo);
                     android_errorWriteLog(0x534e4554, "123237974");
@@ -4360,7 +4235,7 @@
                 }
             }
         }
-        ThreadBase *thread = checkRecordThread_l(io);
+        IAfThreadBase* thread = checkRecordThread_l(io);
         if (thread == NULL) {
             thread = checkPlaybackThread_l(io);
             if (thread == NULL) {
@@ -4376,7 +4251,7 @@
             // session and used it instead of creating a new one.
             sp<IAfEffectChain> chain = getOrphanEffectChain_l(sessionId);
             if (chain != 0) {
-                Mutex::Autolock _l2(thread->mLock);
+                Mutex::Autolock _l2(thread->mutex());
                 thread->addEffectChain_l(chain);
             }
         }
@@ -4385,9 +4260,9 @@
 
         // create effect on selected output thread
         bool pinned = !audio_is_global_session(sessionId) && isSessionAcquired_l(sessionId);
-        ThreadBase *oriThread = nullptr;
+        IAfThreadBase* oriThread = nullptr;
         if (hapticPlaybackRequired && thread->hapticChannelMask() == AUDIO_CHANNEL_NONE) {
-            ThreadBase *hapticThread = hapticPlaybackThread_l();
+            IAfThreadBase* const hapticThread = hapticPlaybackThread_l();
             if (hapticThread == nullptr) {
                 ALOGE("%s haptic thread not found while it is required", __func__);
                 lStatus = INVALID_OPERATION;
@@ -4447,29 +4322,47 @@
     return lStatus;
 }
 
-status_t AudioFlinger::moveEffects(audio_session_t sessionId, audio_io_handle_t srcOutput,
-        audio_io_handle_t dstOutput)
+status_t AudioFlinger::moveEffects(audio_session_t sessionId, audio_io_handle_t srcIo,
+        audio_io_handle_t dstIo)
+NO_THREAD_SAFETY_ANALYSIS
 {
-    ALOGV("moveEffects() session %d, srcOutput %d, dstOutput %d",
-            sessionId, srcOutput, dstOutput);
+    ALOGV("%s() session %d, srcIo %d, dstIo %d", __func__, sessionId, srcIo, dstIo);
     Mutex::Autolock _l(mLock);
-    if (srcOutput == dstOutput) {
-        ALOGW("moveEffects() same dst and src outputs %d", dstOutput);
+    if (srcIo == dstIo) {
+        ALOGW("%s() same dst and src outputs %d", __func__, dstIo);
         return NO_ERROR;
     }
-    PlaybackThread *srcThread = checkPlaybackThread_l(srcOutput);
-    if (srcThread == NULL) {
-        ALOGW("moveEffects() bad srcOutput %d", srcOutput);
+    IAfRecordThread* const srcRecordThread = checkRecordThread_l(srcIo);
+    IAfRecordThread* const dstRecordThread = checkRecordThread_l(dstIo);
+    if (srcRecordThread != nullptr || dstRecordThread != nullptr) {
+        if (srcRecordThread != nullptr) {
+            srcRecordThread->mutex().lock();
+        }
+        if (dstRecordThread != nullptr) {
+            dstRecordThread->mutex().lock();
+        }
+        status_t ret = moveEffectChain_l(sessionId, srcRecordThread, dstRecordThread);
+        if (srcRecordThread != nullptr) {
+            srcRecordThread->mutex().unlock();
+        }
+        if (dstRecordThread != nullptr) {
+            dstRecordThread->mutex().unlock();
+        }
+        return ret;
+    }
+    IAfPlaybackThread* const srcThread = checkPlaybackThread_l(srcIo);
+    if (srcThread == nullptr) {
+        ALOGW("%s() bad srcIo %d", __func__, srcIo);
         return BAD_VALUE;
     }
-    PlaybackThread *dstThread = checkPlaybackThread_l(dstOutput);
-    if (dstThread == NULL) {
-        ALOGW("moveEffects() bad dstOutput %d", dstOutput);
+    IAfPlaybackThread* const dstThread = checkPlaybackThread_l(dstIo);
+    if (dstThread == nullptr) {
+        ALOGW("%s() bad dstIo %d", __func__, dstIo);
         return BAD_VALUE;
     }
 
-    Mutex::Autolock _dl(dstThread->mLock);
-    Mutex::Autolock _sl(srcThread->mLock);
+    Mutex::Autolock _dl(dstThread->mutex());
+    Mutex::Autolock _sl(srcThread->mutex());
     return moveEffectChain_l(sessionId, srcThread, dstThread);
 }
 
@@ -4480,11 +4373,11 @@
 {
     Mutex::Autolock _l(mLock);
 
-    sp<ThreadBase> thread = getEffectThread_l(sessionId, effectId);
+    sp<IAfThreadBase> thread = getEffectThread_l(sessionId, effectId);
     if (thread == nullptr) {
       return;
     }
-    Mutex::Autolock _sl(thread->mLock);
+    Mutex::Autolock _sl(thread->mutex());
     sp<IAfEffectModule> effect = thread->getEffect_l(sessionId, effectId);
     thread->setEffectSuspended_l(&effect->desc().type, suspended, sessionId);
 }
@@ -4492,8 +4385,7 @@
 
 // moveEffectChain_l must be called with both srcThread and dstThread mLocks held
 status_t AudioFlinger::moveEffectChain_l(audio_session_t sessionId,
-                                   AudioFlinger::PlaybackThread *srcThread,
-                                   AudioFlinger::PlaybackThread *dstThread)
+        IAfPlaybackThread* srcThread, IAfPlaybackThread* dstThread)
 NO_THREAD_SAFETY_ANALYSIS // requires srcThread and dstThread locks
 {
     ALOGV("moveEffectChain_l() session %d from thread %p to thread %p",
@@ -4602,18 +4494,60 @@
     return status;
 }
 
+
+// moveEffectChain_l must be called with both srcThread (if not null) and dstThread (if not null)
+// mLocks held
+status_t AudioFlinger::moveEffectChain_l(audio_session_t sessionId,
+        IAfRecordThread* srcThread, IAfRecordThread* dstThread)
+NO_THREAD_SAFETY_ANALYSIS // requires srcThread and dstThread locks
+{
+    sp<IAfEffectChain> chain = nullptr;
+    if (srcThread != 0) {
+        const Vector<sp<IAfEffectChain>> effectChains = srcThread->getEffectChains_l();
+        for (size_t i = 0; i < effectChains.size(); i ++) {
+             if (effectChains[i]->sessionId() == sessionId) {
+                 chain = effectChains[i];
+                 break;
+             }
+        }
+        ALOGV_IF(effectChains.size() == 0, "%s: no effect chain on io=%d", __func__,
+                srcThread->id());
+        if (chain == nullptr) {
+            ALOGE("%s wrong session id %d", __func__, sessionId);
+            return BAD_VALUE;
+        }
+        ALOGV("%s: removing effect chain for session=%d io=%d", __func__, sessionId,
+                srcThread->id());
+        srcThread->removeEffectChain_l(chain);
+    } else {
+        chain = getOrphanEffectChain_l(sessionId);
+        if (chain == nullptr) {
+            ALOGE("%s: no orphan effect chain found for session=%d", __func__, sessionId);
+            return BAD_VALUE;
+        }
+    }
+    if (dstThread != 0) {
+        ALOGV("%s: adding effect chain for session=%d on io=%d", __func__, sessionId,
+                dstThread->id());
+        dstThread->addEffectChain_l(chain);
+        return NO_ERROR;
+    }
+    ALOGV("%s: parking to orphan effect chain for session=%d", __func__, sessionId);
+    putOrphanEffectChain_l(chain);
+    return NO_ERROR;
+}
+
 status_t AudioFlinger::moveAuxEffectToIo(int EffectId,
-                                         const sp<PlaybackThread>& dstThread,
-                                         sp<PlaybackThread> *srcThread)
+        const sp<IAfPlaybackThread>& dstThread, sp<IAfPlaybackThread>* srcThread)
 {
     status_t status = NO_ERROR;
     Mutex::Autolock _l(mLock);
-    sp<PlaybackThread> thread =
-        static_cast<PlaybackThread *>(getEffectThread_l(AUDIO_SESSION_OUTPUT_MIX, EffectId).get());
+    const sp<IAfThreadBase> threadBase = getEffectThread_l(AUDIO_SESSION_OUTPUT_MIX, EffectId);
+    const sp<IAfPlaybackThread> thread = threadBase ? threadBase->asIAfPlaybackThread() : nullptr;
 
     if (EffectId != 0 && thread != 0 && dstThread != thread.get()) {
-        Mutex::Autolock _dl(dstThread->mLock);
-        Mutex::Autolock _sl(thread->mLock);
+        Mutex::Autolock _dl(dstThread->mutex());
+        Mutex::Autolock _sl(thread->mutex());
         sp<IAfEffectChain> srcChain = thread->getEffectChain_l(AUDIO_SESSION_OUTPUT_MIX);
         sp<IAfEffectChain> dstChain;
         if (srcChain == 0) {
@@ -4652,7 +4586,7 @@
     return status;
 }
 
-bool AudioFlinger::isNonOffloadableGlobalEffectEnabled_l()
+bool AudioFlinger::isNonOffloadableGlobalEffectEnabled_l() const
 NO_THREAD_SAFETY_ANALYSIS  // thread lock for getEffectChain_l.
 {
     if (mGlobalEffectEnableTime != 0 &&
@@ -4677,8 +4611,8 @@
     mGlobalEffectEnableTime = systemTime();
 
     for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
-        sp<PlaybackThread> t = mPlaybackThreads.valueAt(i);
-        if (t->mType == ThreadBase::OFFLOAD) {
+        const sp<IAfPlaybackThread> t = mPlaybackThreads.valueAt(i);
+        if (t->type() == IAfThreadBase::OFFLOAD) {
             t->invalidateTracks(AUDIO_STREAM_MUSIC);
         }
     }
@@ -4718,6 +4652,11 @@
 bool AudioFlinger::updateOrphanEffectChains(const sp<IAfEffectModule>& effect)
 {
     Mutex::Autolock _l(mLock);
+    return updateOrphanEffectChains_l(effect);
+}
+
+bool AudioFlinger::updateOrphanEffectChains_l(const sp<IAfEffectModule>& effect)
+{
     audio_session_t session = effect->sessionId();
     ssize_t index = mOrphanEffectChains.indexOfKey(session);
     ALOGV("updateOrphanEffectChains session %d index %zd", session, index);
@@ -4732,6 +4671,55 @@
     return false;
 }
 
+// ----------------------------------------------------------------------------
+// from PatchPanel
+
+/* List connected audio ports and their attributes */
+status_t AudioFlinger::listAudioPorts(unsigned int* num_ports,
+        struct audio_port* ports) const
+{
+    Mutex::Autolock _l(mLock);
+    return mPatchPanel->listAudioPorts(num_ports, ports);
+}
+
+/* Get supported attributes for a given audio port */
+status_t AudioFlinger::getAudioPort(struct audio_port_v7* port) const {
+    const status_t status = AudioValidator::validateAudioPort(*port);
+    if (status != NO_ERROR) {
+        return status;
+    }
+
+    Mutex::Autolock _l(mLock);
+    return mPatchPanel->getAudioPort(port);
+}
+
+/* Connect a patch between several source and sink ports */
+status_t AudioFlinger::createAudioPatch(
+        const struct audio_patch* patch, audio_patch_handle_t* handle)
+{
+    const status_t status = AudioValidator::validateAudioPatch(*patch);
+    if (status != NO_ERROR) {
+        return status;
+    }
+
+    Mutex::Autolock _l(mLock);
+    return mPatchPanel->createAudioPatch(patch, handle);
+}
+
+/* Disconnect a patch */
+status_t AudioFlinger::releaseAudioPatch(audio_patch_handle_t handle)
+{
+    Mutex::Autolock _l(mLock);
+    return mPatchPanel->releaseAudioPatch(handle);
+}
+
+/* List connected audio ports and they attributes */
+status_t AudioFlinger::listAudioPatches(
+        unsigned int* num_patches, struct audio_patch* patches) const
+{
+    Mutex::Autolock _l(mLock);
+    return mPatchPanel->listAudioPatches(num_patches, patches);
+}
 
 // ----------------------------------------------------------------------------
 
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index 700eed4..9aefb6b 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -15,332 +15,355 @@
 ** limitations under the License.
 */
 
-#ifndef ANDROID_AUDIO_FLINGER_H
-#define ANDROID_AUDIO_FLINGER_H
+#pragma once
 
-#include "Configuration.h"
+// Classes and interfaces directly used.
+#include "Client.h"
+#include "DeviceEffectManager.h"
+#include "IAfEffect.h"
+#include "IAfPatchPanel.h"
+#include "IAfThread.h"
+#include "IAfTrack.h"
+#include "MelReporter.h"
+#include "PatchCommandThread.h"
+
+// External classes
+#include <audio_utils/FdToString.h>
+#include <audio_utils/SimpleLog.h>
+#include <media/IAudioFlinger.h>
+#include <media/MediaMetricsItem.h>
+#include <media/audiohal/DevicesFactoryHalInterface.h>
+#include <mediautils/ServiceUtilities.h>
+#include <mediautils/Synchronization.h>
+
+// not needed with the includes above, added to prevent transitive include dependency.
+#include <utils/KeyedVector.h>
+#include <utils/String16.h>
 #include <atomic>
-#include <mutex>
-#include <chrono>
-#include <deque>
+#include <functional>
 #include <map>
-#include <numeric>
 #include <optional>
 #include <set>
-#include <string>
-#include <vector>
-#include <stdint.h>
-#include <sys/types.h>
-#include <limits.h>
-
-#include <android/media/BnAudioTrack.h>
-#include <android/media/IAudioFlingerClient.h>
-#include <android/media/IAudioTrackCallback.h>
-#include <android/os/BnExternalVibrationController.h>
-#include <android/content/AttributionSourceState.h>
-
-
-#include <android-base/macros.h>
-#include <cutils/atomic.h>
-#include <cutils/compiler.h>
-
-#include <cutils/properties.h>
-#include <media/IAudioFlinger.h>
-#include <media/AudioSystem.h>
-#include <media/AudioTrack.h>
-#include <media/MmapStreamInterface.h>
-#include <media/MmapStreamCallback.h>
-
-#include <utils/Errors.h>
-#include <utils/threads.h>
-#include <utils/SortedVector.h>
-#include <utils/TypeHelpers.h>
-#include <utils/Vector.h>
-
-#include <binder/AppOpsManager.h>
-#include <binder/BinderService.h>
-#include <binder/IAppOpsCallback.h>
-#include <binder/MemoryDealer.h>
-
-#include <system/audio.h>
-#include <system/audio_policy.h>
-
-#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/VolumeShaper.h>
-#include <mediautils/BatteryNotifier.h>
-#include <mediautils/ServiceUtilities.h>
-#include <mediautils/SharedMemoryAllocator.h>
-#include <mediautils/Synchronization.h>
-#include <mediautils/ThreadSnapshot.h>
-
-#include <afutils/AllocatorFactory.h>
-#include <afutils/AudioWatchdog.h>
-#include <afutils/NBAIO_Tee.h>
-
-#include <audio_utils/clock.h>
-#include <audio_utils/FdToString.h>
-#include <audio_utils/LinearMap.h>
-#include <audio_utils/MelAggregator.h>
-#include <audio_utils/MelProcessor.h>
-#include <audio_utils/SimpleLog.h>
-#include <audio_utils/TimestampVerifier.h>
-
-#include <sounddose/SoundDoseManager.h>
-#include <timing/MonotonicFrameCounter.h>
-#include <timing/SyncEvent.h>
-#include <timing/SynchronizedRecordState.h>
-
-#include <datapath/AudioHwDevice.h>
-#include <datapath/AudioStreamOut.h>
-#include <datapath/SpdifStreamOut.h>
-#include <datapath/ThreadMetrics.h>
-#include <datapath/TrackMetrics.h>
-#include <fastpath/FastCapture.h>
-#include <fastpath/FastMixer.h>
-#include <media/nbaio/NBAIO.h>
-
-#include <android/os/IPowerManager.h>
-
-#include <media/nblog/NBLog.h>
-#include <private/media/AudioEffectShared.h>
-#include <private/media/AudioTrackShared.h>
-
-#include <vibrator/ExternalVibration.h>
-#include <vibrator/ExternalVibrationUtils.h>
-
-#include "android/media/BnAudioRecord.h"
-#include "android/media/BnEffect.h"
-
-#include "Client.h"
-
-// include AudioFlinger component interfaces
-#include "IAfEffect.h"
 
 namespace android {
 
-class AudioMixer;
-class AudioBuffer;
-class AudioResampler;
-class DeviceHalInterface;
-class DevicesFactoryHalCallback;
-class DevicesFactoryHalInterface;
-class EffectsFactoryHalInterface;
-class FastMixer;
-class IAudioManager;
-class PassthruBufferProvider;
-class RecordBufferConverter;
-class ServerProxy;
-
-// ----------------------------------------------------------------------------
-
-static const nsecs_t kDefaultStandbyTimeInNsecs = seconds(3);
-
-#define INCLUDING_FROM_AUDIOFLINGER_H
-
-using android::content::AttributionSourceState;
-
-class AudioFlinger : public AudioFlingerServerAdapter::Delegate
+class AudioFlinger
+    : public AudioFlingerServerAdapter::Delegate  // IAudioFlinger client interface
+    , public IAfClientCallback
+    , public IAfDeviceEffectManagerCallback
+    , public IAfMelReporterCallback
+    , public IAfPatchPanelCallback
+    , public IAfThreadCallback
 {
     friend class sp<AudioFlinger>;
-    friend class Client; // removeClient_l();
 public:
     static void instantiate() ANDROID_API;
 
-    static AttributionSourceState checkAttributionSourcePackage(
-        const AttributionSourceState& attributionSource);
+private:
 
-    status_t dump(int fd, const Vector<String16>& args) override;
+    // ---- begin IAudioFlinger interface
 
-    // IAudioFlinger interface, in binder opcode order
+    status_t dump(int fd, const Vector<String16>& args) final;
+
     status_t createTrack(const media::CreateTrackRequest& input,
-                         media::CreateTrackResponse& output) override;
+                         media::CreateTrackResponse& output) final;
 
     status_t createRecord(const media::CreateRecordRequest& input,
-                          media::CreateRecordResponse& output) override;
+                          media::CreateRecordResponse& output) final;
 
-    virtual     uint32_t    sampleRate(audio_io_handle_t ioHandle) const;
-    virtual     audio_format_t format(audio_io_handle_t output) const;
-    virtual     size_t      frameCount(audio_io_handle_t ioHandle) const;
-    virtual     size_t      frameCountHAL(audio_io_handle_t ioHandle) const;
-    virtual     uint32_t    latency(audio_io_handle_t output) const;
+    uint32_t sampleRate(audio_io_handle_t ioHandle) const final;
+    audio_format_t format(audio_io_handle_t output) const final;
+    size_t frameCount(audio_io_handle_t ioHandle) const final;
+    size_t frameCountHAL(audio_io_handle_t ioHandle) const final;
+    uint32_t latency(audio_io_handle_t output) const final;
 
-    virtual     status_t    setMasterVolume(float value);
-    virtual     status_t    setMasterMute(bool muted);
-
-    virtual     float       masterVolume() const;
-    virtual     bool        masterMute() const;
+    status_t setMasterVolume(float value) final;
+    status_t setMasterMute(bool muted) final;
+    float masterVolume() const final;
+    bool masterMute() const final;
 
     // Balance value must be within -1.f (left only) to 1.f (right only) inclusive.
-                status_t    setMasterBalance(float balance) override;
-                status_t    getMasterBalance(float *balance) const override;
+    status_t setMasterBalance(float balance) final;
+    status_t getMasterBalance(float* balance) const final;
 
-    virtual     status_t    setStreamVolume(audio_stream_type_t stream, float value,
-                                            audio_io_handle_t output);
-    virtual     status_t    setStreamMute(audio_stream_type_t stream, bool muted);
+    status_t setStreamVolume(audio_stream_type_t stream, float value,
+            audio_io_handle_t output) final;
+    status_t setStreamMute(audio_stream_type_t stream, bool muted) final;
 
-    virtual     float       streamVolume(audio_stream_type_t stream,
-                                         audio_io_handle_t output) const;
-    virtual     bool        streamMute(audio_stream_type_t stream) const;
+    float streamVolume(audio_stream_type_t stream,
+            audio_io_handle_t output) const final;
+    bool streamMute(audio_stream_type_t stream) const final;
 
-    virtual     status_t    setMode(audio_mode_t mode);
+    status_t setMode(audio_mode_t mode) final;
 
-    virtual     status_t    setMicMute(bool state);
-    virtual     bool        getMicMute() const;
+    status_t setMicMute(bool state) final;
+    bool getMicMute() const final;
 
-    virtual     void        setRecordSilenced(audio_port_handle_t portId, bool silenced);
+    void setRecordSilenced(audio_port_handle_t portId, bool silenced) final;
 
-    virtual     status_t    setParameters(audio_io_handle_t ioHandle, const String8& keyValuePairs);
-    virtual     String8     getParameters(audio_io_handle_t ioHandle, const String8& keys) const;
+    status_t setParameters(audio_io_handle_t ioHandle, const String8& keyValuePairs) final;
+    String8 getParameters(audio_io_handle_t ioHandle, const String8& keys) const final;
 
-    virtual     void        registerClient(const sp<media::IAudioFlingerClient>& client);
+    void registerClient(const sp<media::IAudioFlingerClient>& client) final;
+    size_t getInputBufferSize(uint32_t sampleRate, audio_format_t format,
+            audio_channel_mask_t channelMask) const final;
 
-    virtual     size_t      getInputBufferSize(uint32_t sampleRate, audio_format_t format,
-                                               audio_channel_mask_t channelMask) const;
+    status_t openOutput(const media::OpenOutputRequest& request,
+            media::OpenOutputResponse* response) final;
 
-    virtual status_t openOutput(const media::OpenOutputRequest& request,
-                                media::OpenOutputResponse* response);
+    audio_io_handle_t openDuplicateOutput(audio_io_handle_t output1,
+            audio_io_handle_t output2) final;
 
-    virtual audio_io_handle_t openDuplicateOutput(audio_io_handle_t output1,
-                                                  audio_io_handle_t output2);
+    status_t closeOutput(audio_io_handle_t output) final;
 
-    virtual status_t closeOutput(audio_io_handle_t output);
+    status_t suspendOutput(audio_io_handle_t output) final;
 
-    virtual status_t suspendOutput(audio_io_handle_t output);
+    status_t restoreOutput(audio_io_handle_t output) final;
 
-    virtual status_t restoreOutput(audio_io_handle_t output);
+    status_t openInput(const media::OpenInputRequest& request,
+            media::OpenInputResponse* response) final;
 
-    virtual status_t openInput(const media::OpenInputRequest& request,
-                               media::OpenInputResponse* response);
+    status_t closeInput(audio_io_handle_t input) final;
 
-    virtual status_t closeInput(audio_io_handle_t input);
+    status_t setVoiceVolume(float volume) final;
 
-    virtual status_t setVoiceVolume(float volume);
+    status_t getRenderPosition(uint32_t* halFrames, uint32_t* dspFrames,
+            audio_io_handle_t output) const final;
 
-    virtual status_t getRenderPosition(uint32_t *halFrames, uint32_t *dspFrames,
-                                       audio_io_handle_t output) const;
-
-    virtual uint32_t getInputFramesLost(audio_io_handle_t ioHandle) const;
+    uint32_t getInputFramesLost(audio_io_handle_t ioHandle) const final;
 
     // This is the binder API.  For the internal API see nextUniqueId().
-    virtual audio_unique_id_t newAudioUniqueId(audio_unique_id_use_t use);
+    audio_unique_id_t newAudioUniqueId(audio_unique_id_use_t use) final;
 
-    void acquireAudioSessionId(audio_session_t audioSession, pid_t pid, uid_t uid) override;
+    void acquireAudioSessionId(audio_session_t audioSession, pid_t pid, uid_t uid) final;
 
-    virtual void releaseAudioSessionId(audio_session_t audioSession, pid_t pid);
+    void releaseAudioSessionId(audio_session_t audioSession, pid_t pid) final;
 
-    virtual status_t queryNumberEffects(uint32_t *numEffects) const;
+    status_t queryNumberEffects(uint32_t* numEffects) const final;
 
-    virtual status_t queryEffect(uint32_t index, effect_descriptor_t *descriptor) const;
+    status_t queryEffect(uint32_t index, effect_descriptor_t* descriptor) const final;
 
-    virtual status_t getEffectDescriptor(const effect_uuid_t *pUuid,
-                                         const effect_uuid_t *pTypeUuid,
-                                         uint32_t preferredTypeFlag,
-                                         effect_descriptor_t *descriptor) const;
+    status_t getEffectDescriptor(const effect_uuid_t* pUuid,
+            const effect_uuid_t* pTypeUuid,
+            uint32_t preferredTypeFlag,
+            effect_descriptor_t* descriptor) const final;
 
-    virtual status_t createEffect(const media::CreateEffectRequest& request,
-                                  media::CreateEffectResponse* response);
+    status_t createEffect(const media::CreateEffectRequest& request,
+            media::CreateEffectResponse* response) final;
 
-    virtual status_t moveEffects(audio_session_t sessionId, audio_io_handle_t srcOutput,
-                        audio_io_handle_t dstOutput);
+    status_t moveEffects(audio_session_t sessionId, audio_io_handle_t srcOutput,
+            audio_io_handle_t dstOutput) final;
 
-            void setEffectSuspended(int effectId,
-                                    audio_session_t sessionId,
-                                    bool suspended) override;
+    void setEffectSuspended(int effectId,
+            audio_session_t sessionId,
+            bool suspended) final;
 
-    virtual audio_module_handle_t loadHwModule(const char *name);
+    audio_module_handle_t loadHwModule(const char* name) final;
 
-    virtual uint32_t getPrimaryOutputSamplingRate();
-    virtual size_t getPrimaryOutputFrameCount();
+    uint32_t getPrimaryOutputSamplingRate() const final;
+    size_t getPrimaryOutputFrameCount() const final;
 
-    virtual status_t setLowRamDevice(bool isLowRamDevice, int64_t totalMemory) override;
-
-    /* List available audio ports and their attributes */
-    virtual status_t listAudioPorts(unsigned int *num_ports,
-                                    struct audio_port *ports);
+    status_t setLowRamDevice(bool isLowRamDevice, int64_t totalMemory) final;
 
     /* Get attributes for a given audio port */
-    virtual status_t getAudioPort(struct audio_port_v7 *port);
+    status_t getAudioPort(struct audio_port_v7* port) const final;
 
     /* Create an audio patch between several source and sink ports */
-    virtual status_t createAudioPatch(const struct audio_patch *patch,
-                                       audio_patch_handle_t *handle);
+    status_t createAudioPatch(const struct audio_patch *patch,
+            audio_patch_handle_t* handle) final;
 
     /* Release an audio patch */
-    virtual status_t releaseAudioPatch(audio_patch_handle_t handle);
+    status_t releaseAudioPatch(audio_patch_handle_t handle) final;
 
     /* List existing audio patches */
-    virtual status_t listAudioPatches(unsigned int *num_patches,
-                                      struct audio_patch *patches);
+    status_t listAudioPatches(unsigned int* num_patches,
+            struct audio_patch* patches) const final;
 
     /* Set audio port configuration */
-    virtual status_t setAudioPortConfig(const struct audio_port_config *config);
+    status_t setAudioPortConfig(const struct audio_port_config* config) final;
 
     /* Get the HW synchronization source used for an audio session */
-    virtual audio_hw_sync_t getAudioHwSyncForSession(audio_session_t sessionId);
+    audio_hw_sync_t getAudioHwSyncForSession(audio_session_t sessionId) final;
 
     /* Indicate JAVA services are ready (scheduling, power management ...) */
-    virtual status_t systemReady();
-    virtual status_t audioPolicyReady() { mAudioPolicyReady.store(true); return NO_ERROR; }
-            bool isAudioPolicyReady() const { return mAudioPolicyReady.load(); }
+    status_t systemReady() final;
+    status_t audioPolicyReady() final { mAudioPolicyReady.store(true); return NO_ERROR; }
 
+    status_t getMicrophones(std::vector<media::MicrophoneInfoFw>* microphones) const final;
 
-    virtual status_t getMicrophones(std::vector<media::MicrophoneInfoFw> *microphones);
+    status_t setAudioHalPids(const std::vector<pid_t>& pids) final;
 
-    virtual status_t setAudioHalPids(const std::vector<pid_t>& pids);
+    status_t setVibratorInfos(const std::vector<media::AudioVibratorInfo>& vibratorInfos) final;
 
-    virtual status_t setVibratorInfos(const std::vector<media::AudioVibratorInfo>& vibratorInfos);
+    status_t updateSecondaryOutputs(
+            const TrackSecondaryOutputsMap& trackSecondaryOutputs) final;
 
-    virtual status_t updateSecondaryOutputs(
-            const TrackSecondaryOutputsMap& trackSecondaryOutputs);
-
-    virtual status_t getMmapPolicyInfos(
+    status_t getMmapPolicyInfos(
             media::audio::common::AudioMMapPolicyType policyType,
-            std::vector<media::audio::common::AudioMMapPolicyInfo> *policyInfos);
+            std::vector<media::audio::common::AudioMMapPolicyInfo>* policyInfos) final;
 
-    virtual int32_t getAAudioMixerBurstCount();
+    int32_t getAAudioMixerBurstCount() const final;
 
-    virtual int32_t getAAudioHardwareBurstMinUsec();
+    int32_t getAAudioHardwareBurstMinUsec() const final;
 
-    virtual status_t setDeviceConnectedState(const struct audio_port_v7 *port,
-                                             media::DeviceConnectedState state);
+    status_t setDeviceConnectedState(const struct audio_port_v7* port,
+            media::DeviceConnectedState state) final;
 
-    virtual status_t setSimulateDeviceConnections(bool enabled);
+    status_t setSimulateDeviceConnections(bool enabled) final;
 
-    virtual status_t setRequestedLatencyMode(
-            audio_io_handle_t output, audio_latency_mode_t mode);
+    status_t setRequestedLatencyMode(
+            audio_io_handle_t output, audio_latency_mode_t mode) final;
 
-    virtual status_t getSupportedLatencyModes(audio_io_handle_t output,
-            std::vector<audio_latency_mode_t>* modes);
+    status_t getSupportedLatencyModes(audio_io_handle_t output,
+            std::vector<audio_latency_mode_t>* modes) const final;
 
-    virtual status_t setBluetoothVariableLatencyEnabled(bool enabled);
+    status_t setBluetoothVariableLatencyEnabled(bool enabled) final;
 
-    virtual status_t isBluetoothVariableLatencyEnabled(bool* enabled);
+    status_t isBluetoothVariableLatencyEnabled(bool* enabled) const final;
 
-    virtual status_t supportsBluetoothVariableLatency(bool* support);
+    status_t supportsBluetoothVariableLatency(bool* support) const final;
 
-    virtual status_t getSoundDoseInterface(const sp<media::ISoundDoseCallback>& callback,
-                                           sp<media::ISoundDose>* soundDose);
+    status_t getSoundDoseInterface(const sp<media::ISoundDoseCallback>& callback,
+            sp<media::ISoundDose>* soundDose) const final;
 
-    status_t invalidateTracks(const std::vector<audio_port_handle_t>& portIds) override;
+    status_t invalidateTracks(const std::vector<audio_port_handle_t>& portIds) final;
 
-    virtual status_t getAudioPolicyConfig(media::AudioPolicyConfig* config);
+    status_t getAudioPolicyConfig(media::AudioPolicyConfig* config) final;
 
     status_t onTransactWrapper(TransactionCode code, const Parcel& data, uint32_t flags,
-        const std::function<status_t()>& delegate) override;
+            const std::function<status_t()>& delegate) final;
 
-    // end of IAudioFlinger interface
+    // ---- end of IAudioFlinger interface
 
-    sp<NBLog::Writer>   newWriter_l(size_t size, const char *name);
-    void                unregisterWriter(const sp<NBLog::Writer>& writer);
+    // ---- begin IAfClientCallback interface
+
+    Mutex& clientMutex() const final { return mClientLock; }
+    void removeClient_l(pid_t pid) final;
+    void removeNotificationClient(pid_t pid) final;
+    status_t moveAuxEffectToIo(
+            int effectId,
+            const sp<IAfPlaybackThread>& dstThread,
+            sp<IAfPlaybackThread>* srcThread) final;
+
+    // ---- end of IAfClientCallback interface
+
+    // ---- begin IAfDeviceEffectManagerCallback interface
+
+    // also used by IAfThreadCallback
+    bool isAudioPolicyReady() const final { return mAudioPolicyReady.load(); }
+    // below also used by IAfMelReporterCallback, IAfPatchPanelCallback
+    const sp<PatchCommandThread>& getPatchCommandThread() final { return mPatchCommandThread; }
+    status_t addEffectToHal(
+            const struct audio_port_config* device, const sp<EffectHalInterface>& effect) final;
+    status_t removeEffectFromHal(
+            const struct audio_port_config* device, const sp<EffectHalInterface>& effect) final;
+
+    // ---- end of IAfDeviceEffectManagerCallback interface
+
+    // ---- begin IAfMelReporterCallback interface
+
+    // below also used by IAfThreadCallback
+    Mutex& mutex() const final { return mLock; }
+    sp<IAfThreadBase> checkOutputThread_l(audio_io_handle_t ioHandle) const final REQUIRES(mLock);
+
+    // ---- end of IAfMelReporterCallback interface
+
+    // ---- begin IAfPatchPanelCallback interface
+
+    void closeThreadInternal_l(const sp<IAfPlaybackThread>& thread) final;
+    void closeThreadInternal_l(const sp<IAfRecordThread>& thread) final;
+    // return thread associated with primary hardware device, or NULL
+    IAfPlaybackThread* primaryPlaybackThread_l() const final;
+    IAfPlaybackThread* checkPlaybackThread_l(audio_io_handle_t output) const final;
+    IAfRecordThread* checkRecordThread_l(audio_io_handle_t input) const final;
+    IAfMmapThread* checkMmapThread_l(audio_io_handle_t io) const final;
+    void lock() const final ACQUIRE(mLock) { mLock.lock(); }
+    void unlock() const final RELEASE(mLock) { mLock.unlock(); }
+    sp<IAfThreadBase> openInput_l(audio_module_handle_t module,
+            audio_io_handle_t* input,
+            audio_config_t* config,
+            audio_devices_t device,
+            const char* address,
+            audio_source_t source,
+            audio_input_flags_t flags,
+            audio_devices_t outputDevice,
+            const String8& outputDeviceAddress) final;
+    sp<IAfThreadBase> openOutput_l(audio_module_handle_t module,
+            audio_io_handle_t* output,
+            audio_config_t* halConfig,
+            audio_config_base_t* mixerConfig,
+            audio_devices_t deviceType,
+            const String8& address,
+            audio_output_flags_t flags) final;
+    const DefaultKeyedVector<audio_module_handle_t, AudioHwDevice*>&
+            getAudioHwDevs_l() const final { return mAudioHwDevs; }
+    void updateDownStreamPatches_l(const struct audio_patch* patch,
+            const std::set<audio_io_handle_t>& streams) final;
+    void updateOutDevicesForRecordThreads_l(const DeviceDescriptorBaseVector& devices) final;
+
+    // ---- end of IAfPatchPanelCallback interface
+
+    // ----- begin IAfThreadCallback interface
+
+    bool isNonOffloadableGlobalEffectEnabled_l() const final;
+    bool btNrecIsOff() const final { return mBtNrecIsOff.load(); }
+    float masterVolume_l() const final;
+    bool masterMute_l() const final;
+    float getMasterBalance_l() const;
+    // no range check, AudioFlinger::mLock held
+    bool streamMute_l(audio_stream_type_t stream) const final { return mStreamTypes[stream].mute; }
+    audio_mode_t getMode() const final { return mMode; }
+    bool isLowRamDevice() const final { return mIsLowRamDevice; }
+    uint32_t getScreenState() const final { return mScreenState; }
+
+    std::optional<media::AudioVibratorInfo> getDefaultVibratorInfo_l() const final;
+    const sp<IAfPatchPanel>& getPatchPanel() const final { return mPatchPanel; }
+    const sp<MelReporter>& getMelReporter() const final { return mMelReporter; }
+    const sp<EffectsFactoryHalInterface>& getEffectsFactoryHal() const final {
+        return mEffectsFactoryHal;
+    }
+    sp<IAudioManager> getOrCreateAudioManager() final;
+
+    // Called when the last effect handle on an effect instance is removed. If this
+    // effect belongs to an effect chain in mOrphanEffectChains, the chain is updated
+    // and removed from mOrphanEffectChains if it does not contain any effect.
+    // Return true if the effect was found in mOrphanEffectChains, false otherwise.
+    bool updateOrphanEffectChains(const sp<IAfEffectModule>& effect) final;
+
+    status_t moveEffectChain_l(audio_session_t sessionId,
+            IAfPlaybackThread* srcThread, IAfPlaybackThread* dstThread) final;
+
+    // This is a helper that is called during incoming binder calls.
+    // Requests media.log to start merging log buffers
+    void requestLogMerge() final;
+    sp<NBLog::Writer> newWriter_l(size_t size, const char *name) final;
+    void unregisterWriter(const sp<NBLog::Writer>& writer) final;
+
+    sp<audioflinger::SyncEvent> createSyncEvent(AudioSystem::sync_event_t type,
+            audio_session_t triggerSession,
+            audio_session_t listenerSession,
+            const audioflinger::SyncEventCallback& callBack,
+            const wp<IAfTrackBase>& cookie) final;
+
+    void ioConfigChanged(audio_io_config_event_t event,
+            const sp<AudioIoDescriptor>& ioDesc,
+            pid_t pid = 0) final;
+    void onNonOffloadableGlobalEffectEnable() final;
+    void onSupportedLatencyModesChanged(
+            audio_io_handle_t output, const std::vector<audio_latency_mode_t>& modes) final;
+
+    // ---- end of IAfThreadCallback interface
+
+    /* List available audio ports and their attributes */
+    status_t listAudioPorts(unsigned int* num_ports, struct audio_port* ports) const;
+
     sp<EffectsFactoryHalInterface> getEffectsFactory();
 
+public:
+    // TODO(b/292281786): Remove this when Oboeservice can get access to
+    // openMmapStream through an IAudioFlinger handle directly.
+    static inline std::atomic<AudioFlinger*> gAudioFlinger = nullptr;
+
     status_t openMmapStream(MmapStreamInterface::stream_direction_t direction,
                             const audio_attributes_t *attr,
                             audio_config_base_t *config,
@@ -350,21 +373,6 @@
                             const sp<MmapStreamCallback>& callback,
                             sp<MmapStreamInterface>& interface,
                             audio_port_handle_t *handle);
-
-    static os::HapticScale onExternalVibrationStart(
-        const sp<os::ExternalVibration>& externalVibration);
-    static void onExternalVibrationStop(const sp<os::ExternalVibration>& externalVibration);
-
-    status_t addEffectToHal(
-            const struct audio_port_config *device, const sp<EffectHalInterface>& effect);
-    status_t removeEffectFromHal(
-            const struct audio_port_config *device, const sp<EffectHalInterface>& effect);
-
-    void updateDownStreamPatches_l(const struct audio_patch *patch,
-                                   const std::set<audio_io_handle_t>& streams);
-
-    std::optional<media::AudioVibratorInfo> getDefaultVibratorInfo_l();
-
 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;
@@ -374,132 +382,30 @@
     Vector< sp<NBLog::Writer> > mUnregisteredWriters;
     Mutex               mUnregisteredWritersLock;
 
-public:
-    // Life cycle of gAudioFlinger and AudioFlinger:
-    //
-    // AudioFlinger is created once and survives until audioserver crashes
-    // irrespective of sp<> and wp<> as it is refcounted by ServiceManager and we
-    // don't issue a ServiceManager::tryUnregisterService().
-    //
-    // gAudioFlinger is an atomic pointer set on AudioFlinger::onFirstRef().
-    // After this is set, it is safe to obtain a wp<> or sp<> from it as the
-    // underlying object does not go away.
-    //
-    // Note: For most inner classes, it is acceptable to hold a reference to the outer
-    // AudioFlinger instance as creation requires AudioFlinger to exist in the first place.
-    //
-    // An atomic here ensures underlying writes have completed before setting
-    // the pointer. Access by memory_order_seq_cst.
-    //
-
-    static inline std::atomic<AudioFlinger *> gAudioFlinger = nullptr;
-
-    sp<audioflinger::SyncEvent> createSyncEvent(AudioSystem::sync_event_t type,
-                                        audio_session_t triggerSession,
-                                        audio_session_t listenerSession,
-                                        const audioflinger::SyncEventCallback& callBack,
-                                        const wp<RefBase>& cookie);
-
-    bool        btNrecIsOff() const { return mBtNrecIsOff.load(); }
-
-    void             lock() ACQUIRE(mLock) { mLock.lock(); }
-    void             unlock() RELEASE(mLock) { mLock.unlock(); }
-
-private:
-
-               audio_mode_t getMode() const { return mMode; }
-
                             AudioFlinger() ANDROID_API;
-    virtual                 ~AudioFlinger();
+    ~AudioFlinger() override;
 
     // call in any IAudioFlinger method that accesses mPrimaryHardwareDev
     status_t                initCheck() const { return mPrimaryHardwareDev == NULL ?
                                                         NO_INIT : NO_ERROR; }
 
     // RefBase
-    virtual     void        onFirstRef();
+    void onFirstRef() override;
 
     AudioHwDevice*          findSuitableHwDev_l(audio_module_handle_t module,
                                                 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
-    // FCC_2 <= channels <= AudioMixer::MAX_NUM_CHANNELS.
-    static const bool kEnableExtendedChannels = true;
-
-    // Returns true if channel mask is permitted for the PCM sink in the MixerThread
-    static inline bool isValidPcmSinkChannelMask(audio_channel_mask_t channelMask) {
-        switch (audio_channel_mask_get_representation(channelMask)) {
-        case AUDIO_CHANNEL_REPRESENTATION_POSITION: {
-            // Haptic channel mask is only applicable for channel position mask.
-            const uint32_t channelCount = audio_channel_count_from_out_mask(
-                    static_cast<audio_channel_mask_t>(channelMask & ~AUDIO_CHANNEL_HAPTIC_ALL));
-            const uint32_t maxChannelCount = kEnableExtendedChannels
-                    ? AudioMixer::MAX_NUM_CHANNELS : FCC_2;
-            if (channelCount < FCC_2 // mono is not supported at this time
-                    || channelCount > maxChannelCount) {
-                return false;
-            }
-            // check that channelMask is the "canonical" one we expect for the channelCount.
-            return audio_channel_position_mask_is_out_canonical(channelMask);
-            }
-        case AUDIO_CHANNEL_REPRESENTATION_INDEX:
-            if (kEnableExtendedChannels) {
-                const uint32_t channelCount = audio_channel_count_from_out_mask(channelMask);
-                if (channelCount >= FCC_2 // mono is not supported at this time
-                        && channelCount <= AudioMixer::MAX_NUM_CHANNELS) {
-                    return true;
-                }
-            }
-            return false;
-        default:
-            return false;
-        }
-    }
-
-    // Set kEnableExtendedPrecision to true to use extended precision in MixerThread
-    static const bool kEnableExtendedPrecision = true;
-
-    // Returns true if format is permitted for the PCM sink in the MixerThread
-    static inline bool isValidPcmSinkFormat(audio_format_t format) {
-        switch (format) {
-        case AUDIO_FORMAT_PCM_16_BIT:
-            return true;
-        case AUDIO_FORMAT_PCM_FLOAT:
-        case AUDIO_FORMAT_PCM_24_BIT_PACKED:
-        case AUDIO_FORMAT_PCM_32_BIT:
-        case AUDIO_FORMAT_PCM_8_24_BIT:
-            return kEnableExtendedPrecision;
-        default:
-            return false;
-        }
-    }
-
-    // standby delay for MIXER and DUPLICATING playback threads is read from property
-    // ro.audio.flinger_standbytime_ms or defaults to kDefaultStandbyTimeInNsecs
-    static nsecs_t          mStandbyTimeInNsecs;
-
     // incremented by 2 when screen state changes, bit 0 == 1 means "off"
-    // AudioFlinger::setParameters() updates, other threads read w/o lock
-    static uint32_t         mScreenState;
+    // AudioFlinger::setParameters() updates with mLock.
+    std::atomic_uint32_t mScreenState{};
 
-    // Internal dump utilities.
-    static const int kDumpLockTimeoutNs = 1 * NANOS_PER_SECOND;
-public:
-    // TODO(b/288339104) extract to afutils
-    static bool dumpTryLock(Mutex& mutex);
-private:
     void dumpPermissionDenial(int fd, const Vector<String16>& args);
     void dumpClients(int fd, const Vector<String16>& args);
     void dumpInternals(int fd, const Vector<String16>& args);
 
     SimpleLog mThreadLog{16}; // 16 Thread history limit
 
-public:
-    // TODO(b/288339104)
-    class ThreadBase;
-private:
-    void dumpToThreadLog_l(const sp<ThreadBase> &thread);
+    void dumpToThreadLog_l(const sp<IAfThreadBase>& thread);
 
     // --- Notification Client ---
     class NotificationClient : public IBinder::DeathRecipient {
@@ -555,66 +461,6 @@
 
     const sp<MediaLogNotifier> mMediaLogNotifier;
 
-    // This is a helper that is called during incoming binder calls.
-    // Requests media.log to start merging log buffers
-    void requestLogMerge();
-
-    // TODO(b/288339104) replace these forward declaration classes with interfaces.
-public:
-    class RecordThread;
-    class PlaybackThread;
-    class MixerThread;
-    class DirectOutputThread;
-    class OffloadThread;
-    class DuplicatingThread;
-    class AsyncCallbackThread;
-    class BitPerfectThread;
-private:
-    class Track;
-    class RecordTrack;
-    class DeviceEffectManager;
-    // TODO(b/288339104) these should be separate files
-public:
-    class PatchPanel;
-    class DeviceEffectManagerCallback;
-private:
-    struct AudioStreamIn;
-    struct TeePatch;
-    using TeePatches = std::vector<TeePatch>;
-
-
-    struct  stream_type_t {
-        stream_type_t()
-            :   volume(1.0f),
-                mute(false)
-        {
-        }
-        float       volume;
-        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 ---
-
-#include "Threads.h"
-
-#include "PatchPanel.h"
-
-#include "PatchCommandThread.h"
-
-#include "DeviceEffectManager.h"
-
-#include "MelReporter.h"
-
     // Find io handle by session id.
     // Preference is given to an io handle with a matching effect chain to session id.
     // If none found, AUDIO_IO_HANDLE_NONE is returned.
@@ -627,7 +473,7 @@
             const uint32_t sessionType = threads.valueAt(i)->hasAudioSession(sessionId);
             if (sessionType != 0) {
                 io = threads.keyAt(i);
-                if ((sessionType & AudioFlinger::ThreadBase::EFFECT_SESSION) != 0) {
+                if ((sessionType & IAfThreadBase::EFFECT_SESSION) != 0) {
                     break; // effect chain here.
                 }
             }
@@ -635,67 +481,15 @@
         return io;
     }
 
-    // Mmap stream control interface implementation. Each MmapThreadHandle controls one
-    // MmapPlaybackThread or MmapCaptureThread instance.
-    class MmapThreadHandle : public MmapStreamInterface {
-    public:
-        explicit            MmapThreadHandle(const sp<MmapThread>& thread);
-        virtual             ~MmapThreadHandle();
+    IAfThreadBase* checkThread_l(audio_io_handle_t ioHandle) const;
+    IAfPlaybackThread* checkMixerThread_l(audio_io_handle_t output) const;
 
-        // MmapStreamInterface virtuals
-        virtual status_t createMmapBuffer(int32_t minSizeFrames,
-                                          struct audio_mmap_buffer_info *info);
-        virtual status_t getMmapPosition(struct audio_mmap_position *position);
-        virtual status_t getExternalPosition(uint64_t *position, int64_t *timeNanos);
-        virtual status_t start(const AudioClient& client,
-                               const audio_attributes_t *attr,
-                               audio_port_handle_t *handle);
-        virtual status_t stop(audio_port_handle_t handle);
-        virtual status_t standby();
-                status_t reportData(const void* buffer, size_t frameCount) override;
+              sp<VolumeInterface> getVolumeInterface_l(audio_io_handle_t output) const;
+              std::vector<sp<VolumeInterface>> getAllVolumeInterfaces_l() const;
 
-    private:
-        const sp<MmapThread> mThread;
-    };
 
-              ThreadBase *checkThread_l(audio_io_handle_t ioHandle) const;
-              sp<AudioFlinger::ThreadBase> checkOutputThread_l(audio_io_handle_t ioHandle) const
-                      REQUIRES(mLock);
-              PlaybackThread *checkPlaybackThread_l(audio_io_handle_t output) const;
-              MixerThread *checkMixerThread_l(audio_io_handle_t output) const;
-              RecordThread *checkRecordThread_l(audio_io_handle_t input) const;
-              MmapThread *checkMmapThread_l(audio_io_handle_t io) const;
-              VolumeInterface *getVolumeInterface_l(audio_io_handle_t output) const;
-              Vector <VolumeInterface *> getAllVolumeInterfaces_l() const;
-
-              sp<ThreadBase> openInput_l(audio_module_handle_t module,
-                                           audio_io_handle_t *input,
-                                           audio_config_t *config,
-                                           audio_devices_t device,
-                                           const char* address,
-                                           audio_source_t source,
-                                           audio_input_flags_t flags,
-                                           audio_devices_t outputDevice,
-                                           const String8& outputDeviceAddress);
-              sp<ThreadBase> openOutput_l(audio_module_handle_t module,
-                                          audio_io_handle_t *output,
-                                          audio_config_t *halConfig,
-                                          audio_config_base_t *mixerConfig,
-                                          audio_devices_t deviceType,
-                                          const String8& address,
-                                          audio_output_flags_t flags);
-
-              void closeOutputFinish(const sp<PlaybackThread>& thread);
-              void closeInputFinish(const sp<RecordThread>& thread);
-
-              // no range check, AudioFlinger::mLock held
-              bool streamMute_l(audio_stream_type_t stream) const
-                                { return mStreamTypes[stream].mute; }
-              void ioConfigChanged(audio_io_config_event_t event,
-                                   const sp<AudioIoDescriptor>& ioDesc,
-                                   pid_t pid = 0);
-              void onSupportedLatencyModesChanged(
-                    audio_io_handle_t output, const std::vector<audio_latency_mode_t>& modes);
+    void closeOutputFinish(const sp<IAfPlaybackThread>& thread);
+    void closeInputFinish(const sp<IAfRecordThread>& thread);
 
               // Allocate an audio_unique_id_t.
               // Specific types are audio_io_handle_t, audio_session_t, effect ID (int),
@@ -708,37 +502,27 @@
               //       Thus it may fail by returning an ID of the wrong sign,
               //       or by returning a non-unique ID.
               // This is the internal API.  For the binder API see newAudioUniqueId().
-              audio_unique_id_t nextUniqueId(audio_unique_id_use_t use);
+    // used by IAfDeviceEffectManagerCallback, IAfPatchPanelCallback, IAfThreadCallback
+    audio_unique_id_t nextUniqueId(audio_unique_id_use_t use) final;
 
               status_t moveEffectChain_l(audio_session_t sessionId,
-                                     PlaybackThread *srcThread,
-                                     PlaybackThread *dstThread);
-
-              status_t moveAuxEffectToIo(int EffectId,
-                                         const sp<PlaybackThread>& dstThread,
-                                         sp<PlaybackThread> *srcThread);
+            IAfRecordThread* srcThread, IAfRecordThread* dstThread);
 
               // return thread associated with primary hardware device, or NULL
-              PlaybackThread *primaryPlaybackThread_l() const;
               DeviceTypeSet primaryOutputDevice_l() const;
 
               // return the playback thread with smallest HAL buffer size, and prefer fast
-              PlaybackThread *fastPlaybackThread_l() const;
+              IAfPlaybackThread* fastPlaybackThread_l() const;
 
-              sp<ThreadBase> getEffectThread_l(audio_session_t sessionId, int effectId);
+              sp<IAfThreadBase> getEffectThread_l(audio_session_t sessionId, int effectId);
 
-              ThreadBase *hapticPlaybackThread_l() const;
+              IAfThreadBase* hapticPlaybackThread_l() const;
 
               void updateSecondaryOutputsForTrack_l(
-                      PlaybackThread::Track* track,
-                      PlaybackThread* thread,
+                      IAfTrack* track,
+                      IAfPlaybackThread* thread,
                       const std::vector<audio_io_handle_t>& secondaryOutputs) const;
 
-
-                void        removeClient_l(pid_t pid);
-                void        removeNotificationClient(pid_t pid);
-                bool isNonOffloadableGlobalEffectEnabled_l();
-                void onNonOffloadableGlobalEffectEnable();
                 bool isSessionAcquired_l(audio_session_t audioSession);
 
                 // Store an effect chain to mOrphanEffectChains keyed vector.
@@ -752,49 +536,16 @@
                 // Get an effect chain for the specified session in mOrphanEffectChains and remove
                 // it if found. Returns 0 if not found (this is the most common case).
                 sp<IAfEffectChain> getOrphanEffectChain_l(audio_session_t session);
-                // Called when the last effect handle on an effect instance is removed. If this
-                // effect belongs to an effect chain in mOrphanEffectChains, the chain is updated
-                // and removed from mOrphanEffectChains if it does not contain any effect.
-                // Return true if the effect was found in mOrphanEffectChains, false otherwise.
-public:
-// TODO(b/288339104) suggest better grouping
-                bool updateOrphanEffectChains(const sp<IAfEffectModule>& effect);
-private:
+
                 std::vector< sp<IAfEffectModule> > purgeStaleEffects_l();
 
+                std::vector< sp<IAfEffectModule> > purgeOrphanEffectChains_l();
+                bool updateOrphanEffectChains_l(const sp<IAfEffectModule>& effect);
+
                 void broadcastParametersToRecordThreads_l(const String8& keyValuePairs);
-                void updateOutDevicesForRecordThreads_l(const DeviceDescriptorBaseVector& devices);
                 void forwardParametersToDownstreamPatches_l(
                         audio_io_handle_t upStream, const String8& keyValuePairs,
-                        const std::function<bool(const sp<PlaybackThread>&)>& useThread = nullptr);
-
-    // AudioStreamIn is immutable, so their fields are const.
-    // For emphasis, we could also make all pointers to them be "const *",
-    // but that would clutter the code unnecessarily.
-
-    struct AudioStreamIn : public Source {
-        AudioHwDevice* const audioHwDev;
-        sp<StreamInHalInterface> stream;
-        audio_input_flags_t flags;
-
-        sp<DeviceHalInterface> hwDev() const { return audioHwDev->hwDevice(); }
-
-        AudioStreamIn(AudioHwDevice *dev, const 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 {
-        sp<RecordThread::PatchRecord> patchRecord;
-        sp<PlaybackThread::PatchTrack> patchTrack;
-    };
+            const std::function<bool(const sp<IAfPlaybackThread>&)>& useThread = nullptr);
 
     // for mAudioSessionRefs only
     struct AudioSessionRef {
@@ -810,10 +561,9 @@
                 // protects mClients and mNotificationClients.
                 // must be locked after mLock and ThreadBase::mLock if both must be locked
                 // avoids acquiring AudioFlinger::mLock from inside thread loop.
-public:
-    // TODO(b/288339104) access by getter,
-    mutable     Mutex                               mClientLock;
-private:
+
+    mutable Mutex mClientLock;
+
                 // protected by mClientLock
                 DefaultKeyedVector< pid_t, wp<Client> >     mClients;   // see ~Client()
 
@@ -860,7 +610,7 @@
     mutable     hardware_call_state                 mHardwareStatus;    // for dump only
 
 
-                DefaultKeyedVector< audio_io_handle_t, sp<PlaybackThread> >  mPlaybackThreads;
+    DefaultKeyedVector<audio_io_handle_t, sp<IAfPlaybackThread>> mPlaybackThreads;
                 stream_type_t                       mStreamTypes[AUDIO_STREAM_CNT];
 
                 // member variables below are protected by mLock
@@ -869,7 +619,7 @@
                 float                               mMasterBalance = 0.f;
                 // end of variables protected by mLock
 
-                DefaultKeyedVector< audio_io_handle_t, sp<RecordThread> >    mRecordThreads;
+    DefaultKeyedVector<audio_io_handle_t, sp<IAfRecordThread>> mRecordThreads;
 
                 // protected by mClientLock
                 DefaultKeyedVector< pid_t, sp<NotificationClient> >    mNotificationClients;
@@ -883,9 +633,6 @@
                 // protected by mLock
                 Vector<AudioSessionRef*> mAudioSessionRefs;
 
-                float       masterVolume_l() const;
-                float       getMasterBalance_l() const;
-                bool        masterMute_l() const;
                 AudioHwDevice* loadHwModule_l(const char *name);
 
                 // sync events awaiting for a session to be created.
@@ -900,17 +647,14 @@
                 // list of MMAP stream control threads. Those threads allow for wake lock, routing
                 // and volume control for activity on the associated MMAP stream at the HAL.
                 // Audio data transfer is directly handled by the client creating the MMAP stream
-                DefaultKeyedVector< audio_io_handle_t, sp<MmapThread> >  mMmapThreads;
+    DefaultKeyedVector<audio_io_handle_t, sp<IAfMmapThread>> mMmapThreads;
 
-private:
     sp<Client>  registerPid(pid_t pid);    // always returns non-0
 
     // for use from destructor
     status_t    closeOutput_nonvirtual(audio_io_handle_t output);
-    void        closeThreadInternal_l(const sp<PlaybackThread>& thread);
     status_t    closeInput_nonvirtual(audio_io_handle_t input);
-    void        closeThreadInternal_l(const sp<RecordThread>& thread);
-    void        setAudioHwSyncForSession_l(PlaybackThread *thread, audio_session_t sessionId);
+    void setAudioHwSyncForSession_l(IAfPlaybackThread* thread, audio_session_t sessionId);
 
     status_t    checkStreamType(audio_stream_type_t stream) const;
 
@@ -919,15 +663,10 @@
                                       size_t rejectedKVPSize, const String8& rejectedKVPs,
                                       uid_t callingUid);
 
-    sp<IAudioManager> getOrCreateAudioManager();
-
-public:
     // These methods read variables atomically without mLock,
     // though the variables are updated with mLock.
-    bool    isLowRamDevice() const { return mIsLowRamDevice; }
     size_t getClientSharedHeapSize() const;
 
-private:
     std::atomic<bool> mIsLowRamDevice;
     bool    mIsDeviceTypeKnown;
     int64_t mTotalMemory;
@@ -936,16 +675,13 @@
 
     nsecs_t mGlobalEffectEnableTime;  // when a global effect was last enabled
 
-    // protected by mLock
-    PatchPanel mPatchPanel;
-public:
-    // TODO(b/288339104) access by getter.
+    /* const */ sp<IAfPatchPanel> mPatchPanel;
+
     sp<EffectsFactoryHalInterface> mEffectsFactoryHal;
-private:
 
     const sp<PatchCommandThread> mPatchCommandThread;
-    sp<DeviceEffectManager> mDeviceEffectManager;
-    sp<MelReporter> mMelReporter;
+    /* const */ sp<DeviceEffectManager> mDeviceEffectManager;  // set onFirstRef
+    /* const */ sp<MelReporter> mMelReporter;  // set onFirstRef
 
     bool       mSystemReady;
     std::atomic_bool mAudioPolicyReady{};
@@ -960,9 +696,6 @@
 
     static inline constexpr const char *mMetricsId = AMEDIAMETRICS_KEY_AUDIO_FLINGER;
 
-    // Keep in sync with java definition in media/java/android/media/AudioRecord.java
-    static constexpr int32_t kMaxSharedAudioHistoryMs = 5000;
-
     std::map<media::audio::common::AudioMMapPolicyType,
              std::vector<media::audio::common::AudioMMapPolicyInfo>> mPolicyInfos;
     int32_t mAAudioBurstsPerBuffer = 0;
@@ -975,16 +708,6 @@
     std::atomic_bool mBluetoothLatencyModesEnabled;
 };
 
-#undef INCLUDING_FROM_AUDIOFLINGER_H
-
-std::string formatToString(audio_format_t format);
-std::string inputFlagsToString(audio_input_flags_t flags);
-std::string outputFlagsToString(audio_output_flags_t flags);
-std::string devicesToString(audio_devices_t devices);
-const char *sourceToString(audio_source_t source);
-
 // ----------------------------------------------------------------------------
 
 } // namespace android
-
-#endif // ANDROID_AUDIO_FLINGER_H
diff --git a/services/audioflinger/Client.cpp b/services/audioflinger/Client.cpp
new file mode 100644
index 0000000..93599ac
--- /dev/null
+++ b/services/audioflinger/Client.cpp
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "Client.h"
+
+namespace android {
+
+Client::Client(const sp<IAfClientCallback>& afClientCallback, pid_t pid)
+    : mAfClientCallback(afClientCallback)
+    , mPid(pid)
+    , mClientAllocator(AllocatorFactory::getClientAllocator()) {}
+
+// Client destructor must be called with AudioFlinger::mClientLock held
+Client::~Client()
+{
+    mAfClientCallback->removeClient_l(mPid);
+}
+
+AllocatorFactory::ClientAllocator& Client::allocator()
+{
+    return mClientAllocator;
+}
+
+}   // namespace android
\ No newline at end of file
diff --git a/services/audioflinger/Client.h b/services/audioflinger/Client.h
index cb507fe..b2e3cf7 100644
--- a/services/audioflinger/Client.h
+++ b/services/audioflinger/Client.h
@@ -16,26 +16,42 @@
 
 #pragma once
 
-// TODO(b/288339104) Move to nested namespace
+#include <afutils/AllocatorFactory.h>
+#include <android-base/macros.h>  // DISALLOW_COPY_AND_ASSIGN
+#include <utils/Mutex.h>
+#include <utils/RefBase.h>        // avoid transitive dependency
+
+// TODO(b/291318727) Move to nested namespace
 namespace android {
 
-class AudioFlinger;
+class IAfPlaybackThread;
+
+class IAfClientCallback : public virtual RefBase {
+public:
+    virtual Mutex& clientMutex() const = 0;
+    virtual void removeClient_l(pid_t pid) = 0;
+    virtual void removeNotificationClient(pid_t pid) = 0;
+    virtual status_t moveAuxEffectToIo(
+            int effectId,
+            const sp<IAfPlaybackThread>& dstThread,
+            sp<IAfPlaybackThread>* srcThread) = 0;  // used by indirectly by clients.
+};
 
 class Client : public RefBase {
 public:
-    Client(const sp<AudioFlinger>& audioFlinger, pid_t pid);
+    Client(const sp<IAfClientCallback>& audioFlinger, pid_t pid);
 
     // TODO(b/289139675) make Client container.
     // Client destructor must be called with AudioFlinger::mClientLock held
     ~Client() override;
     AllocatorFactory::ClientAllocator& allocator();
     pid_t pid() const { return mPid; }
-    sp<AudioFlinger> audioFlinger() const { return mAudioFlinger; }
+    const auto& afClientCallback() const { return mAfClientCallback; }
 
 private:
     DISALLOW_COPY_AND_ASSIGN(Client);
 
-    const sp<AudioFlinger> mAudioFlinger;
+    const sp<IAfClientCallback> mAfClientCallback;
     const pid_t mPid;
     AllocatorFactory::ClientAllocator mClientAllocator;
 };
diff --git a/services/audioflinger/DeviceEffectManager.cpp b/services/audioflinger/DeviceEffectManager.cpp
index 366a7ab..681ec5f 100644
--- a/services/audioflinger/DeviceEffectManager.cpp
+++ b/services/audioflinger/DeviceEffectManager.cpp
@@ -15,16 +15,17 @@
 ** limitations under the License.
 */
 
-
-#define LOG_TAG "AudioFlinger::DeviceEffectManager"
+#define LOG_TAG "DeviceEffectManager"
 //#define LOG_NDEBUG 0
 
-#include <utils/Log.h>
-#include <audio_utils/primitives.h>
+#include "DeviceEffectManager.h"
 
-#include "AudioFlinger.h"
 #include "EffectConfiguration.h"
+
+#include <afutils/DumpTryLock.h>
+#include <audio_utils/primitives.h>
 #include <media/audiohal/EffectsFactoryHalInterface.h>
+#include <utils/Log.h>
 
 // ----------------------------------------------------------------------------
 
@@ -34,39 +35,78 @@
 using detail::AudioHalVersionInfo;
 using media::IEffectClient;
 
-void AudioFlinger::DeviceEffectManager::onCreateAudioPatch(audio_patch_handle_t handle,
-        const PatchPanel::Patch& patch) {
+DeviceEffectManager::DeviceEffectManager(
+        const sp<IAfDeviceEffectManagerCallback>& afDeviceEffectManagerCallback)
+    : mAfDeviceEffectManagerCallback(afDeviceEffectManagerCallback),
+      mMyCallback(new DeviceEffectManagerCallback(*this)) {}
+
+void DeviceEffectManager::onFirstRef() {
+    mAfDeviceEffectManagerCallback->getPatchCommandThread()->addListener(this);
+}
+
+status_t DeviceEffectManager::addEffectToHal(const struct audio_port_config* device,
+        const sp<EffectHalInterface>& effect) {
+    return mAfDeviceEffectManagerCallback->addEffectToHal(device, effect);
+};
+
+status_t DeviceEffectManager::removeEffectFromHal(const struct audio_port_config* device,
+        const sp<EffectHalInterface>& effect) {
+    return mAfDeviceEffectManagerCallback->removeEffectFromHal(device, effect);
+};
+
+void DeviceEffectManager::onCreateAudioPatch(audio_patch_handle_t handle,
+        const IAfPatchPanel::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); // TODO(b/288339104) void*
-        ALOGV("%s Effect onCreatePatch status %d", __func__, status);
-        ALOGW_IF(status == BAD_VALUE, "%s onCreatePatch error %d", __func__, status);
+    for (auto& effectProxies : mDeviceEffects) {
+        for (auto& effect : effectProxies.second) {
+            const status_t status = effect->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::onReleaseAudioPatch(audio_patch_handle_t handle) {
+void DeviceEffectManager::onReleaseAudioPatch(audio_patch_handle_t handle) {
     ALOGV("%s", __func__);
     Mutex::Autolock _l(mLock);
-    for (auto& effect : mDeviceEffects) {
-        effect.second->onReleasePatch(handle);
+    for (auto& effectProxies : mDeviceEffects) {
+        for (auto& effect : effectProxies.second) {
+            effect->onReleasePatch(handle);
+        }
+    }
+}
+
+void DeviceEffectManager::onUpdateAudioPatch(audio_patch_handle_t oldHandle,
+        audio_patch_handle_t newHandle, const IAfPatchPanel::Patch& patch) {
+    ALOGV("%s oldhandle %d newHandle %d mHalHandle %d device sink %08x",
+            __func__, oldHandle, newHandle, patch.mHalHandle,
+            patch.mAudioPatch.num_sinks > 0 ? patch.mAudioPatch.sinks[0].ext.device.type : 0);
+    Mutex::Autolock _l(mLock);
+    for (auto& effectProxies : mDeviceEffects) {
+        for (auto& effect : effectProxies.second) {
+            const status_t status = effect->onUpdatePatch(oldHandle, newHandle, patch);
+            ALOGV("%s Effect onUpdatePatch status %d", __func__, status);
+            ALOGW_IF(status != NO_ERROR, "%s onUpdatePatch error %d", __func__, status);
+        }
     }
 }
 
 // DeviceEffectManager::createEffect_l() must be called with AudioFlinger::mLock held
-sp<IAfEffectHandle> AudioFlinger::DeviceEffectManager::createEffect_l(
+sp<IAfEffectHandle> DeviceEffectManager::createEffect_l(
         effect_descriptor_t *descriptor,
         const AudioDeviceTypeAddr& device,
         const sp<Client>& client,
         const sp<IEffectClient>& effectClient,
-        const std::map<audio_patch_handle_t, PatchPanel::Patch>& patches,
+        const std::map<audio_patch_handle_t, IAfPatchPanel::Patch>& patches,
         int *enabled,
         status_t *status,
         bool probe,
         bool notifyFramesProcessed) {
     sp<IAfDeviceEffectProxy> effect;
+    std::vector<sp<IAfDeviceEffectProxy>> effectsForDevice = {};
     sp<IAfEffectHandle> handle;
     status_t lStatus;
 
@@ -80,11 +120,21 @@
         Mutex::Autolock _l(mLock);
         auto iter = mDeviceEffects.find(device);
         if (iter != mDeviceEffects.end()) {
-            effect = iter->second;
-        } else {
+            effectsForDevice = iter->second;
+            for (const auto& iterEffect : effectsForDevice) {
+                if (memcmp(&iterEffect->desc().uuid, &descriptor->uuid, sizeof(effect_uuid_t)) ==
+                    0) {
+                    effect = iterEffect;
+                    break;
+                }
+            }
+        }
+        if (effect == nullptr) {
             effect = IAfDeviceEffectProxy::create(device, mMyCallback,
-                    descriptor, mAudioFlinger.nextUniqueId(AUDIO_UNIQUE_ID_USE_EFFECT),
+                    descriptor,
+                    mAfDeviceEffectManagerCallback->nextUniqueId(AUDIO_UNIQUE_ID_USE_EFFECT),
                     notifyFramesProcessed);
+            effectsForDevice.push_back(effect);
         }
         // create effect handle and connect it to effect module
         handle = IAfEffectHandle::create(
@@ -93,12 +143,13 @@
         if (lStatus == NO_ERROR) {
             lStatus = effect->addHandle(handle.get());
             if (lStatus == NO_ERROR) {
-                lStatus = effect->init(&patches); // TODO(b/288339104) void*
+                lStatus = effect->init(patches);
                 if (lStatus == NAME_NOT_FOUND) {
                     lStatus = NO_ERROR;
                 }
                 if (lStatus == NO_ERROR || lStatus == ALREADY_EXISTS) {
-                    mDeviceEffects.emplace(device, effect);
+                    mDeviceEffects.erase(device);
+                    mDeviceEffects.emplace(device, effectsForDevice);
                 }
             }
         }
@@ -110,7 +161,7 @@
     return handle;
 }
 
-status_t AudioFlinger::DeviceEffectManager::checkEffectCompatibility(
+status_t DeviceEffectManager::checkEffectCompatibility(
         const effect_descriptor_t *desc) {
     const sp<EffectsFactoryHalInterface> effectsFactory =
             audioflinger::EffectConfiguration::getEffectsFactoryHal();
@@ -136,7 +187,7 @@
     return NO_ERROR;
 }
 
-status_t AudioFlinger::DeviceEffectManager::createEffectHal(
+status_t DeviceEffectManager::createEffectHal(
         const effect_uuid_t *pEffectUuid, int32_t sessionId, int32_t deviceId,
         sp<EffectHalInterface> *effect) {
     status_t status = NO_INIT;
@@ -149,10 +200,10 @@
     return status;
 }
 
-void AudioFlinger::DeviceEffectManager::dump(int fd)
+void DeviceEffectManager::dump(int fd)
 NO_THREAD_SAFETY_ANALYSIS  // conditional try lock
 {
-    const bool locked = dumpTryLock(mLock);
+    const bool locked = afutils::dumpTryLock(mLock);
     if (!locked) {
         String8 result("DeviceEffectManager may be deadlocked\n");
         write(fd, result.string(), result.size());
@@ -164,8 +215,10 @@
         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->dump2(fd, 4);
+        for (const auto& effect : iter.second) {
+            write(fd, outStr.string(), outStr.size());
+            effect->dump2(fd, 4);
+        }
     }
 
     if (locked) {
@@ -173,15 +226,27 @@
     }
 }
 
-
-size_t AudioFlinger::DeviceEffectManager::removeEffect(const sp<IAfDeviceEffectProxy>& effect)
+size_t DeviceEffectManager::removeEffect(const sp<IAfDeviceEffectProxy>& effect)
 {
     Mutex::Autolock _l(mLock);
-    mDeviceEffects.erase(effect->device());
+    const auto& iter = mDeviceEffects.find(effect->device());
+    if (iter != mDeviceEffects.end()) {
+        const auto& iterEffect = std::find_if(
+                iter->second.begin(), iter->second.end(), [&effect](const auto& effectProxy) {
+                    return memcmp(&effectProxy->desc().uuid, &effect->desc().uuid,
+                            sizeof(effect_uuid_t)) == 0;
+                });
+        if (iterEffect != iter->second.end()) {
+            iter->second.erase(iterEffect);
+            if (iter->second.empty()) {
+                mDeviceEffects.erase(effect->device());
+            }
+        }
+    }
     return mDeviceEffects.size();
 }
 
-bool AudioFlinger::DeviceEffectManagerCallback::disconnectEffectHandle(
+bool DeviceEffectManagerCallback::disconnectEffectHandle(
         IAfEffectHandle *handle, bool unpinIfLast) {
     sp<IAfEffectBase> effectBase = handle->effect().promote();
     if (effectBase == nullptr) {
@@ -203,4 +268,12 @@
     return true;
 }
 
+bool DeviceEffectManagerCallback::isAudioPolicyReady() const {
+    return mManager.afDeviceEffectManagerCallback()->isAudioPolicyReady();
+}
+
+int DeviceEffectManagerCallback::newEffectId() const {
+    return mManager.afDeviceEffectManagerCallback()->nextUniqueId(AUDIO_UNIQUE_ID_USE_EFFECT);
+}
+
 } // namespace android
diff --git a/services/audioflinger/DeviceEffectManager.h b/services/audioflinger/DeviceEffectManager.h
index c589714..cb7fad1 100644
--- a/services/audioflinger/DeviceEffectManager.h
+++ b/services/audioflinger/DeviceEffectManager.h
@@ -15,26 +15,41 @@
 ** limitations under the License.
 */
 
-#ifndef INCLUDING_FROM_AUDIOFLINGER_H
-    #error This header file should only be included from AudioFlinger.h
-#endif
+#pragma once
+
+#include "IAfEffect.h"
+#include "PatchCommandThread.h"
+
+#include <utils/Mutex.h>  // avoid transitive dependency
+
+namespace android {
+
+class IAfDeviceEffectManagerCallback : public virtual RefBase {
+public:
+    virtual bool isAudioPolicyReady() const = 0;
+    virtual audio_unique_id_t nextUniqueId(audio_unique_id_use_t use) = 0;
+    virtual const sp<PatchCommandThread>& getPatchCommandThread() = 0;
+    virtual status_t addEffectToHal(
+            const struct audio_port_config* device, const sp<EffectHalInterface>& effect) = 0;
+    virtual status_t removeEffectFromHal(
+            const struct audio_port_config* device, const sp<EffectHalInterface>& effect) = 0;
+};
+
+class DeviceEffectManagerCallback;
 
 // DeviceEffectManager is concealed within AudioFlinger, their lifetimes are the same.
 class DeviceEffectManager : public PatchCommandThread::PatchCommandListener {
 public:
-    explicit DeviceEffectManager(AudioFlinger& audioFlinger)
-        : mAudioFlinger(audioFlinger),
-          mMyCallback(new DeviceEffectManagerCallback(*this)) {}
+    explicit DeviceEffectManager(
+            const sp<IAfDeviceEffectManagerCallback>& afDeviceEffectManagerCallback);
 
-    void onFirstRef() override {
-        mAudioFlinger.mPatchCommandThread->addListener(this);
-    }
+    void onFirstRef() override;
 
     sp<IAfEffectHandle> createEffect_l(effect_descriptor_t *descriptor,
                 const AudioDeviceTypeAddr& device,
                 const sp<Client>& client,
                 const sp<media::IEffectClient>& effectClient,
-                const std::map<audio_patch_handle_t, PatchPanel::Patch>& patches,
+                const std::map<audio_patch_handle_t, IAfPatchPanel::Patch>& patches,
                 int *enabled,
                 status_t *status,
                 bool probe,
@@ -45,34 +60,32 @@
            int32_t sessionId, int32_t deviceId,
            sp<EffectHalInterface> *effect);
     status_t addEffectToHal(const struct audio_port_config *device,
-            const sp<EffectHalInterface>& effect) {
-        return mAudioFlinger.addEffectToHal(device, effect);
-    };
+            const sp<EffectHalInterface>& effect);
     status_t removeEffectFromHal(const struct audio_port_config *device,
-            const sp<EffectHalInterface>& effect) {
-        return mAudioFlinger.removeEffectFromHal(device, effect);
-    };
+            const sp<EffectHalInterface>& effect);
 
-    AudioFlinger& audioFlinger() const { return mAudioFlinger; }
+    const auto& afDeviceEffectManagerCallback() const { return mAfDeviceEffectManagerCallback; }
 
     void dump(int fd);
 
     // PatchCommandThread::PatchCommandListener implementation
 
     void onCreateAudioPatch(audio_patch_handle_t handle,
-                            const PatchPanel::Patch& patch) override;
-    void onReleaseAudioPatch(audio_patch_handle_t handle) override;
+            const IAfPatchPanel::Patch& patch) final;
+    void onReleaseAudioPatch(audio_patch_handle_t handle) final;
+    void onUpdateAudioPatch(audio_patch_handle_t oldHandle,
+                            audio_patch_handle_t newHandle,
+                            const IAfPatchPanel::Patch& patch) final;
 
 private:
     status_t checkEffectCompatibility(const effect_descriptor_t *desc);
 
     Mutex mLock;
-    AudioFlinger &mAudioFlinger;
+    const sp<IAfDeviceEffectManagerCallback> mAfDeviceEffectManagerCallback;
     const sp<DeviceEffectManagerCallback> mMyCallback;
-    std::map<AudioDeviceTypeAddr, sp<IAfDeviceEffectProxy>> mDeviceEffects;
+    std::map<AudioDeviceTypeAddr, std::vector<sp<IAfDeviceEffectProxy>>> mDeviceEffects;
 };
 
-public: // TODO(b/288339104) extract inner class.
 class DeviceEffectManagerCallback : public EffectCallbackInterface {
 public:
     explicit DeviceEffectManagerCallback(DeviceEffectManager& manager)
@@ -129,11 +142,9 @@
 
     wp<IAfEffectChain> chain() const override { return nullptr; }
 
-    bool isAudioPolicyReady() const override {
-        return mManager.audioFlinger().isAudioPolicyReady();
-    }
+    bool isAudioPolicyReady() const final;
 
-    int newEffectId() { return mManager.audioFlinger().nextUniqueId(AUDIO_UNIQUE_ID_USE_EFFECT); }
+    int newEffectId() const;
 
     status_t addEffectToHal(const struct audio_port_config *device,
             const sp<EffectHalInterface>& effect) {
@@ -146,4 +157,5 @@
 private:
     DeviceEffectManager& mManager;
 };
-private:
+
+}  // namespace android
diff --git a/services/audioflinger/Effects.cpp b/services/audioflinger/Effects.cpp
index 1f26cb0..c3e1fba 100644
--- a/services/audioflinger/Effects.cpp
+++ b/services/audioflinger/Effects.cpp
@@ -19,10 +19,25 @@
 #define LOG_TAG "AudioFlinger"
 //#define LOG_NDEBUG 0
 
-#include <algorithm>
+#include "Effects.h"
 
-#include "Configuration.h"
-#include <utils/Log.h>
+#include "Client.h"
+#include "EffectConfiguration.h"
+
+#include <afutils/DumpTryLock.h>
+#include <audio_utils/channels.h>
+#include <audio_utils/primitives.h>
+#include <media/AudioCommonTypes.h>
+#include <media/AudioContainers.h>
+#include <media/AudioDeviceTypeAddr.h>
+#include <media/AudioEffect.h>
+#include <media/ShmemCompat.h>
+#include <media/TypeConverter.h>
+#include <media/audiohal/EffectHalInterface.h>
+#include <media/audiohal/EffectsFactoryHalInterface.h>
+#include <mediautils/MethodStatistics.h>
+#include <mediautils/ServiceUtilities.h>
+#include <mediautils/TimeCheck.h>
 #include <system/audio_effects/effect_aec.h>
 #include <system/audio_effects/effect_downmix.h>
 #include <system/audio_effects/effect_dynamicsprocessing.h>
@@ -30,22 +45,9 @@
 #include <system/audio_effects/effect_ns.h>
 #include <system/audio_effects/effect_spatializer.h>
 #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/ShmemCompat.h>
-#include <media/audiohal/EffectHalInterface.h>
-#include <media/audiohal/EffectsFactoryHalInterface.h>
-#include <mediautils/MethodStatistics.h>
-#include <mediautils/ServiceUtilities.h>
-#include <mediautils/TimeCheck.h>
+#include <utils/Log.h>
 
-#include "AudioFlinger.h"
-#include "EffectConfiguration.h"
-#include "Effects.h"
+#include <algorithm>
 
 // ----------------------------------------------------------------------------
 
@@ -507,16 +509,17 @@
 
     result.appendFormat("\tEffect ID %d:\n", mId);
 
-    bool locked = AudioFlinger::dumpTryLock(mLock);
+    const bool locked = afutils::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");
+    bool isInternal = isInternal_l();
+    result.append("\t\tSession State Registered Internal Enabled Suspended:\n");
+    result.appendFormat("\t\t%05d   %03d   %s          %s        %s       %s\n",
+            mSessionId, mState, mPolicyRegistered ? "y" : "n", isInternal ? "y" : "n",
+            ((isInternal && isEnabled()) || (!isInternal && mPolicyEnabled)) ? "y" : "n",
+            mSuspended ? "y" : "n");
 
     result.append("\t\tDescriptor:\n");
     char uuidStr[64];
@@ -1006,8 +1009,9 @@
     // mConfig.outputCfg.buffer.frameCount cannot be zero.
     mMaxDisableWaitCnt = (uint32_t)std::max(
             (uint64_t)1, // mMaxDisableWaitCnt must be greater than zero.
-            (uint64_t)MAX_DISABLE_TIME_MS * mConfig.outputCfg.samplingRate
-                / ((uint64_t)1000 * mConfig.outputCfg.buffer.frameCount));
+            (uint64_t)mConfig.outputCfg.buffer.frameCount == 0 ? 1
+                : (MAX_DISABLE_TIME_MS * mConfig.outputCfg.samplingRate
+                / ((uint64_t)1000 * mConfig.outputCfg.buffer.frameCount)));
 
 exit:
     // TODO: consider clearing mConfig on error.
@@ -1621,7 +1625,7 @@
     EffectBase::dump(fd, args);
 
     String8 result;
-    bool locked = AudioFlinger::dumpTryLock(mLock);
+    const bool locked = afutils::dumpTryLock(mLock);
 
     result.append("\t\tStatus Engine:\n");
     result.appendFormat("\t\t%03d    %p\n",
@@ -1637,7 +1641,7 @@
             mConfig.inputCfg.samplingRate,
             mConfig.inputCfg.channels,
             mConfig.inputCfg.format,
-            formatToString((audio_format_t)mConfig.inputCfg.format).c_str());
+            toString(static_cast<audio_format_t>(mConfig.inputCfg.format)).c_str());
 
     result.append("\t\t- Output configuration:\n");
     result.append("\t\t\tBuffer     Frames  Smp rate Channels Format\n");
@@ -1647,7 +1651,7 @@
             mConfig.outputCfg.samplingRate,
             mConfig.outputCfg.channels,
             mConfig.outputCfg.format,
-            formatToString((audio_format_t)mConfig.outputCfg.format).c_str());
+            toString(static_cast<audio_format_t>(mConfig.outputCfg.format)).c_str());
 
     result.appendFormat("\t\t- HAL buffers:\n"
             "\t\t\tIn(%s) InConversion(%s) Out(%s) OutConversion(%s)\n",
@@ -1886,7 +1890,7 @@
         }
         mCblkMemory.clear();    // free the shared memory before releasing the heap it belongs to
         // Client destructor must run with AudioFlinger client mutex locked
-        Mutex::Autolock _l2(mClient->audioFlinger()->mClientLock);
+        Mutex::Autolock _l2(mClient->afClientCallback()->clientMutex());
         mClient.clear();
     }
 }
@@ -2095,7 +2099,7 @@
 void EffectHandle::dumpToBuffer(char* buffer, size_t size) const
 NO_THREAD_SAFETY_ANALYSIS  // conditional try lock
 {
-    bool locked = mCblk != NULL && AudioFlinger::dumpTryLock(mCblk->lock);
+    const bool locked = mCblk != nullptr && afutils::dumpTryLock(mCblk->lock);
 
     snprintf(buffer, size, "\t\t\t%5d    %5d  %3s    %3s  %5u  %5u\n",
             (mClient == 0) ? getpid() : mClient->pid(),
@@ -2116,34 +2120,25 @@
 
 /* static */
 sp<IAfEffectChain> IAfEffectChain::create(
-        const wp<Thread /*ThreadBase*/>& wThread,  // TODO(b/288339104) update type
+        const sp<IAfThreadBase>& thread,
         audio_session_t sessionId)
 {
-    // TODO(b/288339104) no weak pointer cast.
-    return sp<EffectChain>::make(sp<AudioFlinger::ThreadBase>::cast(wThread.promote()), sessionId);
+    return sp<EffectChain>::make(thread, sessionId);
 }
 
-EffectChain::EffectChain(const wp<AudioFlinger::ThreadBase>& thread,
+EffectChain::EffectChain(const sp<IAfThreadBase>& thread,
                                        audio_session_t sessionId)
     : mSessionId(sessionId), mActiveTrackCnt(0), mTrackCnt(0), mTailBufferCount(0),
       mVolumeCtrlIdx(-1), mLeftVolume(UINT_MAX), mRightVolume(UINT_MAX),
       mNewLeftVolume(UINT_MAX), mNewRightVolume(UINT_MAX),
       mEffectCallback(new EffectCallback(wp<EffectChain>(this), thread))
 {
-    sp<AudioFlinger::ThreadBase> p = thread.promote();
-    if (p == nullptr) {
-        return;
-    }
-    mStrategy = p->getStrategyForStream(AUDIO_STREAM_MUSIC);
-    mMaxTailBuffers = ((kProcessTailDurationMs * p->sampleRate()) / 1000) /
-                                    p->frameCount();
+    mStrategy = thread->getStrategyForStream(AUDIO_STREAM_MUSIC);
+    mMaxTailBuffers = ((kProcessTailDurationMs * thread->sampleRate()) / 1000) /
+                                    thread->frameCount();
 }
 
-EffectChain::~EffectChain()
-{
-}
-
-// getEffectFromDesc_l() must be called with AudioFlinger::ThreadBase::mLock held
+// getEffectFromDesc_l() must be called with IAfThreadBase::mutex() held
 sp<IAfEffectModule> EffectChain::getEffectFromDesc_l(
         effect_descriptor_t *descriptor) const
 {
@@ -2157,7 +2152,7 @@
     return 0;
 }
 
-// getEffectFromId_l() must be called with AudioFlinger::ThreadBase::mLock held
+// getEffectFromId_l() must be called with IAfThreadBase::mutex() held
 sp<IAfEffectModule> EffectChain::getEffectFromId_l(int id) const
 {
     size_t size = mEffects.size();
@@ -2171,7 +2166,7 @@
     return 0;
 }
 
-// getEffectFromType_l() must be called with AudioFlinger::ThreadBase::mLock held
+// getEffectFromType_l() must be called with IAfThreadBase::mutex() held
 sp<IAfEffectModule> EffectChain::getEffectFromType_l(
         const effect_uuid_t *type) const
 {
@@ -2266,7 +2261,7 @@
     }
 }
 
-// createEffect_l() must be called with AudioFlinger::ThreadBase::mLock held
+// createEffect_l() must be called with IAfThreadBase::mutex() held
 status_t EffectChain::createEffect_l(sp<IAfEffectModule>& effect,
                                                    effect_descriptor_t *desc,
                                                    int id,
@@ -2285,13 +2280,13 @@
     return lStatus;
 }
 
-// addEffect_l() must be called with AudioFlinger::ThreadBase::mLock held
+// addEffect_l() must be called with IAfThreadBase::mutex() held
 status_t EffectChain::addEffect_l(const sp<IAfEffectModule>& effect)
 {
     Mutex::Autolock _l(mLock);
     return addEffect_ll(effect);
 }
-// addEffect_l() must be called with AudioFlinger::ThreadBase::mLock and EffectChain::mLock held
+// addEffect_l() must be called with IAfThreadBase::mLock and EffectChain::mutex() held
 status_t EffectChain::addEffect_ll(const sp<IAfEffectModule>& effect)
 {
     effect->setCallback(mEffectCallback);
@@ -2445,7 +2440,7 @@
     return idx_insert;
 }
 
-// removeEffect_l() must be called with AudioFlinger::ThreadBase::mLock held
+// removeEffect_l() must be called with IAfThreadBase::mutex() held
 size_t EffectChain::removeEffect_l(const sp<IAfEffectModule>& effect,
                                                  bool release)
 {
@@ -2493,7 +2488,7 @@
     return mEffects.size();
 }
 
-// setDevices_l() must be called with AudioFlinger::ThreadBase::mLock held
+// setDevices_l() must be called with IAfThreadBase::mutex() held
 void EffectChain::setDevices_l(const AudioDeviceTypeAddrVector &devices)
 {
     size_t size = mEffects.size();
@@ -2502,7 +2497,7 @@
     }
 }
 
-// setInputDevice_l() must be called with AudioFlinger::ThreadBase::mLock held
+// setInputDevice_l() must be called with IAfThreadBase::mutex() held
 void EffectChain::setInputDevice_l(const AudioDeviceTypeAddr &device)
 {
     size_t size = mEffects.size();
@@ -2511,7 +2506,7 @@
     }
 }
 
-// setMode_l() must be called with AudioFlinger::ThreadBase::mLock held
+// setMode_l() must be called with IAfThreadBase::mutex() held
 void EffectChain::setMode_l(audio_mode_t mode)
 {
     size_t size = mEffects.size();
@@ -2520,7 +2515,7 @@
     }
 }
 
-// setAudioSource_l() must be called with AudioFlinger::ThreadBase::mLock held
+// setAudioSource_l() must be called with IAfThreadBase::mutex() held
 void EffectChain::setAudioSource_l(audio_source_t source)
 {
     size_t size = mEffects.size();
@@ -2536,7 +2531,7 @@
     return false;
 }
 
-// setVolume_l() must be called with AudioFlinger::ThreadBase::mLock or EffectChain::mLock held
+// setVolume_l() must be called with IAfThreadBase::mLock or EffectChain::mLock held
 bool EffectChain::setVolume_l(uint32_t *left, uint32_t *right, bool force)
 {
     uint32_t newLeft = *left;
@@ -2603,7 +2598,7 @@
     return hasControl;
 }
 
-// resetVolume_l() must be called with AudioFlinger::ThreadBase::mLock or EffectChain::mLock held
+// resetVolume_l() must be called with IAfThreadBase::mutex() or EffectChain::mLock held
 void EffectChain::resetVolume_l()
 {
     if ((mLeftVolume != UINT_MAX) && (mRightVolume != UINT_MAX)) {
@@ -2614,7 +2609,7 @@
 }
 
 // containsHapticGeneratingEffect_l must be called with
-// AudioFlinger::ThreadBase::mLock or EffectChain::mLock held
+// IAfThreadBase::mutex() or EffectChain::mLock held
 bool EffectChain::containsHapticGeneratingEffect_l()
 {
     for (size_t i = 0; i < mEffects.size(); ++i) {
@@ -2653,7 +2648,7 @@
     result.appendFormat("    %zu effects for session %d\n", numEffects, mSessionId);
 
     if (numEffects) {
-        bool locked = AudioFlinger::dumpTryLock(mLock);
+        const bool locked = afutils::dumpTryLock(mLock);
         // failed to lock - AudioFlinger is probably deadlocked
         if (!locked) {
             result.append("\tCould not lock mutex:\n");
@@ -2683,7 +2678,7 @@
     }
 }
 
-// must be called with AudioFlinger::ThreadBase::mLock held
+// must be called with IAfThreadBase::mutex() held
 void EffectChain::setEffectSuspended_l(
         const effect_uuid_t *type, bool suspend)
 {
@@ -2739,7 +2734,7 @@
     }
 }
 
-// must be called with AudioFlinger::ThreadBase::mLock held
+// must be called with IAfThreadBase::mutex() held
 void EffectChain::setEffectSuspendedAll_l(bool suspend)
 {
     sp<SuspendedEffectDesc> desc;
@@ -2895,7 +2890,7 @@
     return false;
 }
 
-void EffectChain::setThread(const sp<AudioFlinger::ThreadBase>& thread)
+void EffectChain::setThread(const sp<IAfThreadBase>& thread)
 {
     Mutex::Autolock _l(mLock);
     mEffectCallback->setThread(thread);
@@ -2962,7 +2957,7 @@
 }
 
 // isCompatibleWithThread_l() must be called with thread->mLock held
-bool EffectChain::isCompatibleWithThread_l(const sp<AudioFlinger::ThreadBase>& thread) const
+bool EffectChain::isCompatibleWithThread_l(const sp<IAfThreadBase>& thread) const
 {
     Mutex::Autolock _l(mLock);
     for (size_t i = 0; i < mEffects.size(); i++) {
@@ -2989,18 +2984,18 @@
 bool EffectChain::EffectCallback::updateOrphanEffectChains(
         const sp<IAfEffectBase>& effect) {
     // in EffectChain context, an EffectBase is always from an EffectModule so static cast is safe
-    return mAudioFlinger.updateOrphanEffectChains(effect->asEffectModule());
+    return mAfThreadCallback->updateOrphanEffectChains(effect->asEffectModule());
 }
 
 status_t EffectChain::EffectCallback::allocateHalBuffer(
         size_t size, sp<EffectBufferHalInterface>* buffer) {
-    return mAudioFlinger.mEffectsFactoryHal->allocateBuffer(size, buffer);
+    return mAfThreadCallback->getEffectsFactoryHal()->allocateBuffer(size, buffer);
 }
 
 status_t EffectChain::EffectCallback::addEffectToHal(
         const sp<EffectHalInterface>& effect) {
     status_t result = NO_INIT;
-    sp<AudioFlinger::ThreadBase> t = thread().promote();
+    const sp<IAfThreadBase> t = thread().promote();
     if (t == nullptr) {
         return result;
     }
@@ -3016,7 +3011,7 @@
 status_t EffectChain::EffectCallback::removeEffectFromHal(
         const sp<EffectHalInterface>& effect) {
     status_t result = NO_INIT;
-    sp<AudioFlinger::ThreadBase> t = thread().promote();
+    const sp<IAfThreadBase> t = thread().promote();
     if (t == nullptr) {
         return result;
     }
@@ -3030,7 +3025,7 @@
 }
 
 audio_io_handle_t EffectChain::EffectCallback::io() const {
-    sp<AudioFlinger::ThreadBase> t = thread().promote();
+    const sp<IAfThreadBase> t = thread().promote();
     if (t == nullptr) {
         return AUDIO_IO_HANDLE_NONE;
     }
@@ -3038,7 +3033,7 @@
 }
 
 bool EffectChain::EffectCallback::isOutput() const {
-    sp<AudioFlinger::ThreadBase> t = thread().promote();
+    const sp<IAfThreadBase> t = thread().promote();
     if (t == nullptr) {
         return true;
     }
@@ -3046,19 +3041,19 @@
 }
 
 bool EffectChain::EffectCallback::isOffload() const {
-    return mThreadType == AudioFlinger::ThreadBase::OFFLOAD;
+    return mThreadType == IAfThreadBase::OFFLOAD;
 }
 
 bool EffectChain::EffectCallback::isOffloadOrDirect() const {
-    return mThreadType == AudioFlinger::ThreadBase::OFFLOAD
-            || mThreadType == AudioFlinger::ThreadBase::DIRECT;
+    return mThreadType == IAfThreadBase::OFFLOAD
+            || mThreadType == IAfThreadBase::DIRECT;
 }
 
 bool EffectChain::EffectCallback::isOffloadOrMmap() const {
     switch (mThreadType) {
-    case AudioFlinger::ThreadBase::OFFLOAD:
-    case AudioFlinger::ThreadBase::MMAP_PLAYBACK:
-    case AudioFlinger::ThreadBase::MMAP_CAPTURE:
+    case IAfThreadBase::OFFLOAD:
+    case IAfThreadBase::MMAP_PLAYBACK:
+    case IAfThreadBase::MMAP_CAPTURE:
         return true;
     default:
         return false;
@@ -3066,11 +3061,11 @@
 }
 
 bool EffectChain::EffectCallback::isSpatializer() const {
-    return mThreadType == AudioFlinger::ThreadBase::SPATIALIZER;
+    return mThreadType == IAfThreadBase::SPATIALIZER;
 }
 
 uint32_t EffectChain::EffectCallback::sampleRate() const {
-    sp<AudioFlinger::ThreadBase> t = thread().promote();
+    const sp<IAfThreadBase> t = thread().promote();
     if (t == nullptr) {
         return 0;
     }
@@ -3078,7 +3073,7 @@
 }
 
 audio_channel_mask_t EffectChain::EffectCallback::inChannelMask(int id) const {
-    sp<AudioFlinger::ThreadBase> t = thread().promote();
+    const sp<IAfThreadBase> t = thread().promote();
     if (t == nullptr) {
         return AUDIO_CHANNEL_NONE;
     }
@@ -3087,7 +3082,7 @@
         return AUDIO_CHANNEL_NONE;
     }
 
-    if (mThreadType == AudioFlinger::ThreadBase::SPATIALIZER) {
+    if (mThreadType == IAfThreadBase::SPATIALIZER) {
         if (c->sessionId() == AUDIO_SESSION_OUTPUT_STAGE) {
             if (c->isFirstEffect(id)) {
                 return t->mixerChannelMask();
@@ -3096,7 +3091,7 @@
             }
         } else if (!audio_is_global_session(c->sessionId())) {
             if ((t->hasAudioSession_l(c->sessionId())
-                    & AudioFlinger::ThreadBase::SPATIALIZED_SESSION) != 0) {
+                    & IAfThreadBase::SPATIALIZED_SESSION) != 0) {
                 return t->mixerChannelMask();
             } else {
                 return t->channelMask();
@@ -3114,7 +3109,7 @@
 }
 
 audio_channel_mask_t EffectChain::EffectCallback::outChannelMask() const {
-    sp<AudioFlinger::ThreadBase> t = thread().promote();
+    const sp<IAfThreadBase> t = thread().promote();
     if (t == nullptr) {
         return AUDIO_CHANNEL_NONE;
     }
@@ -3123,10 +3118,10 @@
         return AUDIO_CHANNEL_NONE;
     }
 
-    if (mThreadType == AudioFlinger::ThreadBase::SPATIALIZER) {
+    if (mThreadType == IAfThreadBase::SPATIALIZER) {
         if (!audio_is_global_session(c->sessionId())) {
             if ((t->hasAudioSession_l(c->sessionId())
-                    & AudioFlinger::ThreadBase::SPATIALIZED_SESSION) != 0) {
+                    & IAfThreadBase::SPATIALIZED_SESSION) != 0) {
                 return t->mixerChannelMask();
             } else {
                 return t->channelMask();
@@ -3144,7 +3139,7 @@
 }
 
 audio_channel_mask_t EffectChain::EffectCallback::hapticChannelMask() const {
-    sp<AudioFlinger::ThreadBase> t = thread().promote();
+    const sp<IAfThreadBase> t = thread().promote();
     if (t == nullptr) {
         return AUDIO_CHANNEL_NONE;
     }
@@ -3152,7 +3147,7 @@
 }
 
 size_t EffectChain::EffectCallback::frameCount() const {
-    sp<AudioFlinger::ThreadBase> t = thread().promote();
+    const sp<IAfThreadBase> t = thread().promote();
     if (t == nullptr) {
         return 0;
     }
@@ -3162,7 +3157,7 @@
 uint32_t EffectChain::EffectCallback::latency() const
 NO_THREAD_SAFETY_ANALYSIS  // latency_l() access
 {
-    sp<AudioFlinger::ThreadBase> t = thread().promote();
+    const sp<IAfThreadBase> t = thread().promote();
     if (t == nullptr) {
         return 0;
     }
@@ -3173,7 +3168,7 @@
 void EffectChain::EffectCallback::setVolumeForOutput(float left, float right) const
 NO_THREAD_SAFETY_ANALYSIS  // setVolumeForOutput_l() access
 {
-    sp<AudioFlinger::ThreadBase> t = thread().promote();
+    const sp<IAfThreadBase> t = thread().promote();
     if (t == nullptr) {
         return;
     }
@@ -3182,7 +3177,7 @@
 
 void EffectChain::EffectCallback::checkSuspendOnEffectEnabled(
         const sp<IAfEffectBase>& effect, bool enabled, bool threadLocked) {
-    sp<AudioFlinger::ThreadBase> t = thread().promote();
+    const sp<IAfThreadBase> t = thread().promote();
     if (t == nullptr) {
         return;
     }
@@ -3197,7 +3192,7 @@
 }
 
 void EffectChain::EffectCallback::onEffectEnable(const sp<IAfEffectBase>& effect) {
-    sp<AudioFlinger::ThreadBase> t = thread().promote();
+    const sp<IAfThreadBase> t = thread().promote();
     if (t == nullptr) {
         return;
     }
@@ -3208,7 +3203,7 @@
 void EffectChain::EffectCallback::onEffectDisable(const sp<IAfEffectBase>& effect) {
     checkSuspendOnEffectEnabled(effect, false, false /*threadLocked*/);
 
-    sp<AudioFlinger::ThreadBase> t = thread().promote();
+    const sp<IAfThreadBase> t = thread().promote();
     if (t == nullptr) {
         return;
     }
@@ -3217,7 +3212,7 @@
 
 bool EffectChain::EffectCallback::disconnectEffectHandle(IAfEffectHandle *handle,
                                                       bool unpinIfLast) {
-    sp<AudioFlinger::ThreadBase> t = thread().promote();
+    const sp<IAfThreadBase> t = thread().promote();
     if (t == nullptr) {
         return false;
     }
@@ -3257,11 +3252,11 @@
 /* static */
 sp<IAfDeviceEffectProxy> IAfDeviceEffectProxy::create(
         const AudioDeviceTypeAddr& device,
-        const sp</* DeviceEffectManagerCallback */ RefBase>& callback,  // TODO(b/288339104) type
+        const sp<DeviceEffectManagerCallback>& callback,
         effect_descriptor_t *desc, int id, bool notifyFramesProcessed)
 {
     return sp<DeviceEffectProxy>::make(device,
-            sp<AudioFlinger::DeviceEffectManagerCallback>::cast(callback),
+            callback,
             desc, id, notifyFramesProcessed);
 }
 
@@ -3287,7 +3282,7 @@
 }
 
 status_t DeviceEffectProxy::init(
-        const std::map <audio_patch_handle_t, AudioFlinger::PatchPanel::Patch>& patches) {
+        const std::map <audio_patch_handle_t, IAfPatchPanel::Patch>& patches) {
 //For all audio patches
 //If src or sink device match
 //If the effect is HW accelerated
@@ -3309,8 +3304,25 @@
     return status;
 }
 
+status_t DeviceEffectProxy::onUpdatePatch(audio_patch_handle_t oldPatchHandle,
+        audio_patch_handle_t newPatchHandle,
+        const IAfPatchPanel::Patch& /* patch */) {
+    status_t status = NAME_NOT_FOUND;
+    ALOGV("%s", __func__);
+    Mutex::Autolock _l(mProxyLock);
+    if (mEffectHandles.find(oldPatchHandle) != mEffectHandles.end()) {
+        ALOGV("%s replacing effect from handle %d to handle %d", __func__, oldPatchHandle,
+                newPatchHandle);
+        sp<IAfEffectHandle> effect = mEffectHandles.at(oldPatchHandle);
+        mEffectHandles.erase(oldPatchHandle);
+        mEffectHandles.emplace(newPatchHandle, effect);
+        status = NO_ERROR;
+    }
+    return status;
+}
+
 status_t DeviceEffectProxy::onCreatePatch(
-        audio_patch_handle_t patchHandle, const AudioFlinger::PatchPanel::Patch& patch) {
+        audio_patch_handle_t patchHandle, const IAfPatchPanel::Patch& patch) {
     status_t status = NAME_NOT_FOUND;
     sp<IAfEffectHandle> handle;
     // only consider source[0] as this is the only "true" source of a patch
@@ -3322,6 +3334,9 @@
     }
     if (status == NO_ERROR || status == ALREADY_EXISTS) {
         Mutex::Autolock _l(mProxyLock);
+        size_t erasedHandle = mEffectHandles.erase(patchHandle);
+        ALOGV("%s %s effecthandle %p for patch %d",
+                __func__, (erasedHandle == 0 ? "adding" : "replacing"), handle.get(), patchHandle);
         mEffectHandles.emplace(patchHandle, handle);
     }
     ALOGW_IF(status == BAD_VALUE,
@@ -3330,7 +3345,7 @@
     return status;
 }
 
-status_t DeviceEffectProxy::checkPort(const AudioFlinger::PatchPanel::Patch& patch,
+status_t DeviceEffectProxy::checkPort(const IAfPatchPanel::Patch& patch,
         const struct audio_port_config *port, sp<IAfEffectHandle> *handle) {
 
     ALOGV("%s type %d device type %d address %s device ID %d patch.isSoftware() %d",
@@ -3354,18 +3369,21 @@
 
     if (mDescriptor.flags & EFFECT_FLAG_HW_ACC_TUNNEL) {
         Mutex::Autolock _l(mProxyLock);
-        mDevicePort = *port;
-        mHalEffect = new EffectModule(mMyCallback,
+        if (mHalEffect != nullptr && mDevicePort.id == port->id) {
+            ALOGV("%s reusing HAL effect", __func__);
+        } else {
+            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});
+            if (audio_is_input_device(mDevice.mType)) {
+                mHalEffect->setInputDevice(mDevice);
+            } else {
+                mHalEffect->setDevices({mDevice});
+            }
+            mHalEffect->configure();
         }
-        mHalEffect->configure();
-
         *handle = new EffectHandle(mHalEffect, nullptr, nullptr, 0 /*priority*/,
                                    mNotifyFramesProcessed);
         status = (*handle)->initCheck();
@@ -3376,7 +3394,7 @@
             mDevicePort.id = AUDIO_PORT_HANDLE_NONE;
         }
     } else if (patch.isSoftware() || patch.thread().promote() != nullptr) {
-        sp <AudioFlinger::ThreadBase> thread;
+        sp<IAfThreadBase> thread;
         if (audio_port_config_has_input_direction(port)) {
             if (patch.isSoftware()) {
                 thread = patch.mRecord.thread();
@@ -3453,6 +3471,23 @@
     return mManagerCallback->removeEffectFromHal(&mDevicePort, effect);
 }
 
+status_t DeviceEffectProxy::command(
+        int32_t cmdCode, const std::vector<uint8_t>& cmdData, int32_t maxReplySize,
+        std::vector<uint8_t>* reply) {
+    Mutex::Autolock _l(mProxyLock);
+    status_t status = EffectBase::command(cmdCode, cmdData, maxReplySize, reply);
+    if (status == NO_ERROR) {
+        for (auto& handle : mEffectHandles) {
+            sp<IAfEffectBase> effect = handle.second->effect().promote();
+            if (effect != nullptr) {
+                status = effect->command(cmdCode, cmdData, maxReplySize, reply);
+            }
+        }
+    }
+    ALOGV("%s status %d", __func__, status);
+    return status;
+}
+
 bool DeviceEffectProxy::isOutput() const {
     if (mDevicePort.id != AUDIO_PORT_HANDLE_NONE) {
         return mDevicePort.role == AUDIO_PORT_ROLE_SINK;
@@ -3489,7 +3524,7 @@
     const Vector<String16> args;
     EffectBase::dump(fd, args);
 
-    const bool locked = AudioFlinger::dumpTryLock(mProxyLock);
+    const bool locked = afutils::dumpTryLock(mProxyLock);
     if (!locked) {
         String8 result("DeviceEffectProxy may be deadlocked\n");
         write(fd, result.string(), result.size());
@@ -3519,7 +3554,7 @@
     }
 
     if (locked) {
-        mLock.unlock();
+        mProxyLock.unlock();
     }
 }
 
diff --git a/services/audioflinger/Effects.h b/services/audioflinger/Effects.h
index 07790be..79b4e63 100644
--- a/services/audioflinger/Effects.h
+++ b/services/audioflinger/Effects.h
@@ -15,6 +15,17 @@
 ** limitations under the License.
 */
 
+#pragma once
+
+#include "DeviceEffectManager.h"
+#include "IAfEffect.h"
+
+#include <android-base/macros.h>  // DISALLOW_COPY_AND_ASSIGN
+#include <mediautils/Synchronization.h>
+#include <private/media/AudioEffectShared.h>
+
+#include <map>  // avoid transitive dependency
+
 namespace android {
 
 //--- Audio Effect Management
@@ -382,8 +393,7 @@
 // it also provide it's own input buffer used by the track as accumulation buffer.
 class EffectChain : public IAfEffectChain {
 public:
-    EffectChain(const wp<AudioFlinger::ThreadBase>& wThread, audio_session_t sessionId);
-    ~EffectChain() override;
+    EffectChain(const sp<IAfThreadBase>& thread, audio_session_t sessionId);
 
     void process_l() final;
 
@@ -479,12 +489,7 @@
     bool isBitPerfectCompatible() const final;
 
     // isCompatibleWithThread_l() must be called with thread->mLock held
-    // TODO(b/288339104) type
-    bool isCompatibleWithThread_l(const sp<Thread>& thread) const final {
-        return isCompatibleWithThread_l(sp<AudioFlinger::ThreadBase>::cast(thread));
-    }
-
-    bool isCompatibleWithThread_l(const sp<AudioFlinger::ThreadBase>& thread) const;
+    bool isCompatibleWithThread_l(const sp<IAfThreadBase>& thread) const final;
 
     bool containsHapticGeneratingEffect_l() final;
 
@@ -492,8 +497,7 @@
 
     sp<EffectCallbackInterface> effectCallback() const final { return mEffectCallback; }
 
-    // TODO(b/288339104) type
-    wp<Thread> thread() const final { return mEffectCallback->thread(); }
+    wp<IAfThreadBase> thread() const final { return mEffectCallback->thread(); }
 
     bool isFirstEffect(int id) const final {
         return !mEffects.isEmpty() && id == mEffects[0]->id();
@@ -507,12 +511,7 @@
         return mEffects[index];
     }
 
-    // TODO(b/288339104) type
-    void setThread(const sp<Thread>& thread) final {
-        setThread(sp<AudioFlinger::ThreadBase>::cast(thread));
-    }
-
-    void setThread(const sp<AudioFlinger::ThreadBase>& thread);
+    void setThread(const sp<IAfThreadBase>& thread) final;
 
 private:
 
@@ -527,16 +526,11 @@
         // 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<AudioFlinger::ThreadBase>& thread)
+                const sp<IAfThreadBase>& thread)  // we take a sp<> but store a wp<>.
             : mChain(owner)
-            , mThread(thread)
-            , mAudioFlinger(*AudioFlinger::gAudioFlinger) {
-            sp<AudioFlinger::ThreadBase> base = thread.promote();
-            if (base != nullptr) {
-                mThreadType = base->type();
-            } else {
-                mThreadType = AudioFlinger::ThreadBase::MIXER;  // assure a consistent value.
-            }
+            , mThread(thread) {
+            mThreadType = thread->type();
+            mAfThreadCallback = thread->afThreadCallback();
         }
 
         status_t createEffectHal(const effect_uuid_t *pEffectUuid,
@@ -577,21 +571,22 @@
         wp<IAfEffectChain> chain() const final { return mChain; }
 
         bool isAudioPolicyReady() const final {
-            return mAudioFlinger.isAudioPolicyReady();
+            return mAfThreadCallback->isAudioPolicyReady();
         }
 
-        wp<AudioFlinger::ThreadBase> thread() const { return mThread.load(); }
+        wp<IAfThreadBase> thread() const { return mThread.load(); }
 
-        void setThread(const sp<AudioFlinger::ThreadBase>& thread) {
+        void setThread(const sp<IAfThreadBase>& thread) {
             mThread = thread;
             mThreadType = thread->type();
+            mAfThreadCallback = thread->afThreadCallback();
         }
 
     private:
         const wp<IAfEffectChain> mChain;
-        mediautils::atomic_wp<AudioFlinger::ThreadBase> mThread;
-        AudioFlinger &mAudioFlinger;  // implementation detail: outer instance always exists.
-        AudioFlinger::ThreadBase::type_t mThreadType;
+        mediautils::atomic_wp<IAfThreadBase> mThread;
+        sp<IAfThreadCallback> mAfThreadCallback;
+        IAfThreadBase::type_t mThreadType;
     };
 
     DISALLOW_COPY_AND_ASSIGN(EffectChain);
@@ -657,7 +652,7 @@
 class DeviceEffectProxy : public IAfDeviceEffectProxy, public EffectBase {
 public:
     DeviceEffectProxy(const AudioDeviceTypeAddr& device,
-                const sp<AudioFlinger::DeviceEffectManagerCallback>& callback,
+            const sp<DeviceEffectManagerCallback>& callback,
                 effect_descriptor_t *desc, int id, bool notifyFramesProcessed)
             : EffectBase(callback, desc, id, AUDIO_SESSION_DEVICE, false),
                 mDevice(device), mManagerCallback(callback),
@@ -667,22 +662,14 @@
     status_t setEnabled(bool enabled, bool fromHandle) final;
     sp<IAfDeviceEffectProxy> asDeviceEffectProxy() final { return this; }
 
-    // TODO(b/288339104) type
-    status_t init(const /* std::map<audio_patch_handle_t,
-            PatchPanel::Patch>& */ void * patches) final {
-        return init(*reinterpret_cast<const std::map<
-                audio_patch_handle_t, AudioFlinger::PatchPanel::Patch> *>(patches));
-    }
-    // TODO(b/288339104) type
-    status_t onCreatePatch(audio_patch_handle_t patchHandle,
-            /* const PatchPanel::Patch& */ const void * patch) final {
-        return onCreatePatch(patchHandle,
-                *reinterpret_cast<const AudioFlinger::PatchPanel::Patch *>(patch));
-    }
+    status_t init(const std::map<audio_patch_handle_t,
+            IAfPatchPanel::Patch>& patches) final;
 
-    status_t init(const std::map<audio_patch_handle_t, AudioFlinger::PatchPanel::Patch>& patches);
-    status_t onCreatePatch(
-            audio_patch_handle_t patchHandle, const AudioFlinger::PatchPanel::Patch& patch);
+    status_t onCreatePatch(audio_patch_handle_t patchHandle,
+            const IAfPatchPanel::Patch& patch) final;
+
+    status_t onUpdatePatch(audio_patch_handle_t oldPatchHandle, audio_patch_handle_t newPatchHandle,
+           const IAfPatchPanel::Patch& patch) final;
 
     void onReleasePatch(audio_patch_handle_t patchHandle) final;
 
@@ -697,6 +684,11 @@
     audio_channel_mask_t channelMask() const final;
     uint32_t channelCount() const final;
 
+    status_t command(int32_t cmdCode,
+                     const std::vector<uint8_t>& cmdData,
+                     int32_t maxReplySize,
+                     std::vector<uint8_t>* reply) final;
+
     void dump2(int fd, int spaces) const final;
 
 private:
@@ -706,7 +698,7 @@
         // 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<AudioFlinger::DeviceEffectManagerCallback>& callback)
+                const sp<DeviceEffectManagerCallback>& callback)
             : mProxy(owner), mManagerCallback(callback) {}
 
         status_t createEffectHal(const effect_uuid_t *pEffectUuid,
@@ -757,14 +749,14 @@
 
     private:
         const wp<DeviceEffectProxy> mProxy;
-        const sp<AudioFlinger::DeviceEffectManagerCallback> mManagerCallback;
+        const sp<DeviceEffectManagerCallback> mManagerCallback;
     };
 
-    status_t checkPort(const AudioFlinger::PatchPanel::Patch& patch,
+    status_t checkPort(const IAfPatchPanel::Patch& patch,
             const struct audio_port_config *port, sp<IAfEffectHandle> *handle);
 
     const AudioDeviceTypeAddr mDevice;
-    const sp<AudioFlinger::DeviceEffectManagerCallback> mManagerCallback;
+    const sp<DeviceEffectManagerCallback> mManagerCallback;
     const sp<ProxyCallback> mMyCallback;
 
     mutable Mutex mProxyLock;
diff --git a/services/audioflinger/IAfEffect.h b/services/audioflinger/IAfEffect.h
index 75112ca..c4f0de3 100644
--- a/services/audioflinger/IAfEffect.h
+++ b/services/audioflinger/IAfEffect.h
@@ -16,13 +16,28 @@
 
 #pragma once
 
+#include "IAfPatchPanel.h"  // full class Patch definition needed
+
+#include <android/media/AudioVibratorInfo.h>
+#include <android/media/BnEffect.h>
+#include <android/media/BnEffectClient.h>
+#include <media/AudioCommonTypes.h>  // product_strategy_t
+#include <media/AudioDeviceTypeAddr.h>
+#include <media/audiohal/EffectHalInterface.h>
+#include <utils/RefBase.h>
+#include <vibrator/ExternalVibration.h>
+
 namespace android {
 
+class Client;
+class DeviceEffectManagerCallback;
+
 class IAfDeviceEffectProxy;
 class IAfEffectBase;
 class IAfEffectChain;
 class IAfEffectHandle;
 class IAfEffectModule;
+class IAfThreadBase;
 
 // 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.
@@ -109,6 +124,11 @@
     virtual sp<IAfEffectModule> asEffectModule() = 0;
     virtual sp<IAfDeviceEffectProxy> asDeviceEffectProxy() = 0;
 
+    virtual status_t command(int32_t cmdCode,
+            const std::vector<uint8_t>& cmdData,
+            int32_t maxReplySize,
+            std::vector<uint8_t>* reply) = 0;
+
     virtual void dump(int fd, const Vector<String16>& args) const = 0;
 
 private:
@@ -117,11 +137,6 @@
     virtual void setSuspended(bool suspended) = 0;
     virtual bool suspended() const = 0;
 
-    virtual status_t command(int32_t cmdCode,
-            const std::vector<uint8_t>& cmdData,
-            int32_t maxReplySize,
-            std::vector<uint8_t>* reply) = 0;
-
     virtual ssize_t disconnectHandle(IAfEffectHandle *handle, bool unpinIfLast) = 0;
     virtual ssize_t removeHandle_l(IAfEffectHandle *handle) = 0;
     virtual IAfEffectHandle* controlHandle_l() = 0;
@@ -190,7 +205,7 @@
     // Most of these methods are accessed from AudioFlinger::Thread
 public:
     static sp<IAfEffectChain> create(
-            const wp<Thread /*ThreadBase*/>& wThread,  // TODO(b/288339104) type
+            const sp<IAfThreadBase>& thread,
             audio_session_t sessionId);
 
     // special key used for an entry in mSuspendedEffects keyed vector
@@ -279,8 +294,7 @@
     virtual bool isBitPerfectCompatible() const = 0;
 
     // isCompatibleWithThread_l() must be called with thread->mLock held
-    //  TODO(b/288339104) type
-    virtual bool isCompatibleWithThread_l(const sp<Thread>& thread) const = 0;
+    virtual bool isCompatibleWithThread_l(const sp<IAfThreadBase>& thread) const = 0;
 
     virtual bool containsHapticGeneratingEffect_l() = 0;
 
@@ -288,8 +302,8 @@
 
     virtual sp<EffectCallbackInterface> effectCallback() const = 0;
 
-    virtual wp<Thread> thread() const = 0;  // TODO(b/288339104) type
-    virtual void setThread(const sp<Thread>& thread) = 0;  // TODO(b/288339104) type
+    virtual wp<IAfThreadBase> thread() const = 0;
+    virtual void setThread(const sp<IAfThreadBase>& thread) = 0;
 
     virtual bool isFirstEffect(int id) const = 0;
 
@@ -335,22 +349,24 @@
 
 class IAfDeviceEffectProxy : public virtual IAfEffectBase {
 public:
-    // TODO(b/288339104) type
     static sp<IAfDeviceEffectProxy> create(const AudioDeviceTypeAddr& device,
-                const sp</* DeviceEffectManagerCallback */ RefBase>& callback,
+                const sp<DeviceEffectManagerCallback>& callback,
                 effect_descriptor_t *desc, int id, bool notifyFramesProcessed);
 
     virtual status_t init(
-            const /* std::map<audio_patch_handle_t,
-            PatchPanel::Patch>& */ void * patches) = 0; // TODO(b/288339104) type
+            const std::map<audio_patch_handle_t,
+            IAfPatchPanel::Patch>& patches) = 0;
     virtual const AudioDeviceTypeAddr& device() const = 0;
 
     virtual status_t onCreatePatch(
             audio_patch_handle_t patchHandle,
-            /* const PatchPanel::Patch& */ const void * patch) = 0;
+            const IAfPatchPanel::Patch& patch) = 0;
+    virtual status_t onUpdatePatch(audio_patch_handle_t oldPatchHandle,
+            audio_patch_handle_t newPatchHandle,
+            const IAfPatchPanel::Patch& patch) = 0;
     virtual void onReleasePatch(audio_patch_handle_t patchHandle) = 0;
 
-    virtual void dump2(int fd, int spaces) const = 0; // TODO(b/288339104) naming?
+    virtual void dump2(int fd, int spaces) const = 0; // TODO(b/291319101) naming?
 
 private:
     // used by DeviceEffectProxy
@@ -364,4 +380,4 @@
     virtual status_t removeEffectFromHal(const sp<EffectHalInterface>& effect) = 0;
 };
 
-} // namespace android
+}  // namespace android
diff --git a/services/audioflinger/IAfPatchPanel.h b/services/audioflinger/IAfPatchPanel.h
new file mode 100644
index 0000000..20e092d
--- /dev/null
+++ b/services/audioflinger/IAfPatchPanel.h
@@ -0,0 +1,293 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+// The following includes are required because we have class definitions below
+// for EndPoint and Patch, which precludes using a forward declaration only.
+#include "IAfThread.h"  // IAfThreadBase IAfMmapThread IAfPlaybackThread IAfRecordThread
+#include "IAfTrack.h"   // IAfPatchRecord IAfPatchTrack
+
+#include <datapath/AudioHwDevice.h>
+#include <media/DeviceDescriptorBase.h>
+#include <utils/Log.h>      // ALOG used in this file
+#include <utils/RefBase.h>  // avoid transitive dependency
+#include <utils/Thread.h>
+
+namespace android {
+
+class IAfPatchPanel;
+class PatchCommandThread;
+
+class SoftwarePatch {
+public:
+    SoftwarePatch(
+            const sp<const IAfPatchPanel>& patchPanel,
+            audio_patch_handle_t patchHandle,
+            audio_io_handle_t playbackThreadHandle,
+            audio_io_handle_t recordThreadHandle)
+        : mPatchPanel(patchPanel),
+          mPatchHandle(patchHandle),
+          mPlaybackThreadHandle(playbackThreadHandle),
+          mRecordThreadHandle(recordThreadHandle) {}
+    SoftwarePatch(const SoftwarePatch&) = default;
+
+    // Must be called under AudioFlinger::mLock
+    status_t getLatencyMs_l(double* latencyMs) const;
+    audio_patch_handle_t getPatchHandle() const { return mPatchHandle; };
+    audio_io_handle_t getPlaybackThreadHandle() const { return mPlaybackThreadHandle; };
+    audio_io_handle_t getRecordThreadHandle() const { return mRecordThreadHandle; };
+
+private:
+    const sp<const IAfPatchPanel> mPatchPanel;
+    const audio_patch_handle_t mPatchHandle;
+    const audio_io_handle_t mPlaybackThreadHandle;
+    const audio_io_handle_t mRecordThreadHandle;
+};
+
+class IAfPatchPanelCallback : public virtual RefBase {
+public:
+    virtual void closeThreadInternal_l(const sp<IAfPlaybackThread>& thread) = 0;
+    virtual void closeThreadInternal_l(const sp<IAfRecordThread>& thread) = 0;
+    virtual IAfPlaybackThread* primaryPlaybackThread_l() const = 0;
+    virtual IAfPlaybackThread* checkPlaybackThread_l(audio_io_handle_t output) const = 0;
+    virtual IAfRecordThread* checkRecordThread_l(audio_io_handle_t input) const = 0;
+    virtual IAfMmapThread* checkMmapThread_l(audio_io_handle_t io) const = 0;
+    virtual sp<IAfThreadBase> openInput_l(audio_module_handle_t module,
+            audio_io_handle_t* input,
+            audio_config_t* config,
+            audio_devices_t device,
+            const char* address,
+            audio_source_t source,
+            audio_input_flags_t flags,
+            audio_devices_t outputDevice,
+            const String8& outputDeviceAddress) = 0;
+    virtual sp<IAfThreadBase> openOutput_l(audio_module_handle_t module,
+            audio_io_handle_t* output,
+            audio_config_t* halConfig,
+            audio_config_base_t* mixerConfig,
+            audio_devices_t deviceType,
+            const String8& address,
+            audio_output_flags_t flags) = 0;
+    virtual void lock() const = 0;
+    virtual void unlock() const = 0;
+    virtual const DefaultKeyedVector<audio_module_handle_t, AudioHwDevice*>&
+            getAudioHwDevs_l() const = 0;
+    virtual audio_unique_id_t nextUniqueId(audio_unique_id_use_t use) = 0;
+    virtual const sp<PatchCommandThread>& getPatchCommandThread() = 0;
+    virtual void updateDownStreamPatches_l(
+            const struct audio_patch* patch, const std::set<audio_io_handle_t>& streams) = 0;
+    virtual void updateOutDevicesForRecordThreads_l(const DeviceDescriptorBaseVector& devices) = 0;
+};
+
+class IAfPatchPanel : public virtual RefBase {
+public:
+    static sp<IAfPatchPanel> create(const sp<IAfPatchPanelCallback>& afPatchPanelCallback);
+
+    // Extraction of inner Endpoint and Patch classes would require interfaces
+    // (in the Endpoint case a templated interface) but that seems
+    // excessive for now.  We keep them as inner classes until extraction
+    // is needed.
+    template <typename ThreadType, typename TrackType>
+    class Endpoint final {
+    public:
+        Endpoint() = default;
+        Endpoint(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);
+            return *this;
+        }
+        ~Endpoint() {
+            ALOGE_IF(
+                    mHandle != AUDIO_PATCH_HANDLE_NONE,
+                    "A non empty Patch Endpoint leaked, handle %d", mHandle);
+        }
+
+        status_t checkTrack(TrackType* trackOrNull) const {
+            if (trackOrNull == nullptr) return NO_MEMORY;
+            return trackOrNull->initCheck();
+        }
+        audio_patch_handle_t handle() const { return mHandle; }
+        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; }
+
+        void closeConnections(const sp<IAfPatchPanel>& panel) {
+            if (mHandle != AUDIO_PATCH_HANDLE_NONE) {
+                panel->releaseAudioPatch(mHandle);
+                mHandle = AUDIO_PATCH_HANDLE_NONE;
+            }
+            if (mThread != nullptr) {
+                if (mTrack != nullptr) {
+                    mThread->deletePatchTrack(mTrack);
+                }
+                if (mCloseThread) {
+                    panel->closeThreadInternal_l(mThread);
+                }
+            }
+        }
+        audio_patch_handle_t* handlePtr() { return &mHandle; }
+        void setThread(const sp<ThreadType>& thread, bool closeThread = true) {
+            mThread = thread;
+            mCloseThread = closeThread;
+        }
+        template <typename T>
+        void setTrackAndPeer(const sp<TrackType>& track, const sp<T>& peer, bool holdReference) {
+            mTrack = track;
+            mThread->addPatchTrack(mTrack);
+            mTrack->setPeerProxy(peer, holdReference);
+            mClearPeerProxy = holdReference;
+        }
+        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);
+        }
+
+        friend void swap(Endpoint& a, Endpoint& b) noexcept { a.swap(b); }
+
+    private:
+        sp<ThreadType> mThread;
+        bool mCloseThread = true;
+        bool mClearPeerProxy = true;
+        audio_patch_handle_t mHandle = AUDIO_PATCH_HANDLE_NONE;
+        sp<TrackType> mTrack;
+    };
+
+    class Patch final {
+    public:
+        Patch(const struct audio_patch& patch, bool endpointPatch)
+            : mAudioPatch(patch), mIsEndpointPatch(endpointPatch) {}
+        Patch() = default;
+        ~Patch();
+        Patch(const Patch& other) noexcept {
+            mAudioPatch = other.mAudioPatch;
+            mHalHandle = other.mHalHandle;
+            mPlayback = other.mPlayback;
+            mRecord = other.mRecord;
+            mThread = other.mThread;
+            mIsEndpointPatch = other.mIsEndpointPatch;
+        }
+        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);
+            swap(mIsEndpointPatch, other.mIsEndpointPatch);
+        }
+
+        friend void swap(Patch& a, Patch& b) noexcept { a.swap(b); }
+
+        status_t createConnections(const sp<IAfPatchPanel>& panel);
+        void clearConnections(const sp<IAfPatchPanel>& panel);
+        bool isSoftware() const {
+            return mRecord.handle() != AUDIO_PATCH_HANDLE_NONE ||
+                   mPlayback.handle() != AUDIO_PATCH_HANDLE_NONE;
+        }
+
+        void setThread(const sp<IAfThreadBase>& thread) { mThread = thread; }
+        wp<IAfThreadBase> thread() const { return mThread; }
+
+        // returns the latency of the patch (from record to playback).
+        status_t getLatencyMs(double* latencyMs) const;
+
+        String8 dump(audio_patch_handle_t myHandle) const;
+
+        // Note that audio_patch::id is only unique within a HAL module
+        struct audio_patch mAudioPatch;
+        // handle for audio HAL patch handle present only when the audio HAL version is >= 3.0
+        audio_patch_handle_t mHalHandle = AUDIO_PATCH_HANDLE_NONE;
+        // below members are used by a software audio patch connecting a source device from a
+        // given audio HW module to a sink device on an other audio HW module.
+        // the objects are created by createConnections() and released by clearConnections()
+        // playback thread is created if no existing playback thread can be used
+        // connects playback thread output to sink device
+        Endpoint<IAfPlaybackThread, IAfPatchTrack> mPlayback;
+        // connects source device to record thread input
+        Endpoint<IAfRecordThread, IAfPatchRecord> mRecord;
+
+        wp<IAfThreadBase> mThread;
+        bool mIsEndpointPatch;
+    };
+
+    /* List connected audio ports and their attributes */
+    virtual status_t listAudioPorts(unsigned int* num_ports, struct audio_port* ports) = 0;
+
+    /* Get supported attributes for a given audio port */
+    virtual status_t getAudioPort(struct audio_port_v7* port) = 0;
+
+    /* Create a patch between several source and sink ports */
+    virtual status_t createAudioPatch(
+            const struct audio_patch* patch,
+            audio_patch_handle_t* handle,
+            bool endpointPatch = false) = 0;
+
+    /* Release a patch */
+    virtual status_t releaseAudioPatch(audio_patch_handle_t handle) = 0;
+
+    /* List connected audio devices and they attributes */
+    virtual status_t listAudioPatches(unsigned int* num_patches, struct audio_patch* patches) = 0;
+
+    // Retrieves all currently estrablished software patches for a stream
+    // opened on an intermediate module.
+    virtual status_t getDownstreamSoftwarePatches(
+            audio_io_handle_t stream, std::vector<SoftwarePatch>* patches) const = 0;
+
+    // Notifies patch panel about all opened and closed streams.
+    virtual void notifyStreamOpened(
+            AudioHwDevice* audioHwDevice, audio_io_handle_t stream, struct audio_patch* patch) = 0;
+
+    virtual void notifyStreamClosed(audio_io_handle_t stream) = 0;
+
+    virtual void dump(int fd) const = 0;
+
+    // Must be called under AudioFlinger::mLock
+
+    virtual const std::map<audio_patch_handle_t, Patch>& patches_l() const = 0;
+
+    virtual status_t getLatencyMs_l(audio_patch_handle_t patchHandle, double* latencyMs) const = 0;
+
+    virtual void closeThreadInternal_l(const sp<IAfThreadBase>& thread) const = 0;
+};
+
+}  // namespace android
diff --git a/services/audioflinger/IAfThread.h b/services/audioflinger/IAfThread.h
new file mode 100644
index 0000000..be51d51
--- /dev/null
+++ b/services/audioflinger/IAfThread.h
@@ -0,0 +1,602 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <android/media/IAudioTrackCallback.h>
+#include <android/media/IEffectClient.h>
+#include <audiomanager/IAudioManager.h>
+#include <audio_utils/MelProcessor.h>
+#include <binder/MemoryDealer.h>
+#include <datapath/AudioStreamIn.h>
+#include <datapath/AudioStreamOut.h>
+#include <datapath/VolumeInterface.h>
+#include <fastpath/FastMixerDumpState.h>
+#include <media/DeviceDescriptorBase.h>
+#include <media/MmapStreamInterface.h>
+#include <media/audiohal/StreamHalInterface.h>
+#include <media/nblog/NBLog.h>
+#include <timing/SyncEvent.h>
+#include <utils/Mutex.h>
+#include <utils/RefBase.h>
+#include <vibrator/ExternalVibration.h>
+
+#include <optional>
+
+namespace android {
+
+class IAfDirectOutputThread;
+class IAfDuplicatingThread;
+class IAfMmapCaptureThread;
+class IAfMmapPlaybackThread;
+class IAfPlaybackThread;
+class IAfRecordThread;
+
+class IAfEffectChain;
+class IAfEffectHandle;
+class IAfEffectModule;
+class IAfPatchPanel;
+class IAfPatchRecord;
+class IAfPatchTrack;
+class IAfRecordTrack;
+class IAfTrack;
+class IAfTrackBase;
+class Client;
+class MelReporter;
+
+// Used internally for Threads.cpp and AudioFlinger.cpp
+struct stream_type_t {
+    float volume = 1.f;
+    bool mute = false;
+};
+
+// Note this is exposed through IAfThreadBase::afThreadCallback()
+// and hence may be used by the Effect / Track framework.
+class IAfThreadCallback : public virtual RefBase {
+public:
+    virtual Mutex& mutex() const = 0;
+    virtual bool isNonOffloadableGlobalEffectEnabled_l() const = 0;  // Tracks
+    virtual audio_unique_id_t nextUniqueId(audio_unique_id_use_t use) = 0;
+    virtual bool btNrecIsOff() const = 0;
+    virtual float masterVolume_l() const = 0;
+    virtual bool masterMute_l() const = 0;
+    virtual float getMasterBalance_l() const = 0;
+    virtual bool streamMute_l(audio_stream_type_t stream) const = 0;
+    virtual audio_mode_t getMode() const = 0;
+    virtual bool isLowRamDevice() const = 0;
+    virtual bool isAudioPolicyReady() const = 0;  // Effects
+    virtual uint32_t getScreenState() const = 0;
+    virtual std::optional<media::AudioVibratorInfo> getDefaultVibratorInfo_l() const = 0;
+    virtual const sp<IAfPatchPanel>& getPatchPanel() const = 0;
+    virtual const sp<MelReporter>& getMelReporter() const = 0;
+    virtual const sp<EffectsFactoryHalInterface>& getEffectsFactoryHal() const = 0;
+    virtual sp<IAudioManager> getOrCreateAudioManager() = 0;  // Tracks
+
+    virtual bool updateOrphanEffectChains(const sp<IAfEffectModule>& effect) = 0;
+    virtual status_t moveEffectChain_l(audio_session_t sessionId,
+            IAfPlaybackThread* srcThread, IAfPlaybackThread* dstThread) = 0;
+
+    virtual void requestLogMerge() = 0;
+    virtual sp<NBLog::Writer> newWriter_l(size_t size, const char *name) = 0;
+    virtual void unregisterWriter(const sp<NBLog::Writer>& writer) = 0;
+
+    virtual sp<audioflinger::SyncEvent> createSyncEvent(AudioSystem::sync_event_t type,
+            audio_session_t triggerSession,
+            audio_session_t listenerSession,
+            const audioflinger::SyncEventCallback& callBack,
+            const wp<IAfTrackBase>& cookie) = 0;
+
+    virtual void ioConfigChanged(audio_io_config_event_t event,
+            const sp<AudioIoDescriptor>& ioDesc,
+            pid_t pid = 0) = 0;
+    virtual void onNonOffloadableGlobalEffectEnable() = 0;
+    virtual void onSupportedLatencyModesChanged(
+            audio_io_handle_t output, const std::vector<audio_latency_mode_t>& modes) = 0;
+};
+
+class IAfThreadBase : public virtual RefBase {
+public:
+    enum type_t {
+        MIXER,          // Thread class is MixerThread
+        DIRECT,         // Thread class is DirectOutputThread
+        DUPLICATING,    // Thread class is DuplicatingThread
+        RECORD,         // Thread class is RecordThread
+        OFFLOAD,        // Thread class is OffloadThread
+        MMAP_PLAYBACK,  // Thread class for MMAP playback stream
+        MMAP_CAPTURE,   // Thread class for MMAP capture stream
+        SPATIALIZER,    //
+        BIT_PERFECT,    // Thread class for BitPerfectThread
+        // When adding a value, also update IAfThreadBase::threadTypeToString()
+    };
+
+    static const char* threadTypeToString(type_t type);
+    static std::string formatToString(audio_format_t format);  // compliant for MediaMetrics
+    static bool isValidPcmSinkChannelMask(audio_channel_mask_t channelMask);
+    static bool isValidPcmSinkFormat(audio_format_t format);
+
+    virtual status_t readyToRun() = 0;
+    virtual void clearPowerManager() = 0;
+    virtual status_t initCheck() const = 0;
+    virtual type_t type() const = 0;
+    virtual bool isDuplicating() const = 0;
+    virtual audio_io_handle_t id() const = 0;
+    virtual uint32_t sampleRate() const = 0;
+    virtual audio_channel_mask_t channelMask() const = 0;
+    virtual audio_channel_mask_t mixerChannelMask() const = 0;
+    virtual audio_format_t format() const = 0;
+    virtual uint32_t channelCount() const = 0;
+
+    // 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 audio_channel_mask_t hapticChannelMask() const = 0;
+    virtual uint32_t hapticChannelCount() const = 0;
+    virtual uint32_t latency_l() const = 0;
+    virtual void setVolumeForOutput_l(float left, float right) const = 0;
+
+    // Return's the HAL's frame count i.e. fast mixer buffer size.
+    virtual size_t frameCountHAL() const = 0;
+    virtual size_t frameSize() const = 0;
+    // Should be "virtual status_t requestExitAndWait()" and override same
+    // method in Thread, but Thread::requestExitAndWait() is not yet virtual.
+    virtual void exit() = 0;
+    virtual bool checkForNewParameter_l(const String8& keyValuePair, status_t& status) = 0;
+    virtual status_t setParameters(const String8& keyValuePairs) = 0;
+    virtual String8 getParameters(const String8& keys) = 0;
+    virtual void ioConfigChanged(
+            audio_io_config_event_t event, pid_t pid = 0,
+            audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE) = 0;
+
+    // sendConfigEvent_l() must be called with ThreadBase::mLock held
+    // Can temporarily release the lock if waiting for a reply from
+    // processConfigEvents_l().
+    // status_t sendConfigEvent_l(sp<ConfigEvent>& event);
+    virtual void sendIoConfigEvent(
+            audio_io_config_event_t event, pid_t pid = 0,
+            audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE) = 0;
+    virtual void sendIoConfigEvent_l(
+            audio_io_config_event_t event, pid_t pid = 0,
+            audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE) = 0;
+    virtual void sendPrioConfigEvent(pid_t pid, pid_t tid, int32_t prio, bool forApp) = 0;
+    virtual void sendPrioConfigEvent_l(pid_t pid, pid_t tid, int32_t prio, bool forApp) = 0;
+    virtual status_t sendSetParameterConfigEvent_l(const String8& keyValuePair) = 0;
+    virtual status_t sendCreateAudioPatchConfigEvent(
+            const struct audio_patch* patch, audio_patch_handle_t* handle) = 0;
+    virtual status_t sendReleaseAudioPatchConfigEvent(audio_patch_handle_t handle) = 0;
+    virtual status_t sendUpdateOutDeviceConfigEvent(
+            const DeviceDescriptorBaseVector& outDevices) = 0;
+    virtual void sendResizeBufferConfigEvent_l(int32_t maxSharedAudioHistoryMs) = 0;
+    virtual void sendCheckOutputStageEffectsEvent() = 0;
+    virtual void sendCheckOutputStageEffectsEvent_l() = 0;
+    virtual void sendHalLatencyModesChangedEvent_l() = 0;
+
+    virtual void processConfigEvents_l() = 0;
+    virtual void setCheckOutputStageEffects() = 0;
+    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) = 0;
+    virtual void toAudioPortConfig(struct audio_port_config* config) = 0;
+    virtual void resizeInputBuffer_l(int32_t maxSharedAudioHistoryMs) = 0;
+
+    // see note at declaration of mStandby, mOutDevice and mInDevice
+    virtual bool inStandby() const = 0;
+    virtual const DeviceTypeSet outDeviceTypes() const = 0;
+    virtual audio_devices_t inDeviceType() const = 0;
+    virtual DeviceTypeSet getDeviceTypes() const = 0;
+    virtual const AudioDeviceTypeAddrVector& outDeviceTypeAddrs() const = 0;
+    virtual const AudioDeviceTypeAddr& inDeviceTypeAddr() const = 0;
+    virtual bool isOutput() const = 0;
+    virtual bool isOffloadOrMmap() const = 0;
+    virtual sp<StreamHalInterface> stream() const = 0;
+    virtual sp<IAfEffectHandle> createEffect_l(
+            const sp<Client>& client,
+            const sp<media::IEffectClient>& effectClient,
+            int32_t priority,
+            audio_session_t sessionId,
+            effect_descriptor_t* desc,
+            int* enabled,
+            status_t* status /*non-NULL*/,
+            bool pinned,
+            bool probe,
+            bool notifyFramesProcessed) = 0;
+
+    // return values for hasAudioSession (bit field)
+    enum effect_state {
+        EFFECT_SESSION = 0x1,       // the audio session corresponds to at least one
+                                    // effect
+        TRACK_SESSION = 0x2,        // the audio session corresponds to at least one
+                                    // track
+        FAST_SESSION = 0x4,         // the audio session corresponds to at least one
+                                    // fast track
+        SPATIALIZED_SESSION = 0x8,  // the audio session corresponds to at least one
+                                    // spatialized track
+        BIT_PERFECT_SESSION = 0x10  // the audio session corresponds to at least one
+                                    // bit-perfect track
+    };
+
+    // get effect chain corresponding to session Id.
+    virtual sp<IAfEffectChain> getEffectChain(audio_session_t sessionId) const = 0;
+    // same as getEffectChain() but must be called with ThreadBase mutex locked
+    virtual sp<IAfEffectChain> getEffectChain_l(audio_session_t sessionId) const = 0;
+    virtual std::vector<int> getEffectIds_l(audio_session_t sessionId) const = 0;
+    // add an effect chain to the chain list (mEffectChains)
+    virtual status_t addEffectChain_l(const sp<IAfEffectChain>& chain) = 0;
+    // remove an effect chain from the chain list (mEffectChains)
+    virtual size_t removeEffectChain_l(const sp<IAfEffectChain>& chain) = 0;
+    // lock all effect chains Mutexes. Must be called before releasing the
+    // ThreadBase mutex before processing the mixer and effects. This guarantees the
+    // integrity of the chains during the process.
+    // Also sets the parameter 'effectChains' to current value of mEffectChains.
+    virtual void lockEffectChains_l(Vector<sp<IAfEffectChain>>& effectChains) = 0;
+    // unlock effect chains after process
+    virtual void unlockEffectChains(const Vector<sp<IAfEffectChain>>& effectChains) = 0;
+    // get a copy of mEffectChains vector
+    virtual Vector<sp<IAfEffectChain>> getEffectChains_l() const = 0;
+    // set audio mode to all effect chains
+    virtual void setMode(audio_mode_t mode) = 0;
+    // get effect module with corresponding ID on specified audio session
+    virtual sp<IAfEffectModule> getEffect(audio_session_t sessionId, int effectId) const = 0;
+    virtual sp<IAfEffectModule> getEffect_l(audio_session_t sessionId, int effectId) const = 0;
+    // add and effect module. Also creates the effect chain is none exists for
+    // the effects audio session. Only called in a context of moving an effect
+    // from one thread to another
+    virtual status_t addEffect_l(const sp<IAfEffectModule>& effect) = 0;
+    // remove and effect module. Also removes the effect chain is this was the last
+    // effect
+    virtual void removeEffect_l(const sp<IAfEffectModule>& effect, bool release = false) = 0;
+    // disconnect an effect handle from module and destroy module if last handle
+    virtual void disconnectEffectHandle(IAfEffectHandle* handle, bool unpinIfLast) = 0;
+    // detach all tracks connected to an auxiliary effect
+    virtual void detachAuxEffect_l(int effectId) = 0;
+    // returns a combination of:
+    // - EFFECT_SESSION if effects on this audio session exist in one chain
+    // - TRACK_SESSION if tracks on this audio session exist
+    // - FAST_SESSION if fast tracks on this audio session exist
+    // - SPATIALIZED_SESSION if spatialized tracks on this audio session exist
+    virtual uint32_t hasAudioSession_l(audio_session_t sessionId) const = 0;
+    virtual uint32_t hasAudioSession(audio_session_t sessionId) const = 0;
+
+    // the value returned by default implementation is not important as the
+    // strategy is only meaningful for PlaybackThread which implements this method
+    virtual product_strategy_t getStrategyForSession_l(audio_session_t sessionId) const = 0;
+
+    // check if some effects must be suspended/restored when an effect is enabled
+    // or disabled
+    virtual void checkSuspendOnEffectEnabled(
+            bool enabled, audio_session_t sessionId, bool threadLocked) = 0;
+
+    virtual status_t setSyncEvent(const sp<audioflinger::SyncEvent>& event) = 0;
+    virtual bool isValidSyncEvent(const sp<audioflinger::SyncEvent>& event) const = 0;
+
+    // Return a reference to a per-thread heap which can be used to allocate IMemory
+    // objects that will be read-only to client processes, read/write to mediaserver,
+    // and shared by all client processes of the thread.
+    // The heap is per-thread rather than common across all threads, because
+    // clients can't be trusted not to modify the offset of the IMemory they receive.
+    // If a thread does not have such a heap, this method returns 0.
+    virtual sp<MemoryDealer> readOnlyHeap() const = 0;
+
+    virtual sp<IMemory> pipeMemory() const = 0;
+
+    virtual void systemReady() = 0;
+
+    // checkEffectCompatibility_l() must be called with ThreadBase::mLock held
+    virtual status_t checkEffectCompatibility_l(
+            const effect_descriptor_t* desc, audio_session_t sessionId) = 0;
+
+    virtual void broadcast_l() = 0;
+
+    virtual bool isTimestampCorrectionEnabled() const = 0;
+
+    virtual bool isMsdDevice() const = 0;
+
+    virtual void dump(int fd, const Vector<String16>& args) = 0;
+
+    // deliver stats to mediametrics.
+    virtual void sendStatistics(bool force) = 0;
+
+    virtual Mutex& mutex() const = 0;
+
+    virtual void onEffectEnable(const sp<IAfEffectModule>& effect) = 0;
+    virtual void onEffectDisable() = 0;
+
+    // invalidateTracksForAudioSession_l must be called with holding mLock.
+    virtual void invalidateTracksForAudioSession_l(audio_session_t sessionId) const = 0;
+    // Invalidate all the tracks with the given audio session.
+    virtual void invalidateTracksForAudioSession(audio_session_t sessionId) const = 0;
+
+    virtual bool isStreamInitialized() const = 0;
+    virtual void startMelComputation_l(const sp<audio_utils::MelProcessor>& processor) = 0;
+    virtual void stopMelComputation_l() = 0;
+
+    virtual product_strategy_t getStrategyForStream(audio_stream_type_t stream) const = 0;
+
+    virtual void setEffectSuspended_l(
+            const effect_uuid_t* type, bool suspend, audio_session_t sessionId) = 0;
+
+    // Dynamic cast to derived interface
+    virtual sp<IAfDirectOutputThread> asIAfDirectOutputThread() { return nullptr; }
+    virtual sp<IAfDuplicatingThread> asIAfDuplicatingThread() { return nullptr; }
+    virtual sp<IAfPlaybackThread> asIAfPlaybackThread() { return nullptr; }
+    virtual sp<IAfRecordThread> asIAfRecordThread() { return nullptr; }
+    virtual IAfThreadCallback* afThreadCallback() const = 0;
+};
+
+class IAfPlaybackThread : public virtual IAfThreadBase, public virtual VolumeInterface {
+public:
+    static sp<IAfPlaybackThread> createBitPerfectThread(
+            const sp<IAfThreadCallback>& afThreadCallback, AudioStreamOut* output,
+            audio_io_handle_t id, bool systemReady);
+
+    static sp<IAfPlaybackThread> createDirectOutputThread(
+            const sp<IAfThreadCallback>& afThreadCallback, AudioStreamOut* output,
+            audio_io_handle_t id, bool systemReady, const audio_offload_info_t& offloadInfo);
+
+    static sp<IAfPlaybackThread> createMixerThread(
+            const sp<IAfThreadCallback>& afThreadCallback, AudioStreamOut* output,
+            audio_io_handle_t id, bool systemReady, type_t type = MIXER,
+            audio_config_base_t* mixerConfig = nullptr);
+
+    static sp<IAfPlaybackThread> createOffloadThread(
+            const sp<IAfThreadCallback>& afThreadCallback, AudioStreamOut* output,
+            audio_io_handle_t id, bool systemReady, const audio_offload_info_t& offloadInfo);
+
+    static sp<IAfPlaybackThread> createSpatializerThread(
+            const sp<IAfThreadCallback>& afThreadCallback, AudioStreamOut* output,
+            audio_io_handle_t id, bool systemReady, audio_config_base_t* mixerConfig);
+
+    static constexpr int8_t kMaxTrackStopRetriesOffload = 2;
+
+    enum mixer_state {
+        MIXER_IDLE,            // no active tracks
+        MIXER_TRACKS_ENABLED,  // at least one active track, but no track has any data ready
+        MIXER_TRACKS_READY,    // at least one active track, and at least one track has data
+        MIXER_DRAIN_TRACK,     // drain currently playing track
+        MIXER_DRAIN_ALL,       // fully drain the hardware
+        // standby mode does not have an enum value
+        // suspend by audio policy manager is orthogonal to mixer state
+    };
+
+    // return estimated latency in milliseconds, as reported by HAL
+    virtual uint32_t latency() const = 0;  // should be in IAfThreadBase?
+
+    virtual uint32_t& fastTrackAvailMask_l() = 0;
+
+    virtual sp<IAfTrack> createTrack_l(
+            const sp<Client>& client,
+            audio_stream_type_t streamType,
+            const audio_attributes_t& attr,
+            uint32_t* sampleRate,
+            audio_format_t format,
+            audio_channel_mask_t channelMask,
+            size_t* pFrameCount,
+            size_t* pNotificationFrameCount,
+            uint32_t notificationsPerBuffer,
+            float speed,
+            const sp<IMemory>& sharedBuffer,
+            audio_session_t sessionId,
+            audio_output_flags_t* flags,
+            pid_t creatorPid,
+            const AttributionSourceState& attributionSource,
+            pid_t tid,
+            status_t* status /*non-NULL*/,
+            audio_port_handle_t portId,
+            const sp<media::IAudioTrackCallback>& callback,
+            bool isSpatialized,
+            bool isBitPerfect) = 0;
+
+    virtual status_t addTrack_l(const sp<IAfTrack>& track) = 0;
+    virtual bool destroyTrack_l(const sp<IAfTrack>& track) = 0;
+    virtual bool isTrackActive(const sp<IAfTrack>& track) const = 0;
+    virtual void addOutputTrack_l(const sp<IAfTrack>& track) = 0;
+
+    virtual AudioStreamOut* getOutput_l() const = 0;
+    virtual AudioStreamOut* getOutput() const = 0;
+    virtual AudioStreamOut* clearOutput() = 0;
+
+    // a very large number of suspend() will eventually wraparound, but unlikely
+    virtual void suspend() = 0;
+    virtual void restore() = 0;
+    virtual bool isSuspended() const = 0;
+    virtual status_t getRenderPosition(uint32_t* halFrames, uint32_t* dspFrames) const = 0;
+    // Consider also removing and passing an explicit mMainBuffer initialization
+    // parameter to AF::IAfTrack::Track().
+    virtual float* sinkBuffer() const = 0;
+
+    virtual status_t attachAuxEffect(const sp<IAfTrack>& track, int EffectId) = 0;
+    virtual status_t attachAuxEffect_l(const sp<IAfTrack>& track, int EffectId) = 0;
+
+    // called with AudioFlinger lock held
+    virtual bool invalidateTracks_l(audio_stream_type_t streamType) = 0;
+    virtual bool invalidateTracks_l(std::set<audio_port_handle_t>& portIds) = 0;
+    virtual void invalidateTracks(audio_stream_type_t streamType) = 0;
+    // Invalidate tracks by a set of port ids. The port id will be removed from
+    // the given set if the corresponding track is found and invalidated.
+    virtual void invalidateTracks(std::set<audio_port_handle_t>& portIds) = 0;
+
+    virtual status_t getTimestamp_l(AudioTimestamp& timestamp) = 0;
+    virtual void addPatchTrack(const sp<IAfPatchTrack>& track) = 0;
+    virtual void deletePatchTrack(const sp<IAfPatchTrack>& track) = 0;
+
+    // Return the asynchronous signal wait time.
+    virtual int64_t computeWaitTimeNs_l() const = 0;
+    // returns true if the track is allowed to be added to the thread.
+    virtual bool isTrackAllowed_l(
+            audio_channel_mask_t channelMask, audio_format_t format, audio_session_t sessionId,
+            uid_t uid) const = 0;
+
+    virtual bool supportsHapticPlayback() const = 0;
+
+    virtual void setDownStreamPatch(const struct audio_patch* patch) = 0;
+
+    virtual IAfTrack* getTrackById_l(audio_port_handle_t trackId) = 0;
+
+    virtual bool hasMixer() const = 0;
+
+    virtual status_t setRequestedLatencyMode(audio_latency_mode_t mode) = 0;
+
+    virtual status_t getSupportedLatencyModes(std::vector<audio_latency_mode_t>* modes) = 0;
+
+    virtual status_t setBluetoothVariableLatencyEnabled(bool enabled) = 0;
+
+    virtual void setStandby() = 0;
+    virtual void setStandby_l() = 0;
+    virtual bool waitForHalStart() = 0;
+
+    virtual bool hasFastMixer() const = 0;
+    virtual FastTrackUnderruns getFastTrackUnderruns(size_t fastIndex) const = 0;
+    virtual const std::atomic<int64_t>& framesWritten() const = 0;
+
+    virtual bool usesHwAvSync() const = 0;
+};
+
+class IAfDirectOutputThread : public virtual IAfPlaybackThread {
+public:
+    virtual status_t selectPresentation(int presentationId, int programId) = 0;
+};
+
+class IAfDuplicatingThread : public virtual IAfPlaybackThread {
+public:
+    static sp<IAfDuplicatingThread> create(
+            const sp<IAfThreadCallback>& afThreadCallback, IAfPlaybackThread* mainThread,
+            audio_io_handle_t id, bool systemReady);
+
+    virtual void addOutputTrack(IAfPlaybackThread* thread) = 0;
+    virtual uint32_t waitTimeMs() const = 0;
+    virtual void removeOutputTrack(IAfPlaybackThread* thread) = 0;
+};
+
+class IAfRecordThread : public virtual IAfThreadBase {
+public:
+    static sp<IAfRecordThread> create(
+            const sp<IAfThreadCallback>& afThreadCallback, AudioStreamIn* input,
+            audio_io_handle_t id, bool systemReady);
+
+    virtual sp<IAfRecordTrack> createRecordTrack_l(
+            const sp<Client>& client,
+            const audio_attributes_t& attr,
+            uint32_t* pSampleRate,
+            audio_format_t format,
+            audio_channel_mask_t channelMask,
+            size_t* pFrameCount,
+            audio_session_t sessionId,
+            size_t* pNotificationFrameCount,
+            pid_t creatorPid,
+            const AttributionSourceState& attributionSource,
+            audio_input_flags_t* flags,
+            pid_t tid,
+            status_t* status /*non-NULL*/,
+            audio_port_handle_t portId,
+            int32_t maxSharedAudioHistoryMs) = 0;
+    virtual void destroyTrack_l(const sp<IAfRecordTrack>& track) = 0;
+    virtual void removeTrack_l(const sp<IAfRecordTrack>& track) = 0;
+
+    virtual status_t start(
+            IAfRecordTrack* recordTrack, AudioSystem::sync_event_t event,
+            audio_session_t triggerSession) = 0;
+
+    // ask the thread to stop the specified track, and
+    // return true if the caller should then do it's part of the stopping process
+    virtual bool stop(IAfRecordTrack* recordTrack) = 0;
+
+    virtual AudioStreamIn* getInput() const = 0;
+    virtual AudioStreamIn* clearInput() = 0;
+
+    virtual status_t getActiveMicrophones(
+            std::vector<media::MicrophoneInfoFw>* activeMicrophones) const = 0;
+    virtual status_t setPreferredMicrophoneDirection(audio_microphone_direction_t direction) = 0;
+    virtual status_t setPreferredMicrophoneFieldDimension(float zoom) = 0;
+
+    virtual void addPatchTrack(const sp<IAfPatchRecord>& record) = 0;
+    virtual void deletePatchTrack(const sp<IAfPatchRecord>& record) = 0;
+    virtual bool fastTrackAvailable() const = 0;
+    virtual void setFastTrackAvailable(bool available) = 0;
+
+    virtual void setRecordSilenced(audio_port_handle_t portId, bool silenced) = 0;
+    virtual bool hasFastCapture() const = 0;
+
+    virtual void checkBtNrec() = 0;
+    virtual uint32_t getInputFramesLost() const = 0;
+
+    virtual status_t shareAudioHistory(
+            const std::string& sharedAudioPackageName,
+            audio_session_t sharedSessionId = AUDIO_SESSION_NONE,
+            int64_t sharedAudioStartMs = -1) = 0;
+    virtual void resetAudioHistory_l() = 0;
+};
+
+class IAfMmapThread : public virtual IAfThreadBase {
+public:
+    // createIAudioTrackAdapter() is a static constructor which creates an
+    // MmapStreamInterface AIDL interface adapter from the MmapThread object that
+    // may be passed back to the client.
+    //
+    // Only one AIDL MmapStreamInterface interface adapter should be created per MmapThread.
+    static sp<MmapStreamInterface> createMmapStreamInterfaceAdapter(
+            const sp<IAfMmapThread>& mmapThread);
+
+    virtual void configure(
+            const audio_attributes_t* attr,
+            audio_stream_type_t streamType,
+            audio_session_t sessionId,
+            const sp<MmapStreamCallback>& callback,
+            audio_port_handle_t deviceId,
+            audio_port_handle_t portId) = 0;
+    virtual void disconnect() = 0;
+
+    // MmapStreamInterface handling (see adapter)
+    virtual status_t createMmapBuffer(
+            int32_t minSizeFrames, struct audio_mmap_buffer_info* info) = 0;
+    virtual status_t getMmapPosition(struct audio_mmap_position* position) const = 0;
+    virtual status_t start(
+            const AudioClient& client, const audio_attributes_t* attr,
+            audio_port_handle_t* handle) = 0;
+    virtual status_t stop(audio_port_handle_t handle) = 0;
+    virtual status_t standby() = 0;
+    virtual status_t getExternalPosition(uint64_t* position, int64_t* timeNanos) const = 0;
+    virtual status_t reportData(const void* buffer, size_t frameCount) = 0;
+
+    // TODO(b/291317898)  move to IAfThreadBase?
+    virtual void invalidateTracks(std::set<audio_port_handle_t>& portIds) = 0;
+
+    // Sets the UID records silence - TODO(b/291317898)  move to IAfMmapCaptureThread
+    virtual void setRecordSilenced(audio_port_handle_t portId, bool silenced) = 0;
+
+    virtual sp<IAfMmapPlaybackThread> asIAfMmapPlaybackThread() { return nullptr; }
+    virtual sp<IAfMmapCaptureThread> asIAfMmapCaptureThread() { return nullptr; }
+};
+
+class IAfMmapPlaybackThread : public virtual IAfMmapThread, public virtual VolumeInterface {
+public:
+    static sp<IAfMmapPlaybackThread> create(
+            const sp<IAfThreadCallback>& afThreadCallback, audio_io_handle_t id,
+            AudioHwDevice* hwDev, AudioStreamOut* output, bool systemReady);
+
+    virtual AudioStreamOut* clearOutput() = 0;
+};
+
+class IAfMmapCaptureThread : public virtual IAfMmapThread {
+public:
+    static sp<IAfMmapCaptureThread> create(
+            const sp<IAfThreadCallback>& afThreadCallback, audio_io_handle_t id,
+            AudioHwDevice* hwDev, AudioStreamIn* input, bool systemReady);
+
+    virtual AudioStreamIn* clearInput() = 0;
+};
+
+}  // namespace android
diff --git a/services/audioflinger/IAfTrack.h b/services/audioflinger/IAfTrack.h
new file mode 100644
index 0000000..2302e13
--- /dev/null
+++ b/services/audioflinger/IAfTrack.h
@@ -0,0 +1,607 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <android/media/BnAudioRecord.h>
+#include <android/media/BnAudioTrack.h>
+#include <audiomanager/IAudioManager.h>
+#include <binder/IMemory.h>
+#include <fastpath/FastMixerDumpState.h>
+#include <media/AudioSystem.h>
+#include <media/VolumeShaper.h>
+#include <private/media/AudioTrackShared.h>
+#include <timing/SyncEvent.h>
+#include <timing/SynchronizedRecordState.h>
+#include <utils/RefBase.h>
+#include <vibrator/ExternalVibration.h>
+
+#include <vector>
+
+namespace android {
+
+class Client;
+class ResamplerBufferProvider;
+struct Source;
+
+class IAfDuplicatingThread;
+class IAfPatchRecord;
+class IAfPatchTrack;
+class IAfPlaybackThread;
+class IAfRecordThread;
+class IAfThreadBase;
+
+struct TeePatch {
+    sp<IAfPatchRecord> patchRecord;
+    sp<IAfPatchTrack> patchTrack;
+};
+
+using TeePatches = std::vector<TeePatch>;
+
+// Common interface to all Playback and Record tracks.
+class IAfTrackBase : public virtual RefBase {
+public:
+    enum track_state : int32_t {
+        IDLE,
+        FLUSHED,  // for PlaybackTracks only
+        STOPPED,
+        // next 2 states are currently used for fast tracks
+        // and offloaded tracks only
+        STOPPING_1,  // waiting for first underrun
+        STOPPING_2,  // waiting for presentation complete
+        RESUMING,    // for PlaybackTracks only
+        ACTIVE,
+        PAUSING,
+        PAUSED,
+        STARTING_1,  // for RecordTrack only
+        STARTING_2,  // for RecordTrack only
+    };
+
+    // where to allocate the data buffer
+    enum alloc_type {
+        ALLOC_CBLK,      // allocate immediately after control block
+        ALLOC_READONLY,  // allocate from a separate read-only heap per thread
+        ALLOC_PIPE,      // do not allocate; use the pipe buffer
+        ALLOC_LOCAL,     // allocate a local buffer
+        ALLOC_NONE,      // do not allocate:use the buffer passed to TrackBase constructor
+    };
+
+    enum track_type {
+        TYPE_DEFAULT,
+        TYPE_OUTPUT,
+        TYPE_PATCH,
+    };
+
+    virtual status_t initCheck() const = 0;
+    virtual status_t start(
+            AudioSystem::sync_event_t event = AudioSystem::SYNC_EVENT_NONE,
+            audio_session_t triggerSession = AUDIO_SESSION_NONE) = 0;
+    virtual void stop() = 0;
+    virtual sp<IMemory> getCblk() const = 0;
+    virtual audio_track_cblk_t* cblk() const = 0;
+    virtual audio_session_t sessionId() const = 0;
+    virtual uid_t uid() const = 0;
+    virtual pid_t creatorPid() const = 0;
+    virtual uint32_t sampleRate() const = 0;
+    virtual size_t frameSize() const = 0;
+    virtual audio_port_handle_t portId() const = 0;
+    virtual status_t setSyncEvent(const sp<audioflinger::SyncEvent>& event) = 0;
+    virtual track_state state() const = 0;
+    virtual void setState(track_state state) = 0;
+    virtual sp<IMemory> getBuffers() const = 0;
+    virtual void* buffer() const = 0;
+    virtual size_t bufferSize() const = 0;
+    virtual bool isFastTrack() const = 0;
+    virtual bool isDirect() const = 0;
+    virtual bool isOutputTrack() const = 0;
+    virtual bool isPatchTrack() const = 0;
+    virtual bool isExternalTrack() const = 0;
+
+    virtual void invalidate() = 0;
+    virtual bool isInvalid() const = 0;
+
+    virtual void terminate() = 0;
+    virtual bool isTerminated() const = 0;
+
+    virtual audio_attributes_t attributes() const = 0;
+    virtual bool isSpatialized() const = 0;
+    virtual bool isBitPerfect() const = 0;
+
+    // not currently implemented in TrackBase, but overridden.
+    virtual void destroy() {};  // MmapTrack doesn't implement.
+    virtual void appendDumpHeader(String8& result) const = 0;
+    virtual void appendDump(String8& result, bool active) const = 0;
+
+    // Dup with AudioBufferProvider interface
+    virtual status_t getNextBuffer(AudioBufferProvider::Buffer* buffer) = 0;
+    virtual void releaseBuffer(AudioBufferProvider::Buffer* buffer) = 0;
+
+    // Added for RecordTrack and OutputTrack
+    virtual wp<IAfThreadBase> thread() const = 0;
+    virtual const sp<ServerProxy>& serverProxy() const = 0;
+
+    // TEE_SINK
+    virtual void dumpTee(int fd __unused, const std::string& reason __unused) const {};
+
+    /** returns the buffer contents size converted to time in milliseconds
+     * for PCM Playback or Record streaming tracks. The return value is zero for
+     * PCM static tracks and not defined for non-PCM tracks.
+     *
+     * This may be called without the thread lock.
+     */
+    virtual double bufferLatencyMs() const = 0;
+
+    /** returns whether the track supports server latency computation.
+     * This is set in the constructor and constant throughout the track lifetime.
+     */
+    virtual bool isServerLatencySupported() const = 0;
+
+    /** computes the server latency for PCM Playback or Record track
+     * to the device sink/source.  This is the time for the next frame in the track buffer
+     * written or read from the server thread to the device source or sink.
+     *
+     * This may be called without the thread lock, but latencyMs and fromTrack
+     * may be not be synchronized. For example PatchPanel may not obtain the
+     * thread lock before calling.
+     *
+     * \param latencyMs on success is set to the latency in milliseconds of the
+     *        next frame written/read by the server thread to/from the track buffer
+     *        from the device source/sink.
+     * \param fromTrack on success is set to true if latency was computed directly
+     *        from the track timestamp; otherwise set to false if latency was
+     *        estimated from the server timestamp.
+     *        fromTrack may be nullptr or omitted if not required.
+     *
+     * \returns OK or INVALID_OPERATION on failure.
+     */
+    virtual status_t getServerLatencyMs(double* latencyMs, bool* fromTrack = nullptr) const = 0;
+
+    /** computes the total client latency for PCM Playback or Record tracks
+     * for the next client app access to the device sink/source; i.e. the
+     * server latency plus the buffer latency.
+     *
+     * This may be called without the thread lock, but latencyMs and fromTrack
+     * may be not be synchronized. For example PatchPanel may not obtain the
+     * thread lock before calling.
+     *
+     * \param latencyMs on success is set to the latency in milliseconds of the
+     *        next frame written/read by the client app to/from the track buffer
+     *        from the device sink/source.
+     * \param fromTrack on success is set to true if latency was computed directly
+     *        from the track timestamp; otherwise set to false if latency was
+     *        estimated from the server timestamp.
+     *        fromTrack may be nullptr or omitted if not required.
+     *
+     * \returns OK or INVALID_OPERATION on failure.
+     */
+    virtual status_t getTrackLatencyMs(double* latencyMs, bool* fromTrack = nullptr) const = 0;
+
+    // TODO: Consider making this external.
+    struct FrameTime {
+        int64_t frames;
+        int64_t timeNs;
+    };
+
+    // KernelFrameTime is updated per "mix" period even for non-pcm tracks.
+    virtual void getKernelFrameTime(FrameTime* ft) const = 0;
+
+    virtual audio_format_t format() const = 0;
+    virtual int id() const = 0;
+
+    virtual const char* getTrackStateAsString() const = 0;
+
+    // Called by the PlaybackThread to indicate that the track is becoming active
+    // and a new interval should start with a given device list.
+    virtual void logBeginInterval(const std::string& devices) = 0;
+
+    // Called by the PlaybackThread to indicate the track is no longer active.
+    virtual void logEndInterval() = 0;
+
+    // Called to tally underrun frames in playback.
+    virtual void tallyUnderrunFrames(size_t frames) = 0;
+
+    virtual audio_channel_mask_t channelMask() const = 0;
+
+    /** @return true if the track has changed (metadata or volume) since
+     *          the last time this function was called,
+     *          true if this function was never called since the track creation,
+     *          false otherwise.
+     *  Thread safe.
+     */
+    virtual bool readAndClearHasChanged() = 0;
+
+    /** Set that a metadata has changed and needs to be notified to backend. Thread safe. */
+    virtual void setMetadataHasChanged() = 0;
+
+    /**
+     * Called when a track moves to active state to record its contribution to battery usage.
+     * Track state transitions should eventually be handled within the track class.
+     */
+    virtual void beginBatteryAttribution() = 0;
+
+    /**
+     * Called when a track moves out of the active state to record its contribution
+     * to battery usage.
+     */
+    virtual void endBatteryAttribution() = 0;
+
+    /**
+     * For RecordTrack
+     * TODO(b/291317964) either use this or add asRecordTrack or asTrack etc.
+     */
+    virtual void handleSyncStartEvent(const sp<audioflinger::SyncEvent>& event __unused){};
+
+    // For Thread use, fast tracks and offloaded tracks only
+    // TODO(b/291317964) rearrange to IAfTrack.
+    virtual bool isStopped() const = 0;
+    virtual bool isStopping() const = 0;
+    virtual bool isStopping_1() const = 0;
+    virtual bool isStopping_2() const = 0;
+};
+
+// Common interface for Playback tracks.
+class IAfTrack : public virtual IAfTrackBase {
+public:
+    // FillingStatus is used for suppressing volume ramp at begin of playing
+    enum FillingStatus { FS_INVALID, FS_FILLING, FS_FILLED, FS_ACTIVE };
+
+    // createIAudioTrackAdapter() is a static constructor which creates an
+    // IAudioTrack AIDL interface adapter from the Track object that
+    // may be passed back to the client (if needed).
+    //
+    // Only one AIDL IAudioTrack interface adapter should be created per Track.
+    static sp<media::IAudioTrack> createIAudioTrackAdapter(const sp<IAfTrack>& track);
+
+    static sp<IAfTrack> create(
+            IAfPlaybackThread* thread,
+            const sp<Client>& client,
+            audio_stream_type_t streamType,
+            const audio_attributes_t& attr,
+            uint32_t sampleRate,
+            audio_format_t format,
+            audio_channel_mask_t channelMask,
+            size_t frameCount,
+            void* buffer,
+            size_t bufferSize,
+            const sp<IMemory>& sharedBuffer,
+            audio_session_t sessionId,
+            pid_t creatorPid,
+            const AttributionSourceState& attributionSource,
+            audio_output_flags_t flags,
+            track_type type,
+            audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE,
+            /** default behaviour is to start when there are as many frames
+              * ready as possible (aka. Buffer is full). */
+            size_t frameCountToBeReady = SIZE_MAX,
+            float speed = 1.0f,
+            bool isSpatialized = false,
+            bool isBitPerfect = false);
+
+    virtual void pause() = 0;
+    virtual void flush() = 0;
+    virtual audio_stream_type_t streamType() const = 0;
+    virtual bool isOffloaded() const = 0;
+    virtual bool isOffloadedOrDirect() const = 0;
+    virtual bool isStatic() const = 0;
+    virtual status_t setParameters(const String8& keyValuePairs) = 0;
+    virtual status_t selectPresentation(int presentationId, int programId) = 0;
+    virtual status_t attachAuxEffect(int EffectId) = 0;
+    virtual void setAuxBuffer(int EffectId, int32_t* buffer) = 0;
+    virtual int32_t* auxBuffer() const = 0;
+    virtual void setMainBuffer(float* buffer) = 0;
+    virtual float* mainBuffer() const = 0;
+    virtual int auxEffectId() const = 0;
+    virtual status_t getTimestamp(AudioTimestamp& timestamp) = 0;
+    virtual void signal() = 0;
+    virtual status_t getDualMonoMode(audio_dual_mono_mode_t* mode) const = 0;
+    virtual status_t setDualMonoMode(audio_dual_mono_mode_t mode) = 0;
+    virtual status_t getAudioDescriptionMixLevel(float* leveldB) const = 0;
+    virtual status_t setAudioDescriptionMixLevel(float leveldB) = 0;
+    virtual status_t getPlaybackRateParameters(audio_playback_rate_t* playbackRate) const = 0;
+    virtual status_t setPlaybackRateParameters(const audio_playback_rate_t& playbackRate) = 0;
+
+    // implement FastMixerState::VolumeProvider interface
+    virtual gain_minifloat_packed_t getVolumeLR() const = 0;
+
+    // implement volume handling.
+    virtual media::VolumeShaper::Status applyVolumeShaper(
+            const sp<media::VolumeShaper::Configuration>& configuration,
+            const sp<media::VolumeShaper::Operation>& operation) = 0;
+    virtual sp<media::VolumeShaper::State> getVolumeShaperState(int id) const = 0;
+    virtual sp<media::VolumeHandler> getVolumeHandler() const = 0;
+    /** Set the computed normalized final volume of the track.
+     * !masterMute * masterVolume * streamVolume * averageLRVolume */
+    virtual void setFinalVolume(float volumeLeft, float volumeRight) = 0;
+    virtual float getFinalVolume() const = 0;
+    virtual void getFinalVolume(float* left, float* right) const = 0;
+
+    using SourceMetadatas = std::vector<playback_track_metadata_v7_t>;
+    using MetadataInserter = std::back_insert_iterator<SourceMetadatas>;
+    /** Copy the track metadata in the provided iterator. Thread safe. */
+    virtual void copyMetadataTo(MetadataInserter& backInserter) const = 0;
+
+    /** Return haptic playback of the track is enabled or not, used in mixer. */
+    virtual bool getHapticPlaybackEnabled() const = 0;
+    /** Set haptic playback of the track is enabled or not, should be
+     * set after query or get callback from vibrator service */
+    virtual void setHapticPlaybackEnabled(bool hapticPlaybackEnabled) = 0;
+    /** Return at what intensity to play haptics, used in mixer. */
+    virtual os::HapticScale getHapticIntensity() const = 0;
+    /** Return the maximum amplitude allowed for haptics data, used in mixer. */
+    virtual float getHapticMaxAmplitude() const = 0;
+    /** Set intensity of haptic playback, should be set after querying vibrator service. */
+    virtual void setHapticIntensity(os::HapticScale hapticIntensity) = 0;
+    /** Set maximum amplitude allowed for haptic data, should be set after querying
+     *  vibrator service.
+     */
+    virtual void setHapticMaxAmplitude(float maxAmplitude) = 0;
+    virtual sp<os::ExternalVibration> getExternalVibration() const = 0;
+
+    // This function should be called with holding thread lock.
+    virtual void updateTeePatches_l() = 0;
+
+    // Argument teePatchesToUpdate is by value, use std::move to optimize.
+    virtual void setTeePatchesToUpdate_l(TeePatches teePatchesToUpdate) = 0;
+
+    static bool checkServerLatencySupported(audio_format_t format, audio_output_flags_t flags) {
+        return audio_is_linear_pcm(format) && (flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC) == 0;
+    }
+
+    virtual audio_output_flags_t getOutputFlags() const = 0;
+    virtual float getSpeed() const = 0;
+
+    /**
+     * Updates the mute state and notifies the audio service. Call this only when holding player
+     * thread lock.
+     */
+    virtual void processMuteEvent_l(
+            const sp<IAudioManager>& audioManager, mute_state_t muteState) = 0;
+
+    virtual void triggerEvents(AudioSystem::sync_event_t type) = 0;
+
+    virtual void disable() = 0;
+    virtual int& fastIndex() = 0;
+    virtual bool isPlaybackRestricted() const = 0;
+
+    // Used by thread only
+
+    virtual bool isPausing() const = 0;
+    virtual bool isPaused() const = 0;
+    virtual bool isResuming() const = 0;
+    virtual bool isReady() const = 0;
+    virtual void setPaused() = 0;
+    virtual void reset() = 0;
+    virtual bool isFlushPending() const = 0;
+    virtual void flushAck() = 0;
+    virtual bool isResumePending() const = 0;
+    virtual void resumeAck() = 0;
+    // For direct or offloaded tracks ensure that the pause state is acknowledged
+    // by the playback thread in case of an immediate flush.
+    virtual bool isPausePending() const = 0;
+    virtual void pauseAck() = 0;
+    virtual void updateTrackFrameInfo(
+            int64_t trackFramesReleased, int64_t sinkFramesWritten, uint32_t halSampleRate,
+            const ExtendedTimestamp& timeStamp) = 0;
+    virtual sp<IMemory> sharedBuffer() const = 0;
+
+    // Dup with ExtendedAudioBufferProvider
+    virtual size_t framesReady() const = 0;
+
+    // presentationComplete checked by frames. (Mixed Tracks).
+    // framesWritten is cumulative, never reset, and is shared all tracks
+    // audioHalFrames is derived from output latency
+    virtual bool presentationComplete(int64_t framesWritten, size_t audioHalFrames) = 0;
+
+    // presentationComplete checked by time. (Direct Tracks).
+    virtual bool presentationComplete(uint32_t latencyMs) = 0;
+
+    virtual void resetPresentationComplete() = 0;
+
+    virtual bool hasVolumeController() const = 0;
+    virtual void setHasVolumeController(bool hasVolumeController) = 0;
+    virtual const sp<AudioTrackServerProxy>& audioTrackServerProxy() const = 0;
+    virtual void setCachedVolume(float volume) = 0;
+    virtual void setResetDone(bool resetDone) = 0;
+
+    virtual ExtendedAudioBufferProvider* asExtendedAudioBufferProvider() = 0;
+    virtual VolumeProvider* asVolumeProvider() = 0;
+
+    // TODO(b/291317964) split into getter/setter
+    virtual FillingStatus& fillingStatus() = 0;
+    virtual int8_t& retryCount() = 0;
+    virtual FastTrackUnderruns& fastTrackUnderruns() = 0;
+};
+
+// playback track, used by DuplicatingThread
+class IAfOutputTrack : public virtual IAfTrack {
+public:
+    static sp<IAfOutputTrack> create(
+            IAfPlaybackThread* playbackThread,
+            IAfDuplicatingThread* sourceThread, uint32_t sampleRate,
+            audio_format_t format, audio_channel_mask_t channelMask, size_t frameCount,
+            const AttributionSourceState& attributionSource);
+
+    virtual ssize_t write(void* data, uint32_t frames) = 0;
+    virtual bool bufferQueueEmpty() const = 0;
+    virtual bool isActive() const = 0;
+
+    /** Set the metadatas of the upstream tracks. Thread safe. */
+    virtual void setMetadatas(const SourceMetadatas& metadatas) = 0;
+    /** returns client timestamp to the upstream duplicating thread. */
+    virtual ExtendedTimestamp getClientProxyTimestamp() const = 0;
+};
+
+class IAfMmapTrack : public virtual IAfTrackBase {
+public:
+    static sp<IAfMmapTrack> create(IAfThreadBase* thread,
+            const audio_attributes_t& attr,
+            uint32_t sampleRate,
+            audio_format_t format,
+            audio_channel_mask_t channelMask,
+            audio_session_t sessionId,
+            bool isOut,
+            const android::content::AttributionSourceState& attributionSource,
+            pid_t creatorPid,
+            audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE);
+
+    // protected by MMapThread::mLock
+    virtual void setSilenced_l(bool silenced) = 0;
+    // protected by MMapThread::mLock
+    virtual bool isSilenced_l() const = 0;
+    // protected by MMapThread::mLock
+    virtual bool getAndSetSilencedNotified_l() = 0;
+
+    /**
+     * Updates the mute state and notifies the audio service. Call this only when holding player
+     * thread lock.
+     */
+    virtual void processMuteEvent_l(  // see IAfTrack
+            const sp<IAudioManager>& audioManager, mute_state_t muteState) = 0;
+};
+
+class RecordBufferConverter;
+
+class IAfRecordTrack : public virtual IAfTrackBase {
+public:
+    // createIAudioRecordAdapter() is a static constructor which creates an
+    // IAudioRecord AIDL interface adapter from the RecordTrack object that
+    // may be passed back to the client (if needed).
+    //
+    // Only one AIDL IAudioRecord interface adapter should be created per RecordTrack.
+    static sp<media::IAudioRecord> createIAudioRecordAdapter(const sp<IAfRecordTrack>& recordTrack);
+
+    static sp<IAfRecordTrack> create(IAfRecordThread* thread,
+            const sp<Client>& client,
+            const audio_attributes_t& attr,
+            uint32_t sampleRate,
+            audio_format_t format,
+            audio_channel_mask_t channelMask,
+            size_t frameCount,
+            void* buffer,
+            size_t bufferSize,
+            audio_session_t sessionId,
+            pid_t creatorPid,
+            const AttributionSourceState& attributionSource,
+            audio_input_flags_t flags,
+            track_type type,
+            audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE,
+            int32_t startFrames = -1);
+
+    // clear the buffer overflow flag
+    virtual void clearOverflow() = 0;
+    // set the buffer overflow flag and return previous value
+    virtual bool setOverflow() = 0;
+
+    // TODO(b/291317964) handleSyncStartEvent in IAfTrackBase should move here.
+    virtual void clearSyncStartEvent() = 0;
+    virtual void updateTrackFrameInfo(
+            int64_t trackFramesReleased, int64_t sourceFramesRead, uint32_t halSampleRate,
+            const ExtendedTimestamp& timestamp) = 0;
+
+    virtual void setSilenced(bool silenced) = 0;
+    virtual bool isSilenced() const = 0;
+    virtual status_t getActiveMicrophones(
+            std::vector<media::MicrophoneInfoFw>* activeMicrophones) const = 0;
+
+    virtual status_t setPreferredMicrophoneDirection(audio_microphone_direction_t direction) = 0;
+    virtual status_t setPreferredMicrophoneFieldDimension(float zoom) = 0;
+    virtual status_t shareAudioHistory(
+            const std::string& sharedAudioPackageName, int64_t sharedAudioStartMs) = 0;
+    virtual int32_t startFrames() const = 0;
+
+    static bool checkServerLatencySupported(audio_format_t format, audio_input_flags_t flags) {
+        return audio_is_linear_pcm(format) && (flags & AUDIO_INPUT_FLAG_HW_AV_SYNC) == 0;
+    }
+
+    using SinkMetadatas = std::vector<record_track_metadata_v7_t>;
+    using MetadataInserter = std::back_insert_iterator<SinkMetadatas>;
+    virtual void copyMetadataTo(MetadataInserter& backInserter) const = 0; // see IAfTrack
+
+    // private to Threads
+    virtual AudioBufferProvider::Buffer& sinkBuffer() = 0;
+    virtual audioflinger::SynchronizedRecordState& synchronizedRecordState() = 0;
+    virtual RecordBufferConverter* recordBufferConverter() const = 0;
+    virtual ResamplerBufferProvider* resamplerBufferProvider() const = 0;
+};
+
+// PatchProxyBufferProvider interface is implemented by PatchTrack and PatchRecord.
+// it provides buffer access methods that map those of a ClientProxy (see AudioTrackShared.h)
+class PatchProxyBufferProvider {
+public:
+    virtual ~PatchProxyBufferProvider() = default;
+    virtual bool producesBufferOnDemand() const = 0;
+    virtual status_t obtainBuffer(
+            Proxy::Buffer* buffer, const struct timespec* requested = nullptr) = 0;
+    virtual void releaseBuffer(Proxy::Buffer* buffer) = 0;
+};
+
+class IAfPatchTrackBase : public virtual RefBase {
+public:
+    using Timeout = std::optional<std::chrono::nanoseconds>;
+
+    virtual void setPeerTimeout(std::chrono::nanoseconds timeout) = 0;
+    virtual void setPeerProxy(const sp<IAfPatchTrackBase>& proxy, bool holdReference) = 0;
+    virtual void clearPeerProxy() = 0;
+    virtual PatchProxyBufferProvider* asPatchProxyBufferProvider() = 0;
+};
+
+class IAfPatchTrack : public virtual IAfTrack, public virtual IAfPatchTrackBase {
+public:
+    static sp<IAfPatchTrack> create(
+            IAfPlaybackThread* playbackThread,
+            audio_stream_type_t streamType,
+            uint32_t sampleRate,
+            audio_channel_mask_t channelMask,
+            audio_format_t format,
+            size_t frameCount,
+            void *buffer,
+            size_t bufferSize,
+            audio_output_flags_t flags,
+            const Timeout& timeout = {},
+            size_t frameCountToBeReady = 1 /** Default behaviour is to start
+                                             *  as soon as possible to have
+                                             *  the lowest possible latency
+                                             *  even if it might glitch. */);
+};
+
+class IAfPatchRecord : public virtual IAfRecordTrack, public virtual IAfPatchTrackBase {
+public:
+    static sp<IAfPatchRecord> create(
+            IAfRecordThread* recordThread,
+            uint32_t sampleRate,
+            audio_channel_mask_t channelMask,
+            audio_format_t format,
+            size_t frameCount,
+            void* buffer,
+            size_t bufferSize,
+            audio_input_flags_t flags,
+            const Timeout& timeout = {},
+            audio_source_t source = AUDIO_SOURCE_DEFAULT);
+
+    static sp<IAfPatchRecord> createPassThru(
+            IAfRecordThread* recordThread,
+            uint32_t sampleRate,
+            audio_channel_mask_t channelMask,
+            audio_format_t format,
+            size_t frameCount,
+            audio_input_flags_t flags,
+            audio_source_t source = AUDIO_SOURCE_DEFAULT);
+
+    virtual Source* getSource() = 0;
+    virtual size_t writeFrames(const void* src, size_t frameCount, size_t frameSize) = 0;
+};
+
+}  // namespace android
diff --git a/services/audioflinger/MelReporter.cpp b/services/audioflinger/MelReporter.cpp
index 39f772b..f3256a7 100644
--- a/services/audioflinger/MelReporter.cpp
+++ b/services/audioflinger/MelReporter.cpp
@@ -16,9 +16,9 @@
 */
 
 // #define LOG_NDEBUG 0
-#define LOG_TAG "AudioFlinger::MelReporter"
+#define LOG_TAG "MelReporter"
 
-#include "AudioFlinger.h"
+#include "MelReporter.h"
 
 #include <android/media/ISoundDoseCallback.h>
 #include <audio_utils/power.h>
@@ -28,7 +28,7 @@
 
 namespace android {
 
-bool AudioFlinger::MelReporter::activateHalSoundDoseComputation(const std::string& module,
+bool MelReporter::activateHalSoundDoseComputation(const std::string& module,
         const sp<DeviceHalInterface>& device) {
     if (mSoundDoseManager->forceUseFrameworkMel()) {
         ALOGD("%s: Forcing use of internal MEL computation.", __func__);
@@ -63,7 +63,7 @@
     return true;
 }
 
-void AudioFlinger::MelReporter::activateInternalSoundDoseComputation() {
+void MelReporter::activateInternalSoundDoseComputation() {
     {
         std::lock_guard _l(mLock);
         if (!mUseHalSoundDoseInterface) {
@@ -76,11 +76,11 @@
     mSoundDoseManager->setHalSoundDoseInterface(nullptr);
 }
 
-void AudioFlinger::MelReporter::onFirstRef() {
-    mAudioFlinger.mPatchCommandThread->addListener(this);
+void MelReporter::onFirstRef() {
+    mAfMelReporterCallback->getPatchCommandThread()->addListener(this);
 }
 
-bool AudioFlinger::MelReporter::shouldComputeMelForDeviceType(audio_devices_t device) {
+bool MelReporter::shouldComputeMelForDeviceType(audio_devices_t device) {
     if (!mSoundDoseManager->isCsdEnabled()) {
         ALOGV("%s csd is disabled", __func__);
         return false;
@@ -104,14 +104,14 @@
     }
 }
 
-void AudioFlinger::MelReporter::updateMetadataForCsd(audio_io_handle_t streamHandle,
+void MelReporter::updateMetadataForCsd(audio_io_handle_t streamHandle,
         const std::vector<playback_track_metadata_v7_t>& metadataVec) {
     if (!mSoundDoseManager->isCsdEnabled()) {
         ALOGV("%s csd is disabled", __func__);
         return;
     }
 
-    std::lock_guard _laf(mAudioFlinger.mLock);
+    std::lock_guard _laf(mAfMelReporterCallback->mutex());
     std::lock_guard _l(mLock);
     auto activeMelPatchId = activePatchStreamHandle_l(streamHandle);
     if (!activeMelPatchId) {
@@ -140,8 +140,8 @@
     }
 }
 
-void AudioFlinger::MelReporter::onCreateAudioPatch(audio_patch_handle_t handle,
-        const PatchPanel::Patch& patch) {
+void MelReporter::onCreateAudioPatch(audio_patch_handle_t handle,
+        const IAfPatchPanel::Patch& patch) {
     if (!mSoundDoseManager->isCsdEnabled()) {
         ALOGV("%s csd is disabled", __func__);
         return;
@@ -171,7 +171,7 @@
     }
 
     if (!newPatch.deviceHandles.empty()) {
-        std::lock_guard _afl(mAudioFlinger.mLock);
+        std::lock_guard _afl(mAfMelReporterCallback->mutex());
         std::lock_guard _l(mLock);
         ALOGV("%s add patch handle %d to active devices", __func__, handle);
         startMelComputationForActivePatch_l(newPatch);
@@ -180,10 +180,10 @@
     }
 }
 
-void AudioFlinger::MelReporter::startMelComputationForActivePatch_l(const ActiveMelPatch& patch)
+void MelReporter::startMelComputationForActivePatch_l(const ActiveMelPatch& patch)
 NO_THREAD_SAFETY_ANALYSIS  // access of AudioFlinger::checkOutputThread_l
 {
-    auto outputThread = mAudioFlinger.checkOutputThread_l(patch.streamHandle);
+    auto outputThread = mAfMelReporterCallback->checkOutputThread_l(patch.streamHandle);
     if (outputThread == nullptr) {
         ALOGE("%s cannot find thread for stream handle %d", __func__, patch.streamHandle);
         return;
@@ -198,14 +198,14 @@
             outputThread->startMelComputation_l(mSoundDoseManager->getOrCreateProcessorForDevice(
                 deviceHandle,
                 patch.streamHandle,
-                outputThread->mSampleRate,
-                outputThread->mChannelCount,
-                outputThread->mFormat));
+                outputThread->sampleRate(),
+                outputThread->channelCount(),
+                outputThread->format()));
         }
     }
 }
 
-void AudioFlinger::MelReporter::onReleaseAudioPatch(audio_patch_handle_t handle) {
+void MelReporter::onReleaseAudioPatch(audio_patch_handle_t handle) {
     if (!mSoundDoseManager->isCsdEnabled()) {
         ALOGV("%s csd is disabled", __func__);
         return;
@@ -226,25 +226,31 @@
         mActiveMelPatches.erase(patchIt);
     }
 
-    std::lock_guard _afl(mAudioFlinger.mLock);
+    std::lock_guard _afl(mAfMelReporterCallback->mutex());
     std::lock_guard _l(mLock);
     stopMelComputationForPatch_l(melPatch);
 }
 
-sp<media::ISoundDose> AudioFlinger::MelReporter::getSoundDoseInterface(
+void MelReporter::onUpdateAudioPatch(audio_patch_handle_t oldHandle,
+        audio_patch_handle_t newHandle, const IAfPatchPanel::Patch& patch) {
+    onReleaseAudioPatch(oldHandle);
+    onCreateAudioPatch(newHandle, patch);
+}
+
+sp<media::ISoundDose> MelReporter::getSoundDoseInterface(
         const sp<media::ISoundDoseCallback>& callback) {
     // no need to lock since getSoundDoseInterface is synchronized
     return mSoundDoseManager->getSoundDoseInterface(callback);
 }
 
-void AudioFlinger::MelReporter::stopInternalMelComputation() {
+void MelReporter::stopInternalMelComputation() {
     ALOGV("%s", __func__);
     std::lock_guard _l(mLock);
     mActiveMelPatches.clear();
     mUseHalSoundDoseInterface = true;
 }
 
-void AudioFlinger::MelReporter::stopMelComputationForPatch_l(const ActiveMelPatch& patch)
+void MelReporter::stopMelComputationForPatch_l(const ActiveMelPatch& patch)
 NO_THREAD_SAFETY_ANALYSIS  // access of AudioFlinger::checkOutputThread_l
 {
     if (!patch.csdActive) {
@@ -252,7 +258,7 @@
         return;
     }
 
-    auto outputThread = mAudioFlinger.checkOutputThread_l(patch.streamHandle);
+    auto outputThread = mAfMelReporterCallback->checkOutputThread_l(patch.streamHandle);
 
     ALOGV("%s: stop MEL for stream id: %d", __func__, patch.streamHandle);
     for (const auto& deviceId : patch.deviceHandles) {
@@ -272,7 +278,7 @@
 }
 
 
-std::optional<audio_patch_handle_t> AudioFlinger::MelReporter::activePatchStreamHandle_l(
+std::optional<audio_patch_handle_t> MelReporter::activePatchStreamHandle_l(
         audio_io_handle_t streamHandle) {
     for(const auto& patchIt : mActiveMelPatches) {
         if (patchIt.second.streamHandle == streamHandle) {
@@ -282,11 +288,11 @@
     return std::nullopt;
 }
 
-bool AudioFlinger::MelReporter::useHalSoundDoseInterface_l() {
+bool MelReporter::useHalSoundDoseInterface_l() {
     return !mSoundDoseManager->forceUseFrameworkMel() & mUseHalSoundDoseInterface;
 }
 
-std::string AudioFlinger::MelReporter::dump() {
+std::string MelReporter::dump() {
     std::lock_guard _l(mLock);
     std::string output("\nSound Dose:\n");
     output.append(mSoundDoseManager->dump());
diff --git a/services/audioflinger/MelReporter.h b/services/audioflinger/MelReporter.h
index 2bc33f2..005ca96 100644
--- a/services/audioflinger/MelReporter.h
+++ b/services/audioflinger/MelReporter.h
@@ -15,24 +15,35 @@
 ** limitations under the License.
 */
 
-#ifndef INCLUDING_FROM_AUDIOFLINGER_H
-    #error This header file should only be included from AudioFlinger.h
-#endif
+#pragma once
+
+#include "IAfPatchPanel.h"
+#include "PatchCommandThread.h"
+
+#include <sounddose/SoundDoseManager.h>
 
 #include <mutex>
-#include <sounddose/SoundDoseManager.h>
 #include <unordered_map>
 
+namespace android {
+
 constexpr static int kMaxTimestampDeltaInSec = 120;
 
+class IAfMelReporterCallback : public virtual RefBase {
+public:
+    virtual Mutex& mutex() const = 0;
+    virtual const sp<PatchCommandThread>& getPatchCommandThread() = 0;
+    virtual sp<IAfThreadBase> checkOutputThread_l(audio_io_handle_t ioHandle) const = 0;
+};
+
 /**
  * Class for listening to new patches and starting the MEL computation. MelReporter is
  * concealed within AudioFlinger, their lifetimes are the same.
  */
 class MelReporter : public PatchCommandThread::PatchCommandListener {
 public:
-    explicit MelReporter(AudioFlinger& audioFlinger)
-        : mAudioFlinger(audioFlinger),
+    explicit MelReporter(const sp<IAfMelReporterCallback>& afMelReporterCallback)
+        : mAfMelReporterCallback(afMelReporterCallback),
           mSoundDoseManager(sp<SoundDoseManager>::make()) {}
 
     void onFirstRef() override;
@@ -67,8 +78,11 @@
 
     // PatchCommandListener methods
     void onCreateAudioPatch(audio_patch_handle_t handle,
-                            const PatchPanel::Patch& patch) override;
-    void onReleaseAudioPatch(audio_patch_handle_t handle) override;
+        const IAfPatchPanel::Patch& patch) final;
+    void onReleaseAudioPatch(audio_patch_handle_t handle) final;
+    void onUpdateAudioPatch(audio_patch_handle_t oldHandle,
+                            audio_patch_handle_t newHandle,
+                            const IAfPatchPanel::Patch& patch) final;
 
     /**
      * The new metadata can determine whether we should compute MEL for the given thread.
@@ -100,7 +114,7 @@
 
     bool useHalSoundDoseInterface_l() REQUIRES(mLock);
 
-    AudioFlinger& mAudioFlinger;  // does not own the object
+    const sp<IAfMelReporterCallback> mAfMelReporterCallback;
 
     sp<SoundDoseManager> mSoundDoseManager;
 
@@ -109,9 +123,9 @@
      * Locking order AudioFlinger::mLock -> PatchCommandThread::mLock -> MelReporter::mLock.
      */
     std::mutex mLock;
-    std::unordered_map<audio_patch_handle_t, ActiveMelPatch>
-        mActiveMelPatches GUARDED_BY(AudioFlinger::MelReporter::mLock);
-    std::unordered_map<audio_port_handle_t, int>
-        mActiveDevices GUARDED_BY(AudioFlinger::MelReporter::mLock);
-    bool mUseHalSoundDoseInterface GUARDED_BY(AudioFlinger::MelReporter::mLock) = false;
+    std::unordered_map<audio_patch_handle_t, ActiveMelPatch> mActiveMelPatches GUARDED_BY(mLock);
+    std::unordered_map<audio_port_handle_t, int> mActiveDevices GUARDED_BY(mLock);
+    bool mUseHalSoundDoseInterface GUARDED_BY(mLock) = false;
 };
+
+}  // namespace android
diff --git a/services/audioflinger/MmapTracks.h b/services/audioflinger/MmapTracks.h
index cb46c52..85ce142 100644
--- a/services/audioflinger/MmapTracks.h
+++ b/services/audioflinger/MmapTracks.h
@@ -15,14 +15,18 @@
 ** limitations under the License.
 */
 
-#ifndef INCLUDING_FROM_AUDIOFLINGER_H
-    #error This header file should only be included from AudioFlinger.h
-#endif
+#pragma once
+
+#include "TrackBase.h"
+
+#include <android/content/AttributionSourceState.h>
+
+namespace android {
 
 // playback track
-class MmapTrack : public TrackBase {
+class MmapTrack : public TrackBase, public IAfMmapTrack {
 public:
-                MmapTrack(ThreadBase *thread,
+    MmapTrack(IAfThreadBase* thread,
                             const audio_attributes_t& attr,
                             uint32_t sampleRate,
                             audio_format_t format,
@@ -32,26 +36,25 @@
                             const android::content::AttributionSourceState& attributionSource,
                             pid_t creatorPid,
                             audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE);
-    virtual             ~MmapTrack();
+    ~MmapTrack() override;
 
-                        // TrackBase virtual
-    virtual status_t    initCheck() const;
-    virtual status_t    start(AudioSystem::sync_event_t event,
-                              audio_session_t triggerSession);
-    virtual void        stop();
-    virtual bool        isFastTrack() const { return false; }
-            bool        isDirect() const override { return true; }
+    status_t initCheck() const final;
+    status_t start(
+            AudioSystem::sync_event_t event, audio_session_t triggerSession) final;
+    void stop() final;
+    bool isFastTrack() const final { return false; }
+    bool isDirect() const final { return true; }
 
-            void        appendDumpHeader(String8& result);
-            void        appendDump(String8& result, bool active);
+    void appendDumpHeader(String8& result) const final;
+    void appendDump(String8& result, bool active) const final;
 
                         // protected by MMapThread::mLock
-            void        setSilenced_l(bool silenced) { mSilenced = silenced;
+    void setSilenced_l(bool silenced) final { mSilenced = silenced;
                                                        mSilencedNotified = false;}
                         // protected by MMapThread::mLock
-            bool        isSilenced_l() const { return mSilenced; }
+    bool isSilenced_l() const final { return mSilenced; }
                         // protected by MMapThread::mLock
-            bool        getAndSetSilencedNotified_l() { bool silencedNotified = mSilencedNotified;
+    bool getAndSetSilencedNotified_l() final { bool silencedNotified = mSilencedNotified;
                                                         mSilencedNotified = true;
                                                         return silencedNotified; }
 
@@ -61,10 +64,8 @@
      */
     void processMuteEvent_l(const sp<IAudioManager>& audioManager,
                             mute_state_t muteState)
-                            REQUIRES(AudioFlinger::MmapPlaybackThread::mLock);
+                            /* REQUIRES(MmapPlaybackThread::mLock) */ final;
 private:
-    friend class MmapThread;
-
     DISALLOW_COPY_AND_ASSIGN(MmapTrack);
 
     // AudioBufferProvider interface
@@ -72,19 +73,20 @@
     // releaseBuffer() not overridden
 
     // ExtendedAudioBufferProvider interface
-    virtual size_t framesReady() const;
-    virtual int64_t framesReleased() const;
-    virtual void onTimestamp(const ExtendedTimestamp &timestamp);
+    size_t framesReady() const final;
+    int64_t framesReleased() const final;
+    void onTimestamp(const ExtendedTimestamp &timestamp) final;
 
-    pid_t mPid;
+    const pid_t mPid;
     bool  mSilenced;            // protected by MMapThread::mLock
     bool  mSilencedNotified;    // protected by MMapThread::mLock
 
     // TODO: replace PersistableBundle with own struct
     // access these two variables only when holding player thread lock.
     std::unique_ptr<os::PersistableBundle> mMuteEventExtras
-            GUARDED_BY(AudioFlinger::MmapPlaybackThread::mLock);
+            /* GUARDED_BY(MmapPlaybackThread::mLock) */;
     mute_state_t mMuteState
-            GUARDED_BY(AudioFlinger::MmapPlaybackThread::mLock);
+            /* GUARDED_BY(MmapPlaybackThread::mLock) */;
 };  // end of Track
 
+} // namespace android
\ No newline at end of file
diff --git a/services/audioflinger/PatchCommandThread.cpp b/services/audioflinger/PatchCommandThread.cpp
index f4aab1f..8d5eb9f 100644
--- a/services/audioflinger/PatchCommandThread.cpp
+++ b/services/audioflinger/PatchCommandThread.cpp
@@ -18,31 +18,33 @@
 #define LOG_TAG "AudioFlinger::PatchCommandThread"
 //#define LOG_NDEBUG 0
 
-#include "AudioFlinger.h"
+#include "PatchCommandThread.h"
+
+#include <utils/Log.h>
 
 namespace android {
 
 constexpr char kPatchCommandThreadName[] = "AudioFlinger_PatchCommandThread";
 
-AudioFlinger::PatchCommandThread::~PatchCommandThread() {
+PatchCommandThread::~PatchCommandThread() {
     exit();
 
     std::lock_guard _l(mLock);
     mCommands.clear();
 }
 
-void AudioFlinger::PatchCommandThread::onFirstRef() {
+void PatchCommandThread::onFirstRef() {
     run(kPatchCommandThreadName, ANDROID_PRIORITY_AUDIO);
 }
 
-void AudioFlinger::PatchCommandThread::addListener(const sp<PatchCommandListener>& listener) {
+void PatchCommandThread::addListener(const sp<PatchCommandListener>& listener) {
     ALOGV("%s add listener %p", __func__, static_cast<void*>(listener.get()));
     std::lock_guard _l(mListenerLock);
     mListeners.emplace_back(listener);
 }
 
-void AudioFlinger::PatchCommandThread::createAudioPatch(audio_patch_handle_t handle,
-        const PatchPanel::Patch& patch) {
+void PatchCommandThread::createAudioPatch(audio_patch_handle_t handle,
+        const IAfPatchPanel::Patch& patch) {
     ALOGV("%s handle %d mHalHandle %d num sinks %d device sink %08x",
             __func__, handle, patch.mHalHandle,
             patch.mAudioPatch.num_sinks,
@@ -51,12 +53,22 @@
     createAudioPatchCommand(handle, patch);
 }
 
-void AudioFlinger::PatchCommandThread::releaseAudioPatch(audio_patch_handle_t handle) {
+void PatchCommandThread::releaseAudioPatch(audio_patch_handle_t handle) {
     ALOGV("%s", __func__);
     releaseAudioPatchCommand(handle);
 }
 
-bool AudioFlinger::PatchCommandThread::threadLoop()
+void PatchCommandThread::updateAudioPatch(audio_patch_handle_t oldHandle,
+        audio_patch_handle_t newHandle, const IAfPatchPanel::Patch& patch) {
+    ALOGV("%s handle %d mHalHandle %d num sinks %d device sink %08x",
+            __func__, oldHandle, patch.mHalHandle,
+            patch.mAudioPatch.num_sinks,
+            patch.mAudioPatch.num_sinks > 0 ? patch.mAudioPatch.sinks[0].ext.device.type : 0);
+
+    updateAudioPatchCommand(oldHandle, newHandle, patch);
+}
+
+bool PatchCommandThread::threadLoop()
 NO_THREAD_SAFETY_ANALYSIS  // bug in clang compiler.
 {
     std::unique_lock _l(mLock);
@@ -102,6 +114,21 @@
                     }
                 }
                     break;
+                case UPDATE_AUDIO_PATCH: {
+                    const auto data = (UpdateAudioPatchData*) command->mData.get();
+                    ALOGV("%s processing update audio patch old handle %d new handle %d",
+                          __func__,
+                          data->mOldHandle, data->mNewHandle);
+
+                    for (const auto& listener : listenersCopy) {
+                        auto spListener = listener.promote();
+                        if (spListener) {
+                            spListener->onUpdateAudioPatch(data->mOldHandle,
+                                    data->mNewHandle, data->mPatch);
+                        }
+                    }
+                }
+                    break;
                 default:
                     ALOGW("%s unknown command %d", __func__, command->mCommand);
                     break;
@@ -119,14 +146,14 @@
     return false;
 }
 
-void AudioFlinger::PatchCommandThread::sendCommand(const sp<Command>& command) {
+void PatchCommandThread::sendCommand(const sp<Command>& command) {
     std::lock_guard _l(mLock);
     mCommands.emplace_back(command);
     mWaitWorkCV.notify_one();
 }
 
-void AudioFlinger::PatchCommandThread::createAudioPatchCommand(
-        audio_patch_handle_t handle, const PatchPanel::Patch& patch) {
+void PatchCommandThread::createAudioPatchCommand(
+        audio_patch_handle_t handle, const IAfPatchPanel::Patch& patch) {
     auto command = sp<Command>::make(CREATE_AUDIO_PATCH,
                                      new CreateAudioPatchData(handle, patch));
     ALOGV("%s adding create patch handle %d mHalHandle %d.",
@@ -136,14 +163,24 @@
     sendCommand(command);
 }
 
-void AudioFlinger::PatchCommandThread::releaseAudioPatchCommand(audio_patch_handle_t handle) {
+void PatchCommandThread::releaseAudioPatchCommand(audio_patch_handle_t handle) {
     sp<Command> command =
         sp<Command>::make(RELEASE_AUDIO_PATCH, new ReleaseAudioPatchData(handle));
     ALOGV("%s adding release patch", __func__);
     sendCommand(command);
 }
 
-void AudioFlinger::PatchCommandThread::exit() {
+void PatchCommandThread::updateAudioPatchCommand(
+        audio_patch_handle_t oldHandle, audio_patch_handle_t newHandle,
+        const IAfPatchPanel::Patch& patch) {
+    sp<Command> command = sp<Command>::make(UPDATE_AUDIO_PATCH,
+                                           new UpdateAudioPatchData(oldHandle, newHandle, patch));
+    ALOGV("%s adding update patch old handle %d new handle %d mHalHandle %d.",
+            __func__, oldHandle, newHandle, patch.mHalHandle);
+    sendCommand(command);
+}
+
+void PatchCommandThread::exit() {
     ALOGV("%s", __func__);
     {
         std::lock_guard _l(mLock);
diff --git a/services/audioflinger/PatchCommandThread.h b/services/audioflinger/PatchCommandThread.h
index b52e0a9..66018d7 100644
--- a/services/audioflinger/PatchCommandThread.h
+++ b/services/audioflinger/PatchCommandThread.h
@@ -15,14 +15,22 @@
 ** limitations under the License.
 */
 
-#ifndef INCLUDING_FROM_AUDIOFLINGER_H
-    #error This header file should only be included from AudioFlinger.h
-#endif
+#pragma once
+
+#include "IAfPatchPanel.h"
+
+#include <utils/RefBase.h>  // avoid transitive dependency
+#include <utils/Thread.h>  // avoid transitive dependency
+
+#include <deque>
+#include <mutex>  // avoid transitive dependency
+
+namespace android {
 
 class Command;
 
 // Thread to execute create and release patch commands asynchronously. This is needed because
-// PatchPanel::createAudioPatch and releaseAudioPatch are executed from audio policy service
+// IAfPatchPanel::createAudioPatch and releaseAudioPatch are executed from audio policy service
 // with mutex locked and effect management requires to call back into audio policy service
 class PatchCommandThread : public Thread {
 public:
@@ -30,13 +38,17 @@
     enum {
         CREATE_AUDIO_PATCH,
         RELEASE_AUDIO_PATCH,
+        UPDATE_AUDIO_PATCH,
     };
 
     class PatchCommandListener : public virtual RefBase {
     public:
         virtual void onCreateAudioPatch(audio_patch_handle_t handle,
-                                        const PatchPanel::Patch& patch) = 0;
+                                        const IAfPatchPanel::Patch& patch) = 0;
         virtual void onReleaseAudioPatch(audio_patch_handle_t handle) = 0;
+        virtual void onUpdateAudioPatch(audio_patch_handle_t oldHandle,
+                                        audio_patch_handle_t newHandle,
+                                        const IAfPatchPanel::Patch& patch) = 0;
     };
 
     PatchCommandThread() : Thread(false /* canCallJava */) {}
@@ -44,8 +56,11 @@
 
     void addListener(const sp<PatchCommandListener>& listener);
 
-    void createAudioPatch(audio_patch_handle_t handle, const PatchPanel::Patch& patch);
+    void createAudioPatch(audio_patch_handle_t handle, const IAfPatchPanel::Patch& patch);
     void releaseAudioPatch(audio_patch_handle_t handle);
+    void updateAudioPatch(audio_patch_handle_t oldHandle,
+                          audio_patch_handle_t newHandle,
+                          const IAfPatchPanel::Patch& patch);
 
     // Thread virtuals
     void onFirstRef() override;
@@ -54,9 +69,11 @@
     void exit();
 
     void createAudioPatchCommand(audio_patch_handle_t handle,
-            const PatchPanel::Patch& patch);
+            const IAfPatchPanel::Patch& patch);
     void releaseAudioPatchCommand(audio_patch_handle_t handle);
-
+    void updateAudioPatchCommand(audio_patch_handle_t oldHandle,
+                                 audio_patch_handle_t newHandle,
+                                 const IAfPatchPanel::Patch& patch);
 private:
     class CommandData;
 
@@ -75,11 +92,11 @@
 
     class CreateAudioPatchData : public CommandData {
     public:
-        CreateAudioPatchData(audio_patch_handle_t handle, const PatchPanel::Patch& patch)
+        CreateAudioPatchData(audio_patch_handle_t handle, const IAfPatchPanel::Patch& patch)
             :   mHandle(handle), mPatch(patch) {}
 
         const audio_patch_handle_t mHandle;
-        const PatchPanel::Patch mPatch;
+        const IAfPatchPanel::Patch mPatch;
     };
 
     class ReleaseAudioPatchData : public CommandData {
@@ -90,6 +107,18 @@
         audio_patch_handle_t mHandle;
     };
 
+    class UpdateAudioPatchData : public CommandData {
+    public:
+        UpdateAudioPatchData(audio_patch_handle_t oldHandle,
+                             audio_patch_handle_t newHandle,
+                             const IAfPatchPanel::Patch& patch)
+            :   mOldHandle(oldHandle), mNewHandle(newHandle), mPatch(patch) {}
+
+        const audio_patch_handle_t mOldHandle;
+        const audio_patch_handle_t mNewHandle;
+        const IAfPatchPanel::Patch mPatch;
+    };
+
     void sendCommand(const sp<Command>& command);
 
     std::string mThreadName;
@@ -100,3 +129,5 @@
     std::mutex mListenerLock;
     std::vector<wp<PatchCommandListener>> mListeners GUARDED_BY(mListenerLock);
 };
+
+}  // namespace android
diff --git a/services/audioflinger/PatchPanel.cpp b/services/audioflinger/PatchPanel.cpp
index d0feba5..f11a530 100644
--- a/services/audioflinger/PatchPanel.cpp
+++ b/services/audioflinger/PatchPanel.cpp
@@ -19,16 +19,16 @@
 #define LOG_TAG "AudioFlinger::PatchPanel"
 //#define LOG_NDEBUG 0
 
-#include "Configuration.h"
-#include <utils/Log.h>
-#include <audio_utils/primitives.h>
+#include "PatchPanel.h"
+#include "PatchCommandThread.h"
 
-#include "AudioFlinger.h"
+#include <audio_utils/primitives.h>
 #include <media/AudioParameter.h>
 #include <media/AudioValidator.h>
 #include <media/DeviceDescriptorBase.h>
 #include <media/PatchBuilder.h>
 #include <mediautils/ServiceUtilities.h>
+#include <utils/Log.h>
 
 // ----------------------------------------------------------------------------
 
@@ -47,65 +47,43 @@
 
 namespace android {
 
-/* List connected audio ports and their attributes */
-status_t AudioFlinger::listAudioPorts(unsigned int *num_ports,
-                                struct audio_port *ports)
-{
-    Mutex::Autolock _l(mLock);
-    return mPatchPanel.listAudioPorts(num_ports, ports);
+/* static */
+sp<IAfPatchPanel> IAfPatchPanel::create(const sp<IAfPatchPanelCallback>& afPatchPanelCallback) {
+    return sp<PatchPanel>::make(afPatchPanelCallback);
 }
 
-/* Get supported attributes for a given audio port */
-status_t AudioFlinger::getAudioPort(struct audio_port_v7 *port) {
-    status_t status = AudioValidator::validateAudioPort(*port);
-    if (status != NO_ERROR) {
-        return status;
-    }
-
-    Mutex::Autolock _l(mLock);
-    return mPatchPanel.getAudioPort(port);
+status_t SoftwarePatch::getLatencyMs_l(double* latencyMs) const {
+    return mPatchPanel->getLatencyMs_l(mPatchHandle, latencyMs);
 }
 
-/* Connect a patch between several source and sink ports */
-status_t AudioFlinger::createAudioPatch(const struct audio_patch *patch,
-                                   audio_patch_handle_t *handle)
+status_t PatchPanel::getLatencyMs_l(
+        audio_patch_handle_t patchHandle, double* latencyMs) const
 {
-    status_t status = AudioValidator::validateAudioPatch(*patch);
-    if (status != NO_ERROR) {
-        return status;
-    }
-
-    Mutex::Autolock _l(mLock);
-    return mPatchPanel.createAudioPatch(patch, handle);
-}
-
-/* Disconnect a patch */
-status_t AudioFlinger::releaseAudioPatch(audio_patch_handle_t handle)
-{
-    Mutex::Autolock _l(mLock);
-    return mPatchPanel.releaseAudioPatch(handle);
-}
-
-/* List connected audio ports and they attributes */
-status_t AudioFlinger::listAudioPatches(unsigned int *num_patches,
-                                  struct audio_patch *patches)
-{
-    Mutex::Autolock _l(mLock);
-    return mPatchPanel.listAudioPatches(num_patches, patches);
-}
-
-status_t AudioFlinger::PatchPanel::SoftwarePatch::getLatencyMs_l(double *latencyMs) const
-{
-    const auto& iter = mPatchPanel.mPatches.find(mPatchHandle);
-    if (iter != mPatchPanel.mPatches.end()) {
+    const auto& iter = mPatches.find(patchHandle);
+    if (iter != mPatches.end()) {
         return iter->second.getLatencyMs(latencyMs);
     } else {
         return BAD_VALUE;
     }
 }
 
+void PatchPanel::closeThreadInternal_l(const sp<IAfThreadBase>& thread) const
+{
+    if (const auto recordThread = thread->asIAfRecordThread();
+            recordThread) {
+        mAfPatchPanelCallback->closeThreadInternal_l(recordThread);
+    } else if (const auto playbackThread = thread->asIAfPlaybackThread();
+            playbackThread) {
+        mAfPatchPanelCallback->closeThreadInternal_l(playbackThread);
+    } else {
+        LOG_ALWAYS_FATAL("%s: Endpoints only accept IAfPlayback and IAfRecord threads, "
+                "invalid thread, id: %d  type: %d",
+                __func__, thread->id(), thread->type());
+    }
+}
+
 /* List connected audio ports and their attributes */
-status_t AudioFlinger::PatchPanel::listAudioPorts(unsigned int *num_ports __unused,
+status_t PatchPanel::listAudioPorts(unsigned int* /* num_ports */,
                                 struct audio_port *ports __unused)
 {
     ALOGV(__func__);
@@ -113,7 +91,7 @@
 }
 
 /* Get supported attributes for a given audio port */
-status_t AudioFlinger::PatchPanel::getAudioPort(struct audio_port_v7 *port)
+status_t PatchPanel::getAudioPort(struct audio_port_v7* port)
 {
     if (port->type != AUDIO_PORT_TYPE_DEVICE) {
         // Only query the HAL when the port is a device.
@@ -132,10 +110,10 @@
 }
 
 /* Connect a patch between several source and sink ports */
-status_t AudioFlinger::PatchPanel::createAudioPatch(const struct audio_patch *patch,
+status_t PatchPanel::createAudioPatch(const struct audio_patch* patch,
                                    audio_patch_handle_t *handle,
                                    bool endpointPatch)
- //unlocks AudioFlinger::mLock when calling ThreadBase::sendCreateAudioPatchConfigEvent
+ //unlocks AudioFlinger::mLock when calling IAfThreadBase::sendCreateAudioPatchConfigEvent
  //to avoid deadlocks if the thread loop needs to acquire AudioFlinger::mLock
  //before processing the create patch request.
  NO_THREAD_SAFETY_ANALYSIS
@@ -156,7 +134,8 @@
     if (patch->num_sources > 2) {
         return INVALID_OPERATION;
     }
-
+    bool reuseExistingHalPatch = false;
+    audio_patch_handle_t oldhandle = AUDIO_PATCH_HANDLE_NONE;
     if (*handle != AUDIO_PATCH_HANDLE_NONE) {
         auto iter = mPatches.find(*handle);
         if (iter != mPatches.end()) {
@@ -174,6 +153,7 @@
             if (removedPatch.mHalHandle != AUDIO_PATCH_HANDLE_NONE) {
                 audio_module_handle_t hwModule = AUDIO_MODULE_HANDLE_NONE;
                 const struct audio_patch &oldPatch = removedPatch.mAudioPatch;
+                oldhandle = *handle;
                 if (oldPatch.sources[0].type == AUDIO_PORT_TYPE_DEVICE &&
                         (patch->sources[0].type != AUDIO_PORT_TYPE_DEVICE ||
                                 oldPatch.sources[0].ext.device.hw_module !=
@@ -196,8 +176,12 @@
                     hwDevice->releaseAudioPatch(removedPatch.mHalHandle);
                 }
                 halHandle = removedPatch.mHalHandle;
+                // Prevent to remove/add device effect when mix / device did not change, and
+                // hal patch has not been released
+                // Note that no patch leak at hal layer as halHandle is reused.
+                reuseExistingHalPatch = (hwDevice == 0) && patchesHaveSameRoute(*patch, oldPatch);
             }
-            erasePatch(*handle);
+            erasePatch(*handle, reuseExistingHalPatch);
         }
     }
 
@@ -249,8 +233,8 @@
                         status = INVALID_OPERATION;
                         goto exit;
                     }
-                    sp<ThreadBase> thread =
-                            mAudioFlinger.checkPlaybackThread_l(patch->sources[1].ext.mix.handle);
+                    const sp<IAfThreadBase> thread = mAfPatchPanelCallback->checkPlaybackThread_l(
+                            patch->sources[1].ext.mix.handle);
                     if (thread == 0) {
                         ALOGW("%s() cannot get playback thread", __func__);
                         status = INVALID_OPERATION;
@@ -258,7 +242,7 @@
                     }
                     // existing playback thread is reused, so it is not closed when patch is cleared
                     newPatch.mPlayback.setThread(
-                            reinterpret_cast<PlaybackThread*>(thread.get()), false /*closeThread*/);
+                            thread->asIAfPlaybackThread().get(), false /*closeThread*/);
                 } else {
                     audio_config_t config = AUDIO_CONFIG_INITIALIZER;
                     audio_config_base_t mixerConfig = AUDIO_CONFIG_BASE_INITIALIZER;
@@ -276,7 +260,7 @@
                     if (patch->sinks[0].config_mask & AUDIO_PORT_CONFIG_FLAGS) {
                         flags = patch->sinks[0].flags.output;
                     }
-                    sp<ThreadBase> thread = mAudioFlinger.openOutput_l(
+                    const sp<IAfThreadBase> thread = mAfPatchPanelCallback->openOutput_l(
                                                             patch->sinks[0].ext.device.hw_module,
                                                             &output,
                                                             &config,
@@ -284,12 +268,12 @@
                                                             outputDevice,
                                                             outputDeviceAddress,
                                                             flags);
-                    ALOGV("mAudioFlinger.openOutput_l() returned %p", thread.get());
+                    ALOGV("mAfPatchPanelCallback->openOutput_l() returned %p", thread.get());
                     if (thread == 0) {
                         status = NO_MEMORY;
                         goto exit;
                     }
-                    newPatch.mPlayback.setThread(reinterpret_cast<PlaybackThread*>(thread.get()));
+                    newPatch.mPlayback.setThread(thread->asIAfPlaybackThread().get());
                 }
                 audio_devices_t device = patch->sources[0].ext.device.type;
                 String8 address = String8(patch->sources[0].ext.device.address);
@@ -323,7 +307,7 @@
                                 == AUDIO_STREAM_VOICE_CALL) {
                     source = AUDIO_SOURCE_VOICE_COMMUNICATION;
                 }
-                sp<ThreadBase> thread = mAudioFlinger.openInput_l(srcModule,
+                const sp<IAfThreadBase> thread = mAfPatchPanelCallback->openInput_l(srcModule,
                                                                     &input,
                                                                     &config,
                                                                     device,
@@ -332,13 +316,13 @@
                                                                     flags,
                                                                     outputDevice,
                                                                     outputDeviceAddress);
-                ALOGV("mAudioFlinger.openInput_l() returned %p inChannelMask %08x",
+                ALOGV("mAfPatchPanelCallback->openInput_l() returned %p inChannelMask %08x",
                       thread.get(), config.channel_mask);
                 if (thread == 0) {
                     status = NO_MEMORY;
                     goto exit;
                 }
-                newPatch.mRecord.setThread(reinterpret_cast<RecordThread*>(thread.get()));
+                newPatch.mRecord.setThread(thread->asIAfRecordThread().get());
                 status = newPatch.createConnections(this);
                 if (status != NO_ERROR) {
                     goto exit;
@@ -348,10 +332,11 @@
                 }
             } else {
                 if (patch->sinks[0].type == AUDIO_PORT_TYPE_MIX) {
-                    sp<ThreadBase> thread = mAudioFlinger.checkRecordThread_l(
+                    sp<IAfThreadBase> thread = mAfPatchPanelCallback->checkRecordThread_l(
                                                               patch->sinks[0].ext.mix.handle);
                     if (thread == 0) {
-                        thread = mAudioFlinger.checkMmapThread_l(patch->sinks[0].ext.mix.handle);
+                        thread = mAfPatchPanelCallback->checkMmapThread_l(
+                                patch->sinks[0].ext.mix.handle);
                         if (thread == 0) {
                             ALOGW("%s() bad capture I/O handle %d",
                                     __func__, patch->sinks[0].ext.mix.handle);
@@ -359,9 +344,9 @@
                             goto exit;
                         }
                     }
-                    mAudioFlinger.unlock();
+                    mAfPatchPanelCallback->unlock();
                     status = thread->sendCreateAudioPatchConfigEvent(patch, &halHandle);
-                    mAudioFlinger.lock();
+                    mAfPatchPanelCallback->lock();
                     if (status == NO_ERROR) {
                         newPatch.setThread(thread);
                     }
@@ -385,7 +370,7 @@
         } break;
         case AUDIO_PORT_TYPE_MIX: {
             audio_module_handle_t srcModule =  patch->sources[0].ext.mix.hw_module;
-            ssize_t index = mAudioFlinger.mAudioHwDevs.indexOfKey(srcModule);
+            ssize_t index = mAfPatchPanelCallback->getAudioHwDevs_l().indexOfKey(srcModule);
             if (index < 0) {
                 ALOGW("%s() bad src hw module %d", __func__, srcModule);
                 status = BAD_VALUE;
@@ -411,10 +396,11 @@
                 device->applyAudioPortConfig(&patch->sinks[i]);
                 devices.push_back(device);
             }
-            sp<ThreadBase> thread =
-                            mAudioFlinger.checkPlaybackThread_l(patch->sources[0].ext.mix.handle);
+            sp<IAfThreadBase> thread = mAfPatchPanelCallback->checkPlaybackThread_l(
+                    patch->sources[0].ext.mix.handle);
             if (thread == 0) {
-                thread = mAudioFlinger.checkMmapThread_l(patch->sources[0].ext.mix.handle);
+                thread = mAfPatchPanelCallback->checkMmapThread_l(
+                        patch->sources[0].ext.mix.handle);
                 if (thread == 0) {
                     ALOGW("%s() bad playback I/O handle %d",
                             __func__, patch->sources[0].ext.mix.handle);
@@ -422,13 +408,13 @@
                     goto exit;
                 }
             }
-            if (thread == mAudioFlinger.primaryPlaybackThread_l()) {
-                mAudioFlinger.updateOutDevicesForRecordThreads_l(devices);
+            if (thread == mAfPatchPanelCallback->primaryPlaybackThread_l()) {
+                mAfPatchPanelCallback->updateOutDevicesForRecordThreads_l(devices);
             }
 
-            mAudioFlinger.unlock();
+            mAfPatchPanelCallback->unlock();
             status = thread->sendCreateAudioPatchConfigEvent(patch, &halHandle);
-            mAudioFlinger.lock();
+            mAfPatchPanelCallback->lock();
             if (status == NO_ERROR) {
                 newPatch.setThread(thread);
             }
@@ -453,9 +439,15 @@
 exit:
     ALOGV("%s() status %d", __func__, status);
     if (status == NO_ERROR) {
-        *handle = (audio_patch_handle_t) mAudioFlinger.nextUniqueId(AUDIO_UNIQUE_ID_USE_PATCH);
+        *handle = static_cast<audio_patch_handle_t>(
+                mAfPatchPanelCallback->nextUniqueId(AUDIO_UNIQUE_ID_USE_PATCH));
         newPatch.mHalHandle = halHandle;
-        mAudioFlinger.mPatchCommandThread->createAudioPatch(*handle, newPatch);
+        if (reuseExistingHalPatch) {
+            mAfPatchPanelCallback->getPatchCommandThread()->updateAudioPatch(
+                    oldhandle, *handle, newPatch);
+        } else {
+            mAfPatchPanelCallback->getPatchCommandThread()->createAudioPatch(*handle, newPatch);
+        }
         if (insertedModule != AUDIO_MODULE_HANDLE_NONE) {
             addSoftwarePatchToInsertedModules(insertedModule, *handle, &newPatch.mAudioPatch);
         }
@@ -466,13 +458,13 @@
     return status;
 }
 
-AudioFlinger::PatchPanel::Patch::~Patch()
+PatchPanel::Patch::~Patch()
 {
     ALOGE_IF(isSoftware(), "Software patch connections leaked %d %d",
             mRecord.handle(), mPlayback.handle());
 }
 
-status_t AudioFlinger::PatchPanel::Patch::createConnections(PatchPanel *panel)
+status_t PatchPanel::Patch::createConnections(const sp<IAfPatchPanel>& panel)
 {
     // create patch from source device to record thread input
     status_t status = panel->createAudioPatch(
@@ -546,7 +538,7 @@
         outputFlags = (audio_output_flags_t) (outputFlags & ~AUDIO_OUTPUT_FLAG_FAST);
     }
 
-    sp<RecordThread::PatchRecord> tempRecordTrack;
+    sp<IAfPatchRecord> tempRecordTrack;
     const bool usePassthruPatchRecord =
             (inputFlags & AUDIO_INPUT_FLAG_DIRECT) && (outputFlags & AUDIO_OUTPUT_FLAG_DIRECT);
     const size_t playbackFrameCount = mPlayback.thread()->frameCount();
@@ -558,7 +550,7 @@
         frameCount = std::max(playbackFrameCount, recordFrameCount);
         ALOGV("%s() playframeCount %zu recordFrameCount %zu frameCount %zu",
             __func__, playbackFrameCount, recordFrameCount, frameCount);
-        tempRecordTrack = new RecordThread::PassthruPatchRecord(
+        tempRecordTrack = IAfPatchRecord::createPassThru(
                                                  mRecord.thread().get(),
                                                  sampleRate,
                                                  inChannelMask,
@@ -577,7 +569,7 @@
         ALOGV("%s() playframeCount %zu recordFrameCount %zu frameCount %zu",
             __func__, playbackFrameCount, recordFrameCount, frameCount);
 
-        tempRecordTrack = new RecordThread::PatchRecord(
+        tempRecordTrack = IAfPatchRecord::create(
                                                  mRecord.thread().get(),
                                                  sampleRate,
                                                  inChannelMask,
@@ -602,7 +594,7 @@
     // Disable this behavior for FM Tuner source if no fast capture/mixer available.
     const bool isFmBridge = mAudioPatch.sources[0].ext.device.type == AUDIO_DEVICE_IN_FM_TUNER;
     const size_t frameCountToBeReady = isFmBridge && !usePassthruPatchRecord ? frameCount / 4 : 1;
-    sp<PlaybackThread::PatchTrack> tempPatchTrack = new PlaybackThread::PatchTrack(
+    sp<IAfPatchTrack> tempPatchTrack = IAfPatchTrack::create(
                                            mPlayback.thread().get(),
                                            streamType,
                                            sampleRate,
@@ -636,7 +628,7 @@
     return status;
 }
 
-void AudioFlinger::PatchPanel::Patch::clearConnections(PatchPanel *panel)
+void PatchPanel::Patch::clearConnections(const sp<IAfPatchPanel>& panel)
 {
     ALOGV("%s() mRecord.handle %d mPlayback.handle %d",
             __func__, mRecord.handle(), mPlayback.handle());
@@ -647,7 +639,7 @@
     mPlayback.closeConnections(panel);
 }
 
-status_t AudioFlinger::PatchPanel::Patch::getLatencyMs(double *latencyMs) const
+status_t PatchPanel::Patch::getLatencyMs(double* latencyMs) const
 {
     if (!isSoftware()) return INVALID_OPERATION;
 
@@ -679,7 +671,7 @@
     // If so, do a frame diff and time difference computation to estimate
     // the total patch latency. This requires that frame counts are reported by the
     // HAL are matched properly in the case of record overruns and playback underruns.
-    ThreadBase::TrackBase::FrameTime recordFT{}, playFT{};
+    IAfTrack::FrameTime recordFT{}, playFT{};
     recordTrack->getKernelFrameTime(&recordFT);
     playbackTrack->getKernelFrameTime(&playFT);
     if (recordFT.timeNs > 0 && playFT.timeNs > 0) {
@@ -706,7 +698,7 @@
     return INVALID_OPERATION;
 }
 
-String8 AudioFlinger::PatchPanel::Patch::dump(audio_patch_handle_t myHandle) const
+String8 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: %s (thread %p => thread %p)",
@@ -734,8 +726,8 @@
 }
 
 /* Disconnect a patch */
-status_t AudioFlinger::PatchPanel::releaseAudioPatch(audio_patch_handle_t handle)
- //unlocks AudioFlinger::mLock when calling ThreadBase::sendReleaseAudioPatchConfigEvent
+status_t PatchPanel::releaseAudioPatch(audio_patch_handle_t handle)
+ //unlocks AudioFlinger::mLock when calling IAfThreadBase::sendReleaseAudioPatchConfigEvent
  //to avoid deadlocks if the thread loop needs to acquire AudioFlinger::mLock
  //before processing the release patch request.
  NO_THREAD_SAFETY_ANALYSIS
@@ -767,18 +759,18 @@
 
             if (patch.sinks[0].type == AUDIO_PORT_TYPE_MIX) {
                 audio_io_handle_t ioHandle = patch.sinks[0].ext.mix.handle;
-                sp<ThreadBase> thread = mAudioFlinger.checkRecordThread_l(ioHandle);
+                sp<IAfThreadBase> thread = mAfPatchPanelCallback->checkRecordThread_l(ioHandle);
                 if (thread == 0) {
-                    thread = mAudioFlinger.checkMmapThread_l(ioHandle);
+                    thread = mAfPatchPanelCallback->checkMmapThread_l(ioHandle);
                     if (thread == 0) {
                         ALOGW("%s() bad capture I/O handle %d", __func__, ioHandle);
                         status = BAD_VALUE;
                         break;
                     }
                 }
-                mAudioFlinger.unlock();
+                mAfPatchPanelCallback->unlock();
                 status = thread->sendReleaseAudioPatchConfigEvent(removedPatch.mHalHandle);
-                mAudioFlinger.lock();
+                mAfPatchPanelCallback->lock();
             } else {
                 status = hwDevice->releaseAudioPatch(removedPatch.mHalHandle);
             }
@@ -790,18 +782,18 @@
                 break;
             }
             audio_io_handle_t ioHandle = src.ext.mix.handle;
-            sp<ThreadBase> thread = mAudioFlinger.checkPlaybackThread_l(ioHandle);
+            sp<IAfThreadBase> thread = mAfPatchPanelCallback->checkPlaybackThread_l(ioHandle);
             if (thread == 0) {
-                thread = mAudioFlinger.checkMmapThread_l(ioHandle);
+                thread = mAfPatchPanelCallback->checkMmapThread_l(ioHandle);
                 if (thread == 0) {
                     ALOGW("%s() bad playback I/O handle %d", __func__, ioHandle);
                     status = BAD_VALUE;
                     break;
                 }
             }
-            mAudioFlinger.unlock();
+            mAfPatchPanelCallback->unlock();
             status = thread->sendReleaseAudioPatchConfigEvent(removedPatch.mHalHandle);
-            mAudioFlinger.lock();
+            mAfPatchPanelCallback->lock();
         } break;
         default:
             status = BAD_VALUE;
@@ -811,23 +803,25 @@
     return status;
 }
 
-void AudioFlinger::PatchPanel::erasePatch(audio_patch_handle_t handle) {
+void PatchPanel::erasePatch(audio_patch_handle_t handle, bool reuseExistingHalPatch) {
     mPatches.erase(handle);
     removeSoftwarePatchFromInsertedModules(handle);
-    mAudioFlinger.mPatchCommandThread->releaseAudioPatch(handle);
+    if (!reuseExistingHalPatch) {
+        mAfPatchPanelCallback->getPatchCommandThread()->releaseAudioPatch(handle);
+    }
 }
 
 /* List connected audio ports and they attributes */
-status_t AudioFlinger::PatchPanel::listAudioPatches(unsigned int *num_patches __unused,
+status_t PatchPanel::listAudioPatches(unsigned int* /* num_patches */,
                                   struct audio_patch *patches __unused)
 {
     ALOGV(__func__);
     return NO_ERROR;
 }
 
-status_t AudioFlinger::PatchPanel::getDownstreamSoftwarePatches(
+status_t PatchPanel::getDownstreamSoftwarePatches(
         audio_io_handle_t stream,
-        std::vector<AudioFlinger::PatchPanel::SoftwarePatch> *patches) const
+        std::vector<SoftwarePatch>* patches) const
 {
     for (const auto& module : mInsertedModules) {
         if (module.second.streams.count(stream)) {
@@ -835,7 +829,8 @@
                 const auto& patch_iter = mPatches.find(patchHandle);
                 if (patch_iter != mPatches.end()) {
                     const Patch &patch = patch_iter->second;
-                    patches->emplace_back(*this, patchHandle,
+                    patches->emplace_back(sp<const IAfPatchPanel>::fromExisting(this),
+                            patchHandle,
                             patch.mPlayback.const_thread()->id(),
                             patch.mRecord.const_thread()->id());
                 } else {
@@ -849,7 +844,7 @@
     return BAD_VALUE;
 }
 
-void AudioFlinger::PatchPanel::notifyStreamOpened(
+void PatchPanel::notifyStreamOpened(
         AudioHwDevice *audioHwDevice, audio_io_handle_t stream, struct audio_patch *patch)
 {
     if (audioHwDevice->isInsert()) {
@@ -867,41 +862,41 @@
     }
 }
 
-void AudioFlinger::PatchPanel::notifyStreamClosed(audio_io_handle_t stream)
+void PatchPanel::notifyStreamClosed(audio_io_handle_t stream)
 {
     for (auto& module : mInsertedModules) {
         module.second.streams.erase(stream);
     }
 }
 
-AudioHwDevice* AudioFlinger::PatchPanel::findAudioHwDeviceByModule(audio_module_handle_t module)
+AudioHwDevice* PatchPanel::findAudioHwDeviceByModule(audio_module_handle_t module)
 {
     if (module == AUDIO_MODULE_HANDLE_NONE) return nullptr;
-    ssize_t index = mAudioFlinger.mAudioHwDevs.indexOfKey(module);
+    ssize_t index = mAfPatchPanelCallback->getAudioHwDevs_l().indexOfKey(module);
     if (index < 0) {
         ALOGW("%s() bad hw module %d", __func__, module);
         return nullptr;
     }
-    return mAudioFlinger.mAudioHwDevs.valueAt(index);
+    return mAfPatchPanelCallback->getAudioHwDevs_l().valueAt(index);
 }
 
-sp<DeviceHalInterface> AudioFlinger::PatchPanel::findHwDeviceByModule(audio_module_handle_t module)
+sp<DeviceHalInterface> PatchPanel::findHwDeviceByModule(audio_module_handle_t module)
 {
     AudioHwDevice *audioHwDevice = findAudioHwDeviceByModule(module);
     return audioHwDevice ? audioHwDevice->hwDevice() : nullptr;
 }
 
-void AudioFlinger::PatchPanel::addSoftwarePatchToInsertedModules(
+void PatchPanel::addSoftwarePatchToInsertedModules(
         audio_module_handle_t module, audio_patch_handle_t handle,
         const struct audio_patch *patch)
 {
     mInsertedModules[module].sw_patches.insert(handle);
     if (!mInsertedModules[module].streams.empty()) {
-        mAudioFlinger.updateDownStreamPatches_l(patch, mInsertedModules[module].streams);
+        mAfPatchPanelCallback->updateDownStreamPatches_l(patch, mInsertedModules[module].streams);
     }
 }
 
-void AudioFlinger::PatchPanel::removeSoftwarePatchFromInsertedModules(
+void PatchPanel::removeSoftwarePatchFromInsertedModules(
         audio_patch_handle_t handle)
 {
     for (auto& module : mInsertedModules) {
@@ -909,7 +904,7 @@
     }
 }
 
-void AudioFlinger::PatchPanel::dump(int fd) const
+void PatchPanel::dump(int fd) const
 {
     String8 patchPanelDump;
     const char *indent = "  ";
diff --git a/services/audioflinger/PatchPanel.h b/services/audioflinger/PatchPanel.h
index 2c5e47c..a95c601 100644
--- a/services/audioflinger/PatchPanel.h
+++ b/services/audioflinger/PatchPanel.h
@@ -15,217 +15,58 @@
 ** limitations under the License.
 */
 
-#ifndef INCLUDING_FROM_AUDIOFLINGER_H
-    #error This header file should only be included from AudioFlinger.h
-#endif
+#pragma once
 
-public: // TODO(b/288339104) extract out of AudioFlinger class
-// PatchPanel is concealed within AudioFlinger, their lifetimes are the same.
-class PatchPanel {
+#include "IAfPatchPanel.h"
+
+#include <map>  // avoid transitive dependency
+#include <set>  // avoid transitive dependency
+
+namespace android {
+
+class PatchPanel : public IAfPatchPanel {
 public:
-    class SoftwarePatch {
-      public:
-        SoftwarePatch(const PatchPanel &patchPanel, audio_patch_handle_t patchHandle,
-                audio_io_handle_t playbackThreadHandle, audio_io_handle_t recordThreadHandle)
-                : mPatchPanel(patchPanel), mPatchHandle(patchHandle),
-                  mPlaybackThreadHandle(playbackThreadHandle),
-                  mRecordThreadHandle(recordThreadHandle) {}
-        SoftwarePatch(const SoftwarePatch&) = default;
-
-        // Must be called under AudioFlinger::mLock
-        status_t getLatencyMs_l(double *latencyMs) const;
-        audio_patch_handle_t getPatchHandle() const { return mPatchHandle; };
-        audio_io_handle_t getPlaybackThreadHandle() const { return mPlaybackThreadHandle; };
-        audio_io_handle_t getRecordThreadHandle() const { return mRecordThreadHandle; };
-      private:
-        const PatchPanel &mPatchPanel;
-        const audio_patch_handle_t mPatchHandle;
-        const audio_io_handle_t mPlaybackThreadHandle;
-        const audio_io_handle_t mRecordThreadHandle;
-    };
-
-    explicit PatchPanel(AudioFlinger* audioFlinger) : mAudioFlinger(*audioFlinger) {}
+    explicit PatchPanel(const sp<IAfPatchPanelCallback>& afPatchPanelCallback)
+        : mAfPatchPanelCallback(afPatchPanelCallback) {}
 
     /* List connected audio ports and their attributes */
     status_t listAudioPorts(unsigned int *num_ports,
-                                    struct audio_port *ports);
+        struct audio_port* ports) final;
 
     /* Get supported attributes for a given audio port */
-    status_t getAudioPort(struct audio_port_v7 *port);
+    status_t getAudioPort(struct audio_port_v7* port) final;
 
     /* Create a patch between several source and sink ports */
     status_t createAudioPatch(const struct audio_patch *patch,
                               audio_patch_handle_t *handle,
-                              bool endpointPatch = false);
+                              bool endpointPatch = false) final;
 
     /* Release a patch */
-    status_t releaseAudioPatch(audio_patch_handle_t handle);
+    status_t releaseAudioPatch(audio_patch_handle_t handle) final;
 
     /* List connected audio devices and they attributes */
     status_t listAudioPatches(unsigned int *num_patches,
-                                      struct audio_patch *patches);
+            struct audio_patch* patches) final;
 
     // Retrieves all currently estrablished software patches for a stream
     // opened on an intermediate module.
     status_t getDownstreamSoftwarePatches(audio_io_handle_t stream,
-            std::vector<SoftwarePatch> *patches) const;
+            std::vector<SoftwarePatch>* patches) const final;
 
     // Notifies patch panel about all opened and closed streams.
     void notifyStreamOpened(AudioHwDevice *audioHwDevice, audio_io_handle_t stream,
-                            struct audio_patch *patch);
-    void notifyStreamClosed(audio_io_handle_t stream);
+                            struct audio_patch* patch) final;
+    void notifyStreamClosed(audio_io_handle_t stream) final;
 
-    void dump(int fd) const;
-
-    template<typename ThreadType, typename TrackType>
-    class Endpoint final {
-    public:
-        Endpoint() = default;
-        Endpoint(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);
-            return *this;
-        }
-        ~Endpoint() {
-            ALOGE_IF(mHandle != AUDIO_PATCH_HANDLE_NONE,
-                    "A non empty Patch Endpoint leaked, handle %d", mHandle);
-        }
-
-        status_t checkTrack(TrackType *trackOrNull) const {
-            if (trackOrNull == nullptr) return NO_MEMORY;
-            return trackOrNull->initCheck();
-        }
-        audio_patch_handle_t handle() const { return mHandle; }
-        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; }
-
-        void closeConnections(PatchPanel *panel) {
-            if (mHandle != AUDIO_PATCH_HANDLE_NONE) {
-                panel->releaseAudioPatch(mHandle);
-                mHandle = AUDIO_PATCH_HANDLE_NONE;
-            }
-            if (mThread != 0) {
-                if (mTrack != 0) {
-                    mThread->deletePatchTrack(mTrack);
-                }
-                if (mCloseThread) {
-                    panel->mAudioFlinger.closeThreadInternal_l(mThread);
-                }
-            }
-        }
-        audio_patch_handle_t* handlePtr() { return &mHandle; }
-        void setThread(const sp<ThreadType>& thread, bool closeThread = true) {
-            mThread = thread;
-            mCloseThread = closeThread;
-        }
-        template <typename T>
-        void setTrackAndPeer(const sp<TrackType>& track, const sp<T> &peer, bool holdReference) {
-            mTrack = track;
-            mThread->addPatchTrack(mTrack);
-            mTrack->setPeerProxy(peer, holdReference);
-            mClearPeerProxy = holdReference;
-        }
-        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);
-        }
-
-        friend void swap(Endpoint &a, Endpoint &b) noexcept {
-            a.swap(b);
-        }
-
-    private:
-        sp<ThreadType> mThread;
-        bool mCloseThread = true;
-        bool mClearPeerProxy = true;
-        audio_patch_handle_t mHandle = AUDIO_PATCH_HANDLE_NONE;
-        sp<TrackType> mTrack;
-    };
-
-    class Patch final {
-    public:
-        Patch(const struct audio_patch &patch, bool endpointPatch) :
-            mAudioPatch(patch), mIsEndpointPatch(endpointPatch) {}
-        Patch() = default;
-        ~Patch();
-        Patch(const Patch& other) noexcept {
-            mAudioPatch = other.mAudioPatch;
-            mHalHandle = other.mHalHandle;
-            mPlayback = other.mPlayback;
-            mRecord = other.mRecord;
-            mThread = other.mThread;
-            mIsEndpointPatch = other.mIsEndpointPatch;
-        }
-        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);
-            swap(mIsEndpointPatch, other.mIsEndpointPatch);
-        }
-
-        friend void swap(Patch &a, Patch &b) noexcept {
-            a.swap(b);
-        }
-
-        status_t createConnections(PatchPanel *panel);
-        void clearConnections(PatchPanel *panel);
-        bool isSoftware() const {
-            return mRecord.handle() != AUDIO_PATCH_HANDLE_NONE ||
-                    mPlayback.handle() != AUDIO_PATCH_HANDLE_NONE; }
-
-        void setThread(const 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;
-
-        String8 dump(audio_patch_handle_t myHandle) const;
-
-        // Note that audio_patch::id is only unique within a HAL module
-        struct audio_patch              mAudioPatch;
-        // handle for audio HAL patch handle present only when the audio HAL version is >= 3.0
-        audio_patch_handle_t            mHalHandle = AUDIO_PATCH_HANDLE_NONE;
-        // below members are used by a software audio patch connecting a source device from a
-        // given audio HW module to a sink device on an other audio HW module.
-        // the objects are created by createConnections() and released by clearConnections()
-        // playback thread is created if no existing playback thread can be used
-        // connects playback thread output to sink device
-        Endpoint<PlaybackThread, PlaybackThread::PatchTrack> mPlayback;
-        // connects source device to record thread input
-        Endpoint<RecordThread, RecordThread::PatchRecord> mRecord;
-
-        wp<ThreadBase> mThread;
-        bool mIsEndpointPatch;
-    };
+    void dump(int fd) const final;
 
     // Call with AudioFlinger mLock held
-    std::map<audio_patch_handle_t, Patch>& patches_l() { return mPatches; }
+    const std::map<audio_patch_handle_t, Patch>& patches_l() const final { return mPatches; }
+
+    // Must be called under AudioFlinger::mLock
+    status_t getLatencyMs_l(audio_patch_handle_t patchHandle, double* latencyMs) const final;
+
+    void closeThreadInternal_l(const sp<IAfThreadBase>& thread) const final;
 
 private:
     AudioHwDevice* findAudioHwDeviceByModule(audio_module_handle_t module);
@@ -234,9 +75,40 @@
             audio_module_handle_t module, audio_patch_handle_t handle,
             const struct audio_patch *patch);
     void removeSoftwarePatchFromInsertedModules(audio_patch_handle_t handle);
-    void erasePatch(audio_patch_handle_t handle);
+    /**
+     * erase the patch referred by its handle.
+     * @param handle of the patch to be erased
+     * @param reuseExistingHalPatch if set, do not trig the callback of listeners, listener
+     * would receive instead a onUpdateAudioPatch when the patch will be recreated.
+     * It prevents for example DeviceEffectManager to spuriously remove / add a device on an already
+     * opened input / output mix.
+     */
+    void erasePatch(audio_patch_handle_t handle, bool reuseExistingHalPatch = false);
 
-    AudioFlinger &mAudioFlinger;
+    /**
+     * Returns true if the old and new patches passed as arguments describe the same
+     * connections between the first sink and the first source
+     * @param oldPatch previous patch
+     * @param newPatch new patch
+     * @return true if the route is unchanged between the old and new patch, false otherwise
+     */
+    inline bool patchesHaveSameRoute(
+            const struct audio_patch &newPatch, const struct audio_patch &oldPatch) const {
+        return (newPatch.sources[0].type == AUDIO_PORT_TYPE_DEVICE &&
+                oldPatch.sources[0].type == AUDIO_PORT_TYPE_DEVICE &&
+                newPatch.sources[0].id == oldPatch.sources[0].id &&
+                newPatch.sinks[0].type == AUDIO_PORT_TYPE_MIX &&
+                oldPatch.sinks[0].type == AUDIO_PORT_TYPE_MIX &&
+                newPatch.sinks[0].ext.mix.handle == oldPatch.sinks[0].ext.mix.handle) ||
+                (newPatch.sinks[0].type == AUDIO_PORT_TYPE_DEVICE &&
+                oldPatch.sinks[0].type == AUDIO_PORT_TYPE_DEVICE &&
+                newPatch.sinks[0].id == oldPatch.sinks[0].id &&
+                newPatch.sources[0].type == AUDIO_PORT_TYPE_MIX &&
+                oldPatch.sources[0].type == AUDIO_PORT_TYPE_MIX &&
+                newPatch.sources[0].ext.mix.handle == oldPatch.sources[0].ext.mix.handle);
+    }
+
+    const sp<IAfPatchPanelCallback> mAfPatchPanelCallback;
     std::map<audio_patch_handle_t, Patch> mPatches;
 
     // This map allows going from a thread to "downstream" software patches
@@ -266,4 +138,4 @@
     std::map<audio_module_handle_t, ModuleConnections> mInsertedModules;
 };
 
-private:
+}  // namespace android
diff --git a/services/audioflinger/PlaybackTracks.h b/services/audioflinger/PlaybackTracks.h
index 99d36b8..978c4aa 100644
--- a/services/audioflinger/PlaybackTracks.h
+++ b/services/audioflinger/PlaybackTracks.h
@@ -15,12 +15,15 @@
 ** limitations under the License.
 */
 
-#ifndef INCLUDING_FROM_AUDIOFLINGER_H
-    #error This header file should only be included from AudioFlinger.h
-#endif
+#pragma once
 
-#include <math.h>
-#include <sys/types.h>
+#include "TrackBase.h"
+
+#include <android/os/BnExternalVibrationController.h>
+#include <audio_utils/LinearMap.h>
+#include <binder/AppOpsManager.h>
+
+namespace android {
 
 // Checks and monitors OP_PLAY_AUDIO
 class OpPlayAudioMonitor : public RefBase {
@@ -30,13 +33,13 @@
     bool hasOpPlayAudio() const;
 
     static sp<OpPlayAudioMonitor> createIfNeeded(
-            AudioFlinger::ThreadBase* thread,
+            IAfThreadBase* thread,
             const AttributionSourceState& attributionSource,
             const audio_attributes_t& attr, int id,
             audio_stream_type_t streamType);
 
 private:
-    OpPlayAudioMonitor(AudioFlinger::ThreadBase* thread,
+    OpPlayAudioMonitor(IAfThreadBase* thread,
                        const AttributionSourceState& attributionSource,
                        audio_usage_t usage, int id, uid_t uid);
     void onFirstRef() override;
@@ -57,7 +60,7 @@
     // called by PlayAudioOpCallback when OP_PLAY_AUDIO is updated in AppOp callback
     void checkPlayAudioForUsage();
 
-    wp<AudioFlinger::ThreadBase> mThread;
+    wp<IAfThreadBase> mThread;
     std::atomic_bool mHasOpPlayAudio;
     const AttributionSourceState mAttributionSource;
     const int32_t mUsage; // on purpose not audio_usage_t because always checked in appOps as int32_t
@@ -67,16 +70,9 @@
 };
 
 // playback track
-class Track : public TrackBase, public VolumeProvider {
+class Track : public TrackBase, public virtual IAfTrack, public VolumeProvider {
 public:
-    // createIAudioTrackAdapter() is a static constructor which creates an
-    // IAudioTrack AIDL interface adapter from the Track object that
-    // may be passed back to the client (if needed).
-    //
-    // Only one AIDL IAudioTrack interface wrapper should be created per Track.
-    static sp<media::IAudioTrack> createIAudioTrackAdapter(const sp<Track>& track);
-
-                        Track(  PlaybackThread *thread,
+    Track(IAfPlaybackThread* thread,
                                 const sp<Client>& client,
                                 audio_stream_type_t streamType,
                                 const audio_attributes_t& attr,
@@ -99,72 +95,66 @@
                                 float speed = 1.0f,
                                 bool isSpatialized = false,
                                 bool isBitPerfect = false);
-    virtual             ~Track();
-    virtual status_t    initCheck() const;
-
-            void        appendDumpHeader(String8& result);
-            void        appendDump(String8& result, bool active);
-    virtual status_t    start(AudioSystem::sync_event_t event = AudioSystem::SYNC_EVENT_NONE,
-                              audio_session_t triggerSession = AUDIO_SESSION_NONE);
-    virtual void        stop();
-            void        pause();
-
-            void        flush();
-            void        destroy();
-
-    virtual uint32_t    sampleRate() const;
-
-            audio_stream_type_t streamType() const {
+    ~Track() override;
+    status_t initCheck() const final;
+    void appendDumpHeader(String8& result) const final;
+    void appendDump(String8& result, bool active) const final;
+    status_t start(AudioSystem::sync_event_t event = AudioSystem::SYNC_EVENT_NONE,
+            audio_session_t triggerSession = AUDIO_SESSION_NONE) override;
+    void stop() override;
+    void pause() final;
+    void flush() final;
+    void destroy() final;
+    uint32_t sampleRate() const final;
+    audio_stream_type_t streamType() const final {
                 return mStreamType;
             }
-            bool        isOffloaded() const
+    bool isOffloaded() const final
                                 { return (mFlags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) != 0; }
-            bool        isDirect() const override
+    bool isDirect() const final
                                 { return (mFlags & AUDIO_OUTPUT_FLAG_DIRECT) != 0; }
-            bool        isOffloadedOrDirect() const { return (mFlags
+    bool isOffloadedOrDirect() const final { return (mFlags
                             & (AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD
                                     | AUDIO_OUTPUT_FLAG_DIRECT)) != 0; }
-            bool        isStatic() const { return  mSharedBuffer.get() != nullptr; }
+    bool isStatic() const final { return  mSharedBuffer.get() != nullptr; }
 
-            status_t    setParameters(const String8& keyValuePairs);
-            status_t    selectPresentation(int presentationId, int programId);
-            status_t    attachAuxEffect(int EffectId);
-            void        setAuxBuffer(int EffectId, int32_t *buffer);
-            int32_t     *auxBuffer() const { return mAuxBuffer; }
-            void        setMainBuffer(float *buffer) { mMainBuffer = buffer; }
-            float       *mainBuffer() const { return mMainBuffer; }
-            int         auxEffectId() const { return mAuxEffectId; }
-    virtual status_t    getTimestamp(AudioTimestamp& timestamp);
-            void        signal();
-            status_t    getDualMonoMode(audio_dual_mono_mode_t* mode);
-            status_t    setDualMonoMode(audio_dual_mono_mode_t mode);
-            status_t    getAudioDescriptionMixLevel(float* leveldB);
-            status_t    setAudioDescriptionMixLevel(float leveldB);
-            status_t    getPlaybackRateParameters(audio_playback_rate_t* playbackRate);
-            status_t    setPlaybackRateParameters(const audio_playback_rate_t& playbackRate);
+    status_t setParameters(const String8& keyValuePairs) final;
+    status_t selectPresentation(int presentationId, int programId) final;
+    status_t attachAuxEffect(int EffectId) final;
+    void setAuxBuffer(int EffectId, int32_t* buffer) final;
+    int32_t* auxBuffer() const final { return mAuxBuffer; }
+    void setMainBuffer(float* buffer) final { mMainBuffer = buffer; }
+    float* mainBuffer() const final { return mMainBuffer; }
+    int auxEffectId() const final { return mAuxEffectId; }
+    status_t getTimestamp(AudioTimestamp& timestamp) final;
+    void signal() final;
+    status_t getDualMonoMode(audio_dual_mono_mode_t* mode) const final;
+    status_t setDualMonoMode(audio_dual_mono_mode_t mode) final;
+    status_t getAudioDescriptionMixLevel(float* leveldB) const final;
+    status_t setAudioDescriptionMixLevel(float leveldB) final;
+    status_t getPlaybackRateParameters(audio_playback_rate_t* playbackRate) const final;
+    status_t setPlaybackRateParameters(const audio_playback_rate_t& playbackRate) final;
 
-// implement FastMixerState::VolumeProvider interface
-    virtual gain_minifloat_packed_t getVolumeLR();
+    // implement FastMixerState::VolumeProvider interface
+    gain_minifloat_packed_t getVolumeLR() const final;
 
-            status_t    setSyncEvent(const sp<audioflinger::SyncEvent>& event) override;
-
-    virtual bool        isFastTrack() const { return (mFlags & AUDIO_OUTPUT_FLAG_FAST) != 0; }
-
-            double      bufferLatencyMs() const override {
+    status_t setSyncEvent(const sp<audioflinger::SyncEvent>& event) final;
+    bool isFastTrack() const final { return (mFlags & AUDIO_OUTPUT_FLAG_FAST) != 0; }
+    double bufferLatencyMs() const final {
                             return isStatic() ? 0. : TrackBase::bufferLatencyMs();
                         }
 
-// implement volume handling.
+    // implement volume handling.
     media::VolumeShaper::Status applyVolumeShaper(
                                 const sp<media::VolumeShaper::Configuration>& configuration,
                                 const sp<media::VolumeShaper::Operation>& operation);
-    sp<media::VolumeShaper::State> getVolumeShaperState(int id);
-    sp<media::VolumeHandler>   getVolumeHandler() { return mVolumeHandler; }
+    sp<media::VolumeShaper::State> getVolumeShaperState(int id) const final;
+    sp<media::VolumeHandler> getVolumeHandler() const final{ return mVolumeHandler; }
     /** Set the computed normalized final volume of the track.
      * !masterMute * masterVolume * streamVolume * averageLRVolume */
-    void                setFinalVolume(float volumeLeft, float volumeRight);
-    float               getFinalVolume() const { return mFinalVolume; }
-    void                getFinalVolume(float* left, float* right) const {
+    void setFinalVolume(float volumeLeft, float volumeRight) final;
+    float getFinalVolume() const final { return mFinalVolume; }
+    void getFinalVolume(float* left, float* right) const final {
                             *left = mFinalVolumeLeft;
                             *right = mFinalVolumeRight;
     }
@@ -172,21 +162,22 @@
     using SourceMetadatas = std::vector<playback_track_metadata_v7_t>;
     using MetadataInserter = std::back_insert_iterator<SourceMetadatas>;
     /** Copy the track metadata in the provided iterator. Thread safe. */
-    virtual void    copyMetadataTo(MetadataInserter& backInserter) const;
+    void copyMetadataTo(MetadataInserter& backInserter) const override;
+
 
             /** Return haptic playback of the track is enabled or not, used in mixer. */
-            bool    getHapticPlaybackEnabled() const { return mHapticPlaybackEnabled; }
+    bool getHapticPlaybackEnabled() const final { return mHapticPlaybackEnabled; }
             /** Set haptic playback of the track is enabled or not, should be
              *  set after query or get callback from vibrator service */
-            void    setHapticPlaybackEnabled(bool hapticPlaybackEnabled) {
+    void setHapticPlaybackEnabled(bool hapticPlaybackEnabled) final {
                 mHapticPlaybackEnabled = hapticPlaybackEnabled;
             }
             /** Return at what intensity to play haptics, used in mixer. */
-            os::HapticScale getHapticIntensity() const { return mHapticIntensity; }
+    os::HapticScale getHapticIntensity() const final { return mHapticIntensity; }
             /** Return the maximum amplitude allowed for haptics data, used in mixer. */
-            float getHapticMaxAmplitude() const { return mHapticMaxAmplitude; }
+    float getHapticMaxAmplitude() const final { return mHapticMaxAmplitude; }
             /** Set intensity of haptic playback, should be set after querying vibrator service. */
-            void    setHapticIntensity(os::HapticScale hapticIntensity) {
+    void setHapticIntensity(os::HapticScale hapticIntensity) final {
                 if (os::isValidHapticScale(hapticIntensity)) {
                     mHapticIntensity = hapticIntensity;
                     setHapticPlaybackEnabled(mHapticIntensity != os::HapticScale::MUTE);
@@ -195,16 +186,16 @@
             /** Set maximum amplitude allowed for haptic data, should be set after querying
              *  vibrator service.
              */
-            void    setHapticMaxAmplitude(float maxAmplitude) {
+    void setHapticMaxAmplitude(float maxAmplitude) final {
                 mHapticMaxAmplitude = maxAmplitude;
             }
-            sp<os::ExternalVibration> getExternalVibration() const { return mExternalVibration; }
+    sp<os::ExternalVibration> getExternalVibration() const final { return mExternalVibration; }
 
             // This function should be called with holding thread lock.
-            void    updateTeePatches_l();
-            void    setTeePatchesToUpdate_l(TeePatches teePatchesToUpdate);
+    void updateTeePatches_l() final;
+    void setTeePatchesToUpdate_l(TeePatches teePatchesToUpdate) final;
 
-    void tallyUnderrunFrames(size_t frames) override {
+    void tallyUnderrunFrames(size_t frames) final {
        if (isOut()) { // we expect this from output tracks only
            mAudioTrackServerProxy->tallyUnderrunFrames(frames);
            // Fetch absolute numbers from AudioTrackShared as it counts
@@ -215,29 +206,18 @@
        }
     }
 
-    static bool checkServerLatencySupported(
-            audio_format_t format, audio_output_flags_t flags) {
-        return audio_is_linear_pcm(format)
-                && (flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC) == 0;
-    }
-
-    audio_output_flags_t getOutputFlags() const { return mFlags; }
-    float getSpeed() const { return mSpeed; }
-    bool isSpatialized() const override { return mIsSpatialized; }
-    bool isBitPerfect() const override { return mIsBitPerfect; }
+    audio_output_flags_t getOutputFlags() const final { return mFlags; }
+    float getSpeed() const final { return mSpeed; }
+    bool isSpatialized() const final { return mIsSpatialized; }
+    bool isBitPerfect() const final { return mIsBitPerfect; }
 
     /**
      * Updates the mute state and notifies the audio service. Call this only when holding player
      * thread lock.
      */
-    void processMuteEvent_l(const sp<IAudioManager>& audioManager, mute_state_t muteState);
+    void processMuteEvent_l(const sp<IAudioManager>& audioManager, mute_state_t muteState) final;
 
 protected:
-    // for numerous
-    friend class PlaybackThread;
-    friend class MixerThread;
-    friend class DirectOutputThread;
-    friend class OffloadThread;
 
     DISALLOW_COPY_AND_ASSIGN(Track);
 
@@ -246,38 +226,39 @@
     void releaseBuffer(AudioBufferProvider::Buffer* buffer) override;
 
     // ExtendedAudioBufferProvider interface
-    virtual size_t framesReady() const;
-    virtual int64_t framesReleased() const;
-    virtual void onTimestamp(const ExtendedTimestamp &timestamp);
+    size_t framesReady() const override;
+    int64_t framesReleased() const override;
+    void onTimestamp(const ExtendedTimestamp &timestamp) override;
 
-    bool isPausing() const { return mState == PAUSING; }
-    bool isPaused() const { return mState == PAUSED; }
-    bool isResuming() const { return mState == RESUMING; }
-    bool isReady() const;
-    void setPaused() { mState = PAUSED; }
-    void reset();
-    bool isFlushPending() const { return mFlushHwPending; }
-    void flushAck();
-    bool isResumePending();
-    void resumeAck();
+    // Used by thread
+    bool isPausing() const final { return mState == PAUSING; }
+    bool isPaused() const final { return mState == PAUSED; }
+    bool isResuming() const final { return mState == RESUMING; }
+    bool isReady() const final;
+    void setPaused() final { mState = PAUSED; }
+    void reset() final;
+    bool isFlushPending() const final { return mFlushHwPending; }
+    void flushAck() final;
+    bool isResumePending() const final;
+    void resumeAck() final;
     // For direct or offloaded tracks ensure that the pause state is acknowledged
     // by the playback thread in case of an immediate flush.
-    bool isPausePending() const { return mPauseHwPending; }
-    void pauseAck();
+    bool isPausePending() const final { return mPauseHwPending; }
+    void pauseAck() final;
     void updateTrackFrameInfo(int64_t trackFramesReleased, int64_t sinkFramesWritten,
-            uint32_t halSampleRate, const ExtendedTimestamp &timeStamp);
+            uint32_t halSampleRate, const ExtendedTimestamp& timeStamp) final;
 
-    sp<IMemory> sharedBuffer() const { return mSharedBuffer; }
+    sp<IMemory> sharedBuffer() const final { return mSharedBuffer; }
 
     // presentationComplete checked by frames. (Mixed Tracks).
     // framesWritten is cumulative, never reset, and is shared all tracks
     // audioHalFrames is derived from output latency
-    bool presentationComplete(int64_t framesWritten, size_t audioHalFrames);
+    bool presentationComplete(int64_t framesWritten, size_t audioHalFrames) final;
 
     // presentationComplete checked by time. (Direct Tracks).
-    bool presentationComplete(uint32_t latencyMs);
+    bool presentationComplete(uint32_t latencyMs) final;
 
-    void resetPresentationComplete() {
+    void resetPresentationComplete() final {
         mPresentationCompleteFrames = 0;
         mPresentationCompleteTimeNs = 0;
     }
@@ -288,25 +269,43 @@
 
     void signalClientFlag(int32_t flag);
 
-public:
-    void triggerEvents(AudioSystem::sync_event_t type);
-    virtual void invalidate();
-    void disable();
-
-    int fastIndex() const { return mFastIndex; }
-
-    bool isPlaybackRestricted() const {
+    void triggerEvents(AudioSystem::sync_event_t type) final;
+    void invalidate() final;
+    void disable() final;
+    int& fastIndex() final { return mFastIndex; }
+    bool isPlaybackRestricted() const final {
         // The monitor is only created for tracks that can be silenced.
         return mOpPlayAudioMonitor ? !mOpPlayAudioMonitor->hasOpPlayAudio() : false; }
 
-protected:
+    const sp<AudioTrackServerProxy>& audioTrackServerProxy() const final {
+        return mAudioTrackServerProxy;
+    }
+    bool hasVolumeController() const final { return mHasVolumeController; }
+    void setHasVolumeController(bool hasVolumeController) final {
+        mHasVolumeController = hasVolumeController;
+    }
+    void setCachedVolume(float volume) final {
+        mCachedVolume = volume;
+    }
+    void setResetDone(bool resetDone) final {
+        mResetDone = resetDone;
+    }
+    ExtendedAudioBufferProvider* asExtendedAudioBufferProvider() final {
+        return this;
+    }
+    VolumeProvider* asVolumeProvider() final {
+        return this;
+    }
 
-    // FILLED state is used for suppressing volume ramp at begin of playing
-    enum {FS_INVALID, FS_FILLING, FS_FILLED, FS_ACTIVE};
-    mutable uint8_t     mFillingUpStatus;
+    FillingStatus& fillingStatus() final { return mFillingStatus; }
+    int8_t& retryCount() final { return mRetryCount; }
+    FastTrackUnderruns& fastTrackUnderruns() final { return mObservedUnderruns; }
+
+protected:
+    mutable FillingStatus mFillingStatus;
     int8_t              mRetryCount;
 
-    // see comment at AudioFlinger::PlaybackThread::Track::~Track for why this can't be const
+    // see comment at ~Track for why this can't be const
     sp<IMemory>         mSharedBuffer;
 
     bool                mResetDone;
@@ -385,7 +384,7 @@
     bool                mFlushHwPending; // track requests for thread flush
     bool                mPauseHwPending = false; // direct/offload track request for thread pause
     audio_output_flags_t mFlags;
-    TeePatches  mTeePatches;
+    TeePatches mTeePatches;
     std::optional<TeePatches> mTeePatchesToUpdate;
     const float         mSpeed;
     const bool          mIsSpatialized;
@@ -399,7 +398,7 @@
 
 
 // playback track, used by DuplicatingThread
-class OutputTrack : public Track {
+class OutputTrack : public Track, public IAfOutputTrack {
 public:
 
     class Buffer : public AudioBufferProvider::Buffer {
@@ -407,29 +406,28 @@
         void *mBuffer;
     };
 
-                        OutputTrack(PlaybackThread *thread,
-                                DuplicatingThread *sourceThread,
+    OutputTrack(IAfPlaybackThread* thread,
+            IAfDuplicatingThread* sourceThread,
                                 uint32_t sampleRate,
                                 audio_format_t format,
                                 audio_channel_mask_t channelMask,
                                 size_t frameCount,
                                 const AttributionSourceState& attributionSource);
-    virtual             ~OutputTrack();
+    ~OutputTrack() override;
 
-    virtual status_t    start(AudioSystem::sync_event_t event =
+    status_t start(AudioSystem::sync_event_t event =
                                     AudioSystem::SYNC_EVENT_NONE,
-                             audio_session_t triggerSession = AUDIO_SESSION_NONE);
-    virtual void        stop();
-            ssize_t     write(void* data, uint32_t frames);
-            bool        bufferQueueEmpty() const { return mBufferQueue.size() == 0; }
-            bool        isActive() const { return mActive; }
-    const wp<ThreadBase>& thread() const { return mThread; }
+                             audio_session_t triggerSession = AUDIO_SESSION_NONE) final;
+    void stop() final;
+    ssize_t write(void* data, uint32_t frames) final;
+    bool bufferQueueEmpty() const final { return mBufferQueue.size() == 0; }
+    bool isActive() const final { return mActive; }
 
-            void        copyMetadataTo(MetadataInserter& backInserter) const override;
+    void copyMetadataTo(MetadataInserter& backInserter) const final;
     /** Set the metadatas of the upstream tracks. Thread safe. */
-            void        setMetadatas(const SourceMetadatas& metadatas);
+    void setMetadatas(const SourceMetadatas& metadatas) final;
     /** returns client timestamp to the upstream duplicating thread. */
-    ExtendedTimestamp   getClientProxyTimestamp() const {
+    ExtendedTimestamp getClientProxyTimestamp() const final {
                             // server - kernel difference is not true latency when drained
                             // i.e. mServerProxy->isDrained().
                             ExtendedTimestamp timestamp;
@@ -440,7 +438,6 @@
                             // (with mTimeNs[] filled with -1's) is returned.
                             return timestamp;
                         }
-
 private:
     status_t            obtainBuffer(AudioBufferProvider::Buffer* buffer,
                                      uint32_t waitTimeMs);
@@ -455,7 +452,7 @@
     Vector < Buffer* >          mBufferQueue;
     AudioBufferProvider::Buffer mOutBuffer;
     bool                        mActive;
-    DuplicatingThread* const    mSourceThread; // for waitTimeMs() in write()
+    IAfDuplicatingThread* const mSourceThread; // for waitTimeMs() in write()
     sp<AudioTrackClientProxy>   mClientProxy;
 
     /** Attributes of the source tracks.
@@ -475,10 +472,9 @@
 };  // end of OutputTrack
 
 // playback track, used by PatchPanel
-class PatchTrack : public Track, public PatchTrackBase {
+class PatchTrack : public Track, public PatchTrackBase, public IAfPatchTrack {
 public:
-
-                        PatchTrack(PlaybackThread *playbackThread,
+    PatchTrack(IAfPlaybackThread* playbackThread,
                                    audio_stream_type_t streamType,
                                    uint32_t sampleRate,
                                    audio_channel_mask_t channelMask,
@@ -492,23 +488,24 @@
                                                                     *  as soon as possible to have
                                                                     *  the lowest possible latency
                                                                     *  even if it might glitch. */);
-    virtual             ~PatchTrack();
+    ~PatchTrack() override;
 
-            size_t      framesReady() const override;
+    size_t framesReady() const final;
 
-    virtual status_t    start(AudioSystem::sync_event_t event =
+    status_t start(AudioSystem::sync_event_t event =
                                     AudioSystem::SYNC_EVENT_NONE,
-                             audio_session_t triggerSession = AUDIO_SESSION_NONE);
+                             audio_session_t triggerSession = AUDIO_SESSION_NONE) final;
 
     // AudioBufferProvider interface
-    virtual status_t getNextBuffer(AudioBufferProvider::Buffer* buffer);
-    virtual void releaseBuffer(AudioBufferProvider::Buffer* buffer);
+    status_t getNextBuffer(AudioBufferProvider::Buffer* buffer) final;
+    void releaseBuffer(AudioBufferProvider::Buffer* buffer) final;
 
     // PatchProxyBufferProvider interface
-    virtual status_t    obtainBuffer(Proxy::Buffer* buffer,
-                                     const struct timespec *timeOut = NULL);
-    virtual void        releaseBuffer(Proxy::Buffer* buffer);
+    status_t obtainBuffer(Proxy::Buffer* buffer, const struct timespec* timeOut = nullptr) final;
+    void releaseBuffer(Proxy::Buffer* buffer) final;
 
 private:
             void restartIfDisabled();
 };  // end of PatchTrack
+
+} // namespace android
diff --git a/services/audioflinger/RecordTracks.h b/services/audioflinger/RecordTracks.h
index 61f36a1..021add4 100644
--- a/services/audioflinger/RecordTracks.h
+++ b/services/audioflinger/RecordTracks.h
@@ -15,23 +15,19 @@
 ** limitations under the License.
 */
 
-#include <android/content/AttributionSourceState.h>
+#pragma once
 
-#ifndef INCLUDING_FROM_AUDIOFLINGER_H
-    #error This header file should only be included from AudioFlinger.h
-#endif
+#include "TrackBase.h"
+
+#include <android/content/AttributionSourceState.h>
+#include <datapath/AudioStreamIn.h> // struct Source
+
+namespace android {
 
 // record track
-class RecordTrack : public TrackBase {
+class RecordTrack : public TrackBase, public virtual IAfRecordTrack {
 public:
-    // createIAudioRecordAdapter() is a static constructor which creates an
-    // IAudioRecord AIDL interface wrapper from the RecordTrack object that
-    // may be passed back to the client (if needed).
-    //
-    // Only one AIDL IAudioRecord interface wrapper should be created per RecordTrack.
-    static sp<media::IAudioRecord> createIAudioRecordAdapter(const sp<RecordTrack>& recordTrack);
-
-                        RecordTrack(RecordThread *thread,
+    RecordTrack(IAfRecordThread* thread,
                                 const sp<Client>& client,
                                 const audio_attributes_t& attr,
                                 uint32_t sampleRate,
@@ -47,67 +43,70 @@
                                 track_type type,
                                 audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE,
                                 int32_t startFrames = -1);
-    virtual             ~RecordTrack();
-    virtual status_t    initCheck() const;
+    ~RecordTrack() override;
+    status_t initCheck() const final;
 
-    virtual status_t    start(AudioSystem::sync_event_t event, audio_session_t triggerSession);
-    virtual void        stop();
+    status_t start(AudioSystem::sync_event_t event, audio_session_t triggerSession) final;
+    void stop() final;
+    void destroy() final;
+    void invalidate() final;
 
-            void        destroy();
-
-    virtual void        invalidate();
             // clear the buffer overflow flag
-            void        clearOverflow() { mOverflow = false; }
+    void clearOverflow() final { mOverflow = false; }
             // set the buffer overflow flag and return previous value
-            bool        setOverflow() { bool tmp = mOverflow; mOverflow = true;
+    bool setOverflow() final { bool tmp = mOverflow; mOverflow = true;
                                                 return tmp; }
 
-            void        appendDumpHeader(String8& result);
-            void        appendDump(String8& result, bool active);
+    void appendDumpHeader(String8& result) const final;
+    void appendDump(String8& result, bool active) const final;
 
-            void        handleSyncStartEvent(const sp<audioflinger::SyncEvent>& event);
-            void        clearSyncStartEvent();
+    void handleSyncStartEvent(const sp<audioflinger::SyncEvent>& event) final;
+    void clearSyncStartEvent() final;
 
-            void        updateTrackFrameInfo(int64_t trackFramesReleased,
+    void updateTrackFrameInfo(int64_t trackFramesReleased,
                                              int64_t sourceFramesRead,
                                              uint32_t halSampleRate,
-                                             const ExtendedTimestamp &timestamp);
+                                             const ExtendedTimestamp &timestamp) final;
 
-    virtual bool        isFastTrack() const { return (mFlags & AUDIO_INPUT_FLAG_FAST) != 0; }
-            bool        isDirect() const override
+    bool isFastTrack() const final { return (mFlags & AUDIO_INPUT_FLAG_FAST) != 0; }
+    bool isDirect() const final
                                 { return (mFlags & AUDIO_INPUT_FLAG_DIRECT) != 0; }
 
-            void        setSilenced(bool silenced) { if (!isPatchTrack()) mSilenced = silenced; }
-            bool        isSilenced() const { return mSilenced; }
+    void setSilenced(bool silenced) final { if (!isPatchTrack()) mSilenced = silenced; }
+    bool isSilenced() const final { return mSilenced; }
 
-            status_t    getActiveMicrophones(
-                    std::vector<media::MicrophoneInfoFw>* activeMicrophones);
+    status_t getActiveMicrophones(
+            std::vector<media::MicrophoneInfoFw>* activeMicrophones) const final;
 
-            status_t    setPreferredMicrophoneDirection(audio_microphone_direction_t direction);
-            status_t    setPreferredMicrophoneFieldDimension(float zoom);
-            status_t    shareAudioHistory(const std::string& sharedAudioPackageName,
-                                          int64_t sharedAudioStartMs);
-            int32_t     startFrames() { return mStartFrames; }
+    status_t setPreferredMicrophoneDirection(audio_microphone_direction_t direction) final;
+    status_t setPreferredMicrophoneFieldDimension(float zoom) final;
+    status_t shareAudioHistory(const std::string& sharedAudioPackageName,
+            int64_t sharedAudioStartMs) final;
+    int32_t startFrames() const final { return mStartFrames; }
 
-    static  bool        checkServerLatencySupported(
-                                audio_format_t format, audio_input_flags_t flags) {
-                            return audio_is_linear_pcm(format)
-                                    && (flags & AUDIO_INPUT_FLAG_HW_AV_SYNC) == 0;
-                        }
+    using SinkMetadatas = std::vector<record_track_metadata_v7_t>;
+    using MetadataInserter = std::back_insert_iterator<SinkMetadatas>;
+    void copyMetadataTo(MetadataInserter& backInserter) const final;
 
-            using SinkMetadatas = std::vector<record_track_metadata_v7_t>;
-            using MetadataInserter = std::back_insert_iterator<SinkMetadatas>;
-            virtual void    copyMetadataTo(MetadataInserter& backInserter) const;
+    AudioBufferProvider::Buffer& sinkBuffer() final { return mSink; }
+    audioflinger::SynchronizedRecordState& synchronizedRecordState() final {
+        return mSynchronizedRecordState;
+    }
+    RecordBufferConverter* recordBufferConverter() const final { return mRecordBufferConverter; }
+    ResamplerBufferProvider* resamplerBufferProvider() const final {
+        return mResamplerBufferProvider;
+    }
 
 private:
-    friend class AudioFlinger;  // for mState
-
     DISALLOW_COPY_AND_ASSIGN(RecordTrack);
 
+protected:
     // AudioBufferProvider interface
-    virtual status_t getNextBuffer(AudioBufferProvider::Buffer* buffer);
+    status_t getNextBuffer(AudioBufferProvider::Buffer* buffer) override;
     // releaseBuffer() not overridden
 
+private:
+
     bool                mOverflow;  // overflow on most recent attempt to fill client buffer
 
             AudioBufferProvider::Buffer mSink;  // references client's buffer sink in shared memory
@@ -120,7 +119,7 @@
                     mSynchronizedRecordState{mSampleRate}; // sampleRate defined in base
 
             // used by resampler to find source frames
-            ResamplerBufferProvider            *mResamplerBufferProvider;
+            ResamplerBufferProvider* mResamplerBufferProvider;
 
             // used by the record thread to convert frames to proper destination format
             RecordBufferConverter              *mRecordBufferConverter;
@@ -133,10 +132,9 @@
 };
 
 // playback track, used by PatchPanel
-class PatchRecord : public RecordTrack, public PatchTrackBase {
+class PatchRecord : public RecordTrack, public PatchTrackBase, public IAfPatchRecord {
 public:
-
-    PatchRecord(RecordThread *recordThread,
+    PatchRecord(IAfRecordThread* recordThread,
                 uint32_t sampleRate,
                 audio_channel_mask_t channelMask,
                 audio_format_t format,
@@ -146,20 +144,20 @@
                 audio_input_flags_t flags,
                 const Timeout& timeout = {},
                 audio_source_t source = AUDIO_SOURCE_DEFAULT);
-    virtual             ~PatchRecord();
+    ~PatchRecord() override;
 
-    virtual Source* getSource() { return nullptr; }
+    Source* getSource() override { return nullptr; }
 
     // AudioBufferProvider interface
-    virtual status_t getNextBuffer(AudioBufferProvider::Buffer* buffer);
-    virtual void releaseBuffer(AudioBufferProvider::Buffer* buffer);
+    status_t getNextBuffer(AudioBufferProvider::Buffer* buffer) override;
+    void releaseBuffer(AudioBufferProvider::Buffer* buffer) override;
 
     // PatchProxyBufferProvider interface
-    virtual status_t    obtainBuffer(Proxy::Buffer *buffer,
-                                     const struct timespec *timeOut = NULL);
-    virtual void        releaseBuffer(Proxy::Buffer *buffer);
+    status_t obtainBuffer(Proxy::Buffer* buffer,
+                                     const struct timespec* timeOut = nullptr) override;
+    void releaseBuffer(Proxy::Buffer* buffer) override;
 
-    size_t writeFrames(const void* src, size_t frameCount, size_t frameSize) {
+    size_t writeFrames(const void* src, size_t frameCount, size_t frameSize) final {
         return writeFrames(this, src, frameCount, frameSize);
     }
 
@@ -172,7 +170,7 @@
 
 class PassthruPatchRecord : public PatchRecord, public Source {
 public:
-    PassthruPatchRecord(RecordThread *recordThread,
+    PassthruPatchRecord(IAfRecordThread* recordThread,
                         uint32_t sampleRate,
                         audio_channel_mask_t channelMask,
                         audio_format_t format,
@@ -180,25 +178,25 @@
                         audio_input_flags_t flags,
                         audio_source_t source = AUDIO_SOURCE_DEFAULT);
 
-    Source* getSource() override { return static_cast<Source*>(this); }
+    Source* getSource() final { 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;
+    status_t read(void* buffer, size_t bytes, size_t* read) final;
+    status_t getCapturePosition(int64_t* frames, int64_t* time) final;
+    status_t standby() final;
 
     // 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;
+    status_t getNextBuffer(AudioBufferProvider::Buffer* buffer) final;
+    void releaseBuffer(AudioBufferProvider::Buffer* buffer) final;
 
     // 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;
+    bool producesBufferOnDemand() const final { return true; }
+    status_t obtainBuffer(Proxy::Buffer* buffer, const struct timespec* timeOut = nullptr) final;
+    void releaseBuffer(Proxy::Buffer* buffer) final;
 
 private:
     // This is to use with PatchRecord::writeFrames
@@ -215,7 +213,7 @@
         PassthruPatchRecord& mPassthru;
     };
 
-    sp<StreamInHalInterface> obtainStream(sp<ThreadBase>* thread);
+    sp<StreamInHalInterface> obtainStream(sp<IAfThreadBase>* thread);
 
     PatchRecordAudioBufferProvider mPatchRecordAudioBufferProvider;
     std::unique_ptr<void, decltype(free)*> mSinkBuffer;  // frame size aligned continuous buffer
@@ -227,3 +225,5 @@
     status_t mReadError = NO_ERROR; // GUARDED_BY(mReadLock)
     int64_t mLastReadFrames = 0;  // accessed on RecordThread only
 };
+
+} // namespace android
diff --git a/services/audioflinger/ResamplerBufferProvider.h b/services/audioflinger/ResamplerBufferProvider.h
new file mode 100644
index 0000000..b697743
--- /dev/null
+++ b/services/audioflinger/ResamplerBufferProvider.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+namespace android {
+
+class IAfRecordTrack;
+
+/* The ResamplerBufferProvider is used to retrieve recorded input data from the
+ * RecordThread.  It maintains local state on the relative position of the read
+ * position of the RecordTrack compared with the RecordThread.
+ */
+class ResamplerBufferProvider : public AudioBufferProvider
+{
+public:
+    explicit ResamplerBufferProvider(IAfRecordTrack* recordTrack) :
+        mRecordTrack(recordTrack) {}
+
+    // called to set the ResamplerBufferProvider to head of the RecordThread data buffer,
+    // skipping any previous data read from the hal.
+    void reset();
+
+    /* Synchronizes RecordTrack position with the RecordThread.
+     * Calculates available frames and handle overruns if the RecordThread
+     * has advanced faster than the ResamplerBufferProvider has retrieved data.
+     * TODO: why not do this for every getNextBuffer?
+     *
+     * Parameters
+     * framesAvailable:  pointer to optional output size_t to store record track
+     *                   frames available.
+     *      hasOverrun:  pointer to optional boolean, returns true if track has overrun.
+     */
+
+    void sync(size_t* framesAvailable = nullptr, bool* hasOverrun = nullptr);
+
+    // AudioBufferProvider interface
+    status_t getNextBuffer(AudioBufferProvider::Buffer* buffer) final;
+    void releaseBuffer(AudioBufferProvider::Buffer* buffer) final;
+
+    int32_t getFront() const { return mRsmpInFront; }
+    void setFront(int32_t front) { mRsmpInFront = front; }
+
+private:
+    IAfRecordTrack* const mRecordTrack;
+    size_t mRsmpInUnrel = 0;   // unreleased frames remaining from
+                               // most recent getNextBuffer
+                               // for debug only
+    int32_t mRsmpInFront = 0;  // next available frame
+                               // rolling counter that is never cleared
+};
+
+} // namespace android
\ No newline at end of file
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index af15cfc..575bcf9 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -20,45 +20,49 @@
 // #define LOG_NDEBUG 0
 #define ATRACE_TAG ATRACE_TAG_AUDIO
 
-#include "Configuration.h"
-#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 "Threads.h"
+
+#include "Client.h"
+#include "IAfEffect.h"
+#include "MelReporter.h"
+#include "ResamplerBufferProvider.h"
+
+#include <afutils/DumpTryLock.h>
+#include <afutils/Permission.h>
+#include <afutils/TypedLogger.h>
+#include <afutils/Vibrator.h>
+#include <audio_utils/MelProcessor.h>
+#include <audio_utils/Metadata.h>
+#ifdef DEBUG_CPU_USAGE
+#include <audio_utils/Statistics.h>
+#include <cpustats/ThreadCpuUsage.h>
+#endif
+#include <audio_utils/channels.h>
+#include <audio_utils/format.h>
+#include <audio_utils/minifloat.h>
+#include <audio_utils/mono_blend.h>
+#include <audio_utils/primitives.h>
+#include <audio_utils/safe_math.h>
+#include <audiomanager/AudioManager.h>
+#include <binder/IPCThreadState.h>
+#include <binder/IServiceManager.h>
+#include <binder/PersistableBundle.h>
 #include <cutils/bitops.h>
 #include <cutils/properties.h>
-#include <binder/PersistableBundle.h>
+#include <fastpath/AutoPark.h>
 #include <media/AudioContainers.h>
 #include <media/AudioDeviceTypeAddr.h>
 #include <media/AudioParameter.h>
 #include <media/AudioResamplerPublic.h>
+#ifdef ADD_BATTERY_DATA
+#include <media/IMediaPlayerService.h>
+#include <media/IMediaDeathNotifier.h>
+#endif
+#include <media/MmapStreamCallback.h>
 #include <media/RecordBufferConverter.h>
 #include <media/TypeConverter.h>
-#include <utils/Log.h>
-#include <utils/Trace.h>
-
-#include <private/media/AudioTrackShared.h>
-#include <private/android_filesystem_config.h>
-#include <audio_utils/Balance.h>
-#include <audio_utils/MelProcessor.h>
-#include <audio_utils/Metadata.h>
-#include <audio_utils/channels.h>
-#include <audio_utils/mono_blend.h>
-#include <audio_utils/primitives.h>
-#include <audio_utils/format.h>
-#include <audio_utils/minifloat.h>
-#include <audio_utils/safe_math.h>
-#include <system/audio_effects/effect_aec.h>
-#include <system/audio_effects/effect_downmix.h>
-#include <system/audio_effects/effect_ns.h>
-#include <system/audio_effects/effect_spatializer.h>
-#include <system/audio.h>
-
-// NBAIO implementations
+#include <media/audiohal/EffectsFactoryHalInterface.h>
+#include <media/audiohal/StreamHalInterface.h>
 #include <media/nbaio/AudioStreamInSource.h>
 #include <media/nbaio/AudioStreamOutSink.h>
 #include <media/nbaio/MonoPipe.h>
@@ -68,31 +72,27 @@
 #include <media/nbaio/SourceAudioBufferProvider.h>
 #include <mediautils/BatteryNotifier.h>
 #include <mediautils/Process.h>
-
-#include <audiomanager/AudioManager.h>
-#include <powermanager/PowerManager.h>
-
-#include <media/audiohal/EffectsFactoryHalInterface.h>
-#include <media/audiohal/StreamHalInterface.h>
-
-#include "AudioFlinger.h"
 #include <mediautils/SchedulingPolicyService.h>
 #include <mediautils/ServiceUtilities.h>
+#include <powermanager/PowerManager.h>
+#include <private/android_filesystem_config.h>
+#include <private/media/AudioTrackShared.h>
+#include <system/audio_effects/effect_aec.h>
+#include <system/audio_effects/effect_downmix.h>
+#include <system/audio_effects/effect_ns.h>
+#include <system/audio_effects/effect_spatializer.h>
+#include <utils/Log.h>
+#include <utils/Trace.h>
 
-#ifdef ADD_BATTERY_DATA
-#include <media/IMediaPlayerService.h>
-#include <media/IMediaDeathNotifier.h>
-#endif
-
-#ifdef DEBUG_CPU_USAGE
-#include <audio_utils/Statistics.h>
-#include <cpustats/ThreadCpuUsage.h>
-#endif
-
-#include <fastpath/AutoPark.h>
-
+#include <fcntl.h>
+#include <linux/futex.h>
+#include <math.h>
+#include <memory>
 #include <pthread.h>
-#include <afutils/TypedLogger.h>
+#include <sstream>
+#include <string>
+#include <sys/stat.h>
+#include <sys/syscall.h>
 
 // ----------------------------------------------------------------------------
 
@@ -120,9 +120,13 @@
 
 namespace android {
 
+using audioflinger::SyncEvent;
 using media::IEffectClient;
 using content::AttributionSourceState;
 
+// Keep in sync with java definition in media/java/android/media/AudioRecord.java
+static constexpr int32_t kMaxSharedAudioHistoryMs = 5000;
+
 // retry counts for buffer fill timeout
 // 50 * ~20msecs = 1 second
 static const int8_t kMaxTrackRetries = 50;
@@ -239,8 +243,84 @@
 // and that all "fast" AudioRecord clients read from.  In either case, the size can be small.
 static const size_t kRecordThreadReadOnlyHeapSize = 0xD000;
 
+static const nsecs_t kDefaultStandbyTimeInNsecs = seconds(3);
+
+static nsecs_t getStandbyTimeInNanos() {
+    static nsecs_t standbyTimeInNanos = []() {
+        const int ms = property_get_int32("ro.audio.flinger_standbytime_ms",
+                    kDefaultStandbyTimeInNsecs / NANOS_PER_MILLISECOND);
+        ALOGI("%s: Using %d ms as standby time", __func__, ms);
+        return milliseconds(ms);
+    }();
+    return standbyTimeInNanos;
+}
+
+// Set kEnableExtendedChannels to true to enable greater than stereo output
+// for the MixerThread and device sink.  Number of channels allowed is
+// FCC_2 <= channels <= FCC_LIMIT.
+constexpr bool kEnableExtendedChannels = true;
+
+// Returns true if channel mask is permitted for the PCM sink in the MixerThread
+/* static */
+bool IAfThreadBase::isValidPcmSinkChannelMask(audio_channel_mask_t channelMask) {
+    switch (audio_channel_mask_get_representation(channelMask)) {
+    case AUDIO_CHANNEL_REPRESENTATION_POSITION: {
+        // Haptic channel mask is only applicable for channel position mask.
+        const uint32_t channelCount = audio_channel_count_from_out_mask(
+                static_cast<audio_channel_mask_t>(channelMask & ~AUDIO_CHANNEL_HAPTIC_ALL));
+        const uint32_t maxChannelCount = kEnableExtendedChannels
+                ? FCC_LIMIT : FCC_2;
+        if (channelCount < FCC_2 // mono is not supported at this time
+                || channelCount > maxChannelCount) {
+            return false;
+        }
+        // check that channelMask is the "canonical" one we expect for the channelCount.
+        return audio_channel_position_mask_is_out_canonical(channelMask);
+        }
+    case AUDIO_CHANNEL_REPRESENTATION_INDEX:
+        if (kEnableExtendedChannels) {
+            const uint32_t channelCount = audio_channel_count_from_out_mask(channelMask);
+            if (channelCount >= FCC_2 // mono is not supported at this time
+                    && channelCount <= FCC_LIMIT) {
+                return true;
+            }
+        }
+        return false;
+    default:
+        return false;
+    }
+}
+
+// Set kEnableExtendedPrecision to true to use extended precision in MixerThread
+constexpr bool kEnableExtendedPrecision = true;
+
+// Returns true if format is permitted for the PCM sink in the MixerThread
+/* static */
+bool IAfThreadBase::isValidPcmSinkFormat(audio_format_t format) {
+    switch (format) {
+    case AUDIO_FORMAT_PCM_16_BIT:
+        return true;
+    case AUDIO_FORMAT_PCM_FLOAT:
+    case AUDIO_FORMAT_PCM_24_BIT_PACKED:
+    case AUDIO_FORMAT_PCM_32_BIT:
+    case AUDIO_FORMAT_PCM_8_24_BIT:
+        return kEnableExtendedPrecision;
+    default:
+        return false;
+    }
+}
+
 // ----------------------------------------------------------------------------
 
+// formatToString() needs to be exact for MediaMetrics purposes.
+// Do not use media/TypeConverter.h toString().
+/* static */
+std::string IAfThreadBase::formatToString(audio_format_t format) {
+    std::string result;
+    FormatConverter::toString(format, result);
+    return result;
+}
+
 // TODO: move all toString helpers to audio.h
 // under  #ifdef __cplusplus #endif
 static std::string patchSinksToString(const struct audio_patch *patch)
@@ -515,7 +595,7 @@
 // ----------------------------------------------------------------------------
 
 // static
-const char *AudioFlinger::ThreadBase::threadTypeToString(AudioFlinger::ThreadBase::type_t type)
+const char* ThreadBase::threadTypeToString(ThreadBase::type_t type)
 {
     switch (type) {
     case MIXER:
@@ -541,11 +621,11 @@
     }
 }
 
-AudioFlinger::ThreadBase::ThreadBase(const sp<AudioFlinger>& audioFlinger, audio_io_handle_t id,
+ThreadBase::ThreadBase(const sp<IAfThreadCallback>& afThreadCallback, audio_io_handle_t id,
         type_t type, bool systemReady, bool isOut)
     :   Thread(false /*canCallJava*/),
         mType(type),
-        mAudioFlinger(audioFlinger),
+        mAfThreadCallback(afThreadCallback),
         mThreadMetrics(std::string(AMEDIAMETRICS_KEY_PREFIX_AUDIO_THREAD) + std::to_string(id),
                isOut),
         mIsOut(isOut),
@@ -564,7 +644,7 @@
     memset(&mPatch, 0, sizeof(struct audio_patch));
 }
 
-AudioFlinger::ThreadBase::~ThreadBase()
+ThreadBase::~ThreadBase()
 {
     // mConfigEvents should be empty, but just in case it isn't, free the memory it owns
     mConfigEvents.clear();
@@ -579,7 +659,7 @@
     sendStatistics(true /* force */);
 }
 
-status_t AudioFlinger::ThreadBase::readyToRun()
+status_t ThreadBase::readyToRun()
 {
     status_t status = initCheck();
     if (status == NO_ERROR) {
@@ -590,7 +670,7 @@
     return status;
 }
 
-void AudioFlinger::ThreadBase::exit()
+void ThreadBase::exit()
 {
     ALOGV("ThreadBase::exit");
     // do any cleanup required for exit to succeed
@@ -614,7 +694,7 @@
     requestExitAndWait();
 }
 
-status_t AudioFlinger::ThreadBase::setParameters(const String8& keyValuePairs)
+status_t ThreadBase::setParameters(const String8& keyValuePairs)
 {
     ALOGV("ThreadBase::setParameters() %s", keyValuePairs.string());
     Mutex::Autolock _l(mLock);
@@ -624,7 +704,7 @@
 
 // sendConfigEvent_l() must be called with ThreadBase::mLock held
 // Can temporarily release the lock if waiting for a reply from processConfigEvents_l().
-status_t AudioFlinger::ThreadBase::sendConfigEvent_l(sp<ConfigEvent>& event)
+status_t ThreadBase::sendConfigEvent_l(sp<ConfigEvent>& event)
 NO_THREAD_SAFETY_ANALYSIS  // condition variable
 {
     status_t status = NO_ERROR;
@@ -652,7 +732,7 @@
     return status;
 }
 
-void AudioFlinger::ThreadBase::sendIoConfigEvent(audio_io_config_event_t event, pid_t pid,
+void ThreadBase::sendIoConfigEvent(audio_io_config_event_t event, pid_t pid,
                                                  audio_port_handle_t portId)
 {
     Mutex::Autolock _l(mLock);
@@ -660,7 +740,7 @@
 }
 
 // sendIoConfigEvent_l() must be called with ThreadBase::mLock held
-void AudioFlinger::ThreadBase::sendIoConfigEvent_l(audio_io_config_event_t event, pid_t pid,
+void ThreadBase::sendIoConfigEvent_l(audio_io_config_event_t event, pid_t pid,
                                                    audio_port_handle_t portId)
 {
     // The audio statistics history is exponentially weighted to forget events
@@ -677,14 +757,14 @@
     sendConfigEvent_l(configEvent);
 }
 
-void AudioFlinger::ThreadBase::sendPrioConfigEvent(pid_t pid, pid_t tid, int32_t prio, bool forApp)
+void ThreadBase::sendPrioConfigEvent(pid_t pid, pid_t tid, int32_t prio, bool forApp)
 {
     Mutex::Autolock _l(mLock);
     sendPrioConfigEvent_l(pid, tid, prio, forApp);
 }
 
 // sendPrioConfigEvent_l() must be called with ThreadBase::mLock held
-void AudioFlinger::ThreadBase::sendPrioConfigEvent_l(
+void ThreadBase::sendPrioConfigEvent_l(
         pid_t pid, pid_t tid, int32_t prio, bool forApp)
 {
     sp<ConfigEvent> configEvent = (ConfigEvent *)new PrioConfigEvent(pid, tid, prio, forApp);
@@ -692,7 +772,7 @@
 }
 
 // sendSetParameterConfigEvent_l() must be called with ThreadBase::mLock held
-status_t AudioFlinger::ThreadBase::sendSetParameterConfigEvent_l(const String8& keyValuePair)
+status_t ThreadBase::sendSetParameterConfigEvent_l(const String8& keyValuePair)
 {
     sp<ConfigEvent> configEvent;
     AudioParameter param(keyValuePair);
@@ -710,7 +790,7 @@
     return sendConfigEvent_l(configEvent);
 }
 
-status_t AudioFlinger::ThreadBase::sendCreateAudioPatchConfigEvent(
+status_t ThreadBase::sendCreateAudioPatchConfigEvent(
                                                         const struct audio_patch *patch,
                                                         audio_patch_handle_t *handle)
 {
@@ -725,7 +805,7 @@
     return status;
 }
 
-status_t AudioFlinger::ThreadBase::sendReleaseAudioPatchConfigEvent(
+status_t ThreadBase::sendReleaseAudioPatchConfigEvent(
                                                                 const audio_patch_handle_t handle)
 {
     Mutex::Autolock _l(mLock);
@@ -733,7 +813,7 @@
     return sendConfigEvent_l(configEvent);
 }
 
-status_t AudioFlinger::ThreadBase::sendUpdateOutDeviceConfigEvent(
+status_t ThreadBase::sendUpdateOutDeviceConfigEvent(
         const DeviceDescriptorBaseVector& outDevices)
 {
     if (type() != RECORD) {
@@ -745,7 +825,7 @@
     return sendConfigEvent_l(configEvent);
 }
 
-void AudioFlinger::ThreadBase::sendResizeBufferConfigEvent_l(int32_t maxSharedAudioHistoryMs)
+void ThreadBase::sendResizeBufferConfigEvent_l(int32_t maxSharedAudioHistoryMs)
 {
     ALOG_ASSERT(type() == RECORD, "sendResizeBufferConfigEvent_l() called on non record thread");
     sp<ConfigEvent> configEvent =
@@ -753,27 +833,27 @@
     sendConfigEvent_l(configEvent);
 }
 
-void AudioFlinger::ThreadBase::sendCheckOutputStageEffectsEvent()
+void ThreadBase::sendCheckOutputStageEffectsEvent()
 {
     Mutex::Autolock _l(mLock);
     sendCheckOutputStageEffectsEvent_l();
 }
 
-void AudioFlinger::ThreadBase::sendCheckOutputStageEffectsEvent_l()
+void ThreadBase::sendCheckOutputStageEffectsEvent_l()
 {
     sp<ConfigEvent> configEvent =
             (ConfigEvent *)new CheckOutputStageEffectsEvent();
     sendConfigEvent_l(configEvent);
 }
 
-void AudioFlinger::ThreadBase::sendHalLatencyModesChangedEvent_l()
+void ThreadBase::sendHalLatencyModesChangedEvent_l()
 {
     sp<ConfigEvent> configEvent = sp<HalLatencyModesChangedEvent>::make();
     sendConfigEvent_l(configEvent);
 }
 
 // post condition: mConfigEvents.isEmpty()
-void AudioFlinger::ThreadBase::processConfigEvents_l()
+void ThreadBase::processConfigEvents_l()
 {
     bool configChanged = false;
 
@@ -940,13 +1020,13 @@
     }
 }
 
-void AudioFlinger::ThreadBase::dump(int fd, const Vector<String16>& args)
+void ThreadBase::dump(int fd, const Vector<String16>& args)
 NO_THREAD_SAFETY_ANALYSIS  // conditional try lock
 {
     dprintf(fd, "\n%s thread %p, name %s, tid %d, type %d (%s):\n", isOutput() ? "Output" : "Input",
             this, mThreadName, getTid(), type(), threadTypeToString(type()));
 
-    bool locked = AudioFlinger::dumpTryLock(mLock);
+    const bool locked = afutils::dumpTryLock(mLock);
     if (!locked) {
         dprintf(fd, "  Thread may be deadlocked\n");
     }
@@ -978,18 +1058,20 @@
     }
 }
 
-void AudioFlinger::ThreadBase::dumpBase_l(int fd, const Vector<String16>& args __unused)
+void ThreadBase::dumpBase_l(int fd, const Vector<String16>& /* args */)
 {
     dprintf(fd, "  I/O handle: %d\n", mId);
     dprintf(fd, "  Standby: %s\n", mStandby ? "yes" : "no");
     dprintf(fd, "  Sample rate: %u Hz\n", mSampleRate);
     dprintf(fd, "  HAL frame count: %zu\n", mFrameCount);
-    dprintf(fd, "  HAL format: 0x%x (%s)\n", mHALFormat, formatToString(mHALFormat).c_str());
+    dprintf(fd, "  HAL format: 0x%x (%s)\n", mHALFormat,
+            IAfThreadBase::formatToString(mHALFormat).c_str());
     dprintf(fd, "  HAL buffer size: %zu bytes\n", mBufferSize);
     dprintf(fd, "  Channel count: %u\n", mChannelCount);
     dprintf(fd, "  Channel mask: 0x%08x (%s)\n", mChannelMask,
             channelMaskToString(mChannelMask, mType != RECORD).string());
-    dprintf(fd, "  Processing format: 0x%x (%s)\n", mFormat, formatToString(mFormat).c_str());
+    dprintf(fd, "  Processing format: 0x%x (%s)\n", mFormat,
+            IAfThreadBase::formatToString(mFormat).c_str());
     dprintf(fd, "  Processing frame size: %zu bytes\n", mFrameSize);
     dprintf(fd, "  Pending config events:");
     size_t numConfig = mConfigEvents.size();
@@ -1051,7 +1133,7 @@
     }
 }
 
-void AudioFlinger::ThreadBase::dumpEffectChains_l(int fd, const Vector<String16>& args)
+void ThreadBase::dumpEffectChains_l(int fd, const Vector<String16>& args)
 {
     const size_t SIZE = 256;
     char buffer[SIZE];
@@ -1068,13 +1150,13 @@
     }
 }
 
-void AudioFlinger::ThreadBase::acquireWakeLock()
+void ThreadBase::acquireWakeLock()
 {
     Mutex::Autolock _l(mLock);
     acquireWakeLock_l();
 }
 
-String16 AudioFlinger::ThreadBase::getWakeLockTag()
+String16 ThreadBase::getWakeLockTag()
 {
     switch (mType) {
     case MIXER:
@@ -1099,7 +1181,7 @@
     }
 }
 
-void AudioFlinger::ThreadBase::acquireWakeLock_l()
+void ThreadBase::acquireWakeLock_l()
 {
     getPowerManager_l();
     if (mPowerManager != 0) {
@@ -1122,13 +1204,13 @@
             gBoottime.getBoottimeOffset();
 }
 
-void AudioFlinger::ThreadBase::releaseWakeLock()
+void ThreadBase::releaseWakeLock()
 {
     Mutex::Autolock _l(mLock);
     releaseWakeLock_l();
 }
 
-void AudioFlinger::ThreadBase::releaseWakeLock_l()
+void ThreadBase::releaseWakeLock_l()
 {
     gBoottime.release(mWakeLockToken);
     if (mWakeLockToken != 0) {
@@ -1140,7 +1222,7 @@
     }
 }
 
-void AudioFlinger::ThreadBase::getPowerManager_l() {
+void ThreadBase::getPowerManager_l() {
     if (mSystemReady && mPowerManager == 0) {
         // use checkService() to avoid blocking if power service is not up yet
         sp<IBinder> binder =
@@ -1154,7 +1236,7 @@
     }
 }
 
-void AudioFlinger::ThreadBase::updateWakeLockUids_l(const SortedVector<uid_t> &uids) {
+void ThreadBase::updateWakeLockUids_l(const SortedVector<uid_t>& uids) {
     getPowerManager_l();
 
 #if !LOG_NDEBUG
@@ -1181,25 +1263,25 @@
     }
 }
 
-void AudioFlinger::ThreadBase::clearPowerManager()
+void ThreadBase::clearPowerManager()
 {
     Mutex::Autolock _l(mLock);
     releaseWakeLock_l();
     mPowerManager.clear();
 }
 
-void AudioFlinger::ThreadBase::updateOutDevices(
+void ThreadBase::updateOutDevices(
         const DeviceDescriptorBaseVector& outDevices __unused)
 {
     ALOGE("%s should only be called in RecordThread", __func__);
 }
 
-void AudioFlinger::ThreadBase::resizeInputBuffer_l(int32_t maxSharedAudioHistoryMs __unused)
+void ThreadBase::resizeInputBuffer_l(int32_t /* maxSharedAudioHistoryMs */)
 {
     ALOGE("%s should only be called in RecordThread", __func__);
 }
 
-void AudioFlinger::ThreadBase::PMDeathRecipient::binderDied(const wp<IBinder>& who __unused)
+void ThreadBase::PMDeathRecipient::binderDied(const wp<IBinder>& /* who */)
 {
     sp<ThreadBase> thread = mThread.promote();
     if (thread != 0) {
@@ -1208,7 +1290,7 @@
     ALOGW("power manager service died !!!");
 }
 
-void AudioFlinger::ThreadBase::setEffectSuspended_l(
+void ThreadBase::setEffectSuspended_l(
         const effect_uuid_t *type, bool suspend, audio_session_t sessionId)
 {
     sp<IAfEffectChain> chain = getEffectChain_l(sessionId);
@@ -1223,7 +1305,7 @@
     updateSuspendedSessions_l(type, suspend, sessionId);
 }
 
-void AudioFlinger::ThreadBase::checkSuspendOnAddEffectChain_l(const sp<IAfEffectChain>& chain)
+void ThreadBase::checkSuspendOnAddEffectChain_l(const sp<IAfEffectChain>& chain)
 {
     ssize_t index = mSuspendedSessions.indexOfKey(chain->sessionId());
     if (index < 0) {
@@ -1247,7 +1329,7 @@
     }
 }
 
-void AudioFlinger::ThreadBase::updateSuspendedSessions_l(const effect_uuid_t *type,
+void ThreadBase::updateSuspendedSessions_l(const effect_uuid_t* type,
                                                          bool suspend,
                                                          audio_session_t sessionId)
 {
@@ -1308,7 +1390,7 @@
     }
 }
 
-void AudioFlinger::ThreadBase::checkSuspendOnEffectEnabled(bool enabled,
+void ThreadBase::checkSuspendOnEffectEnabled(bool enabled,
                                                            audio_session_t sessionId,
                                                            bool threadLocked)
 NO_THREAD_SAFETY_ANALYSIS  // manual locking
@@ -1334,7 +1416,7 @@
 }
 
 // checkEffectCompatibility_l() must be called with ThreadBase::mLock held
-status_t AudioFlinger::RecordThread::checkEffectCompatibility_l(
+status_t RecordThread::checkEffectCompatibility_l(
         const effect_descriptor_t *desc, audio_session_t sessionId)
 {
     // No global output effect sessions on record threads
@@ -1378,7 +1460,7 @@
 }
 
 // checkEffectCompatibility_l() must be called with ThreadBase::mLock held
-status_t AudioFlinger::PlaybackThread::checkEffectCompatibility_l(
+status_t PlaybackThread::checkEffectCompatibility_l(
         const effect_descriptor_t *desc, audio_session_t sessionId)
 {
     // no preprocessing on playback threads
@@ -1533,7 +1615,7 @@
 }
 
 // ThreadBase::createEffect_l() must be called with AudioFlinger::mLock held
-sp<IAfEffectHandle> AudioFlinger::ThreadBase::createEffect_l(
+sp<IAfEffectHandle> ThreadBase::createEffect_l(
         const sp<Client>& client,
         const sp<IEffectClient>& effectClient,
         int32_t priority,
@@ -1585,7 +1667,7 @@
         ALOGV("createEffect_l() got effect %p on chain %p", effect.get(), chain.get());
 
         if (effect == 0) {
-            effectId = mAudioFlinger->nextUniqueId(AUDIO_UNIQUE_ID_USE_EFFECT);
+            effectId = mAfThreadCallback->nextUniqueId(AUDIO_UNIQUE_ID_USE_EFFECT);
             // create a new effect module if none present in the chain
             lStatus = chain->createEffect_l(effect, desc, effectId, sessionId, pinned);
             if (lStatus != NO_ERROR) {
@@ -1596,14 +1678,14 @@
             // FIXME: use vector of device and address when effect interface is ready.
             effect->setDevices(outDeviceTypeAddrs());
             effect->setInputDevice(inDeviceTypeAddr());
-            effect->setMode(mAudioFlinger->getMode());
+            effect->setMode(mAfThreadCallback->getMode());
             effect->setAudioSource(mAudioSource);
         }
         if (effect->isHapticGenerator()) {
             // TODO(b/184194057): Use the vibrator information from the vibrator that will be used
             // for the HapticGenerator.
             const std::optional<media::AudioVibratorInfo> defaultVibratorInfo =
-                    std::move(mAudioFlinger->getDefaultVibratorInfo_l());
+                    std::move(mAfThreadCallback->getDefaultVibratorInfo_l());
             if (defaultVibratorInfo) {
                 // Only set the vibrator info when it is a valid one.
                 effect->setVibratorInfo(*defaultVibratorInfo);
@@ -1638,7 +1720,7 @@
     return handle;
 }
 
-void AudioFlinger::ThreadBase::disconnectEffectHandle(IAfEffectHandle *handle,
+void ThreadBase::disconnectEffectHandle(IAfEffectHandle* handle,
                                                       bool unpinIfLast)
 {
     bool remove = false;
@@ -1661,14 +1743,14 @@
         sendCheckOutputStageEffectsEvent_l();
     }
     if (remove) {
-        mAudioFlinger->updateOrphanEffectChains(effect);
+        mAfThreadCallback->updateOrphanEffectChains(effect);
         if (handle->enabled()) {
             effect->checkSuspendOnEffectEnabled(false, false /*threadLocked*/);
         }
     }
 }
 
-void AudioFlinger::ThreadBase::onEffectEnable(const sp<IAfEffectModule>& effect) {
+void ThreadBase::onEffectEnable(const sp<IAfEffectModule>& effect) {
     if (isOffloadOrMmap()) {
         Mutex::Autolock _l(mLock);
         broadcast_l();
@@ -1679,33 +1761,33 @@
             t->invalidateTracks(AUDIO_STREAM_MUSIC);
         }
         if (effect->sessionId() == AUDIO_SESSION_OUTPUT_MIX) {
-            mAudioFlinger->onNonOffloadableGlobalEffectEnable();
+            mAfThreadCallback->onNonOffloadableGlobalEffectEnable();
         }
     }
 }
 
-void AudioFlinger::ThreadBase::onEffectDisable() {
+void ThreadBase::onEffectDisable() {
     if (isOffloadOrMmap()) {
         Mutex::Autolock _l(mLock);
         broadcast_l();
     }
 }
 
-sp<IAfEffectModule> AudioFlinger::ThreadBase::getEffect(audio_session_t sessionId,
-        int effectId)
+sp<IAfEffectModule> ThreadBase::getEffect(audio_session_t sessionId,
+        int effectId) const
 {
     Mutex::Autolock _l(mLock);
     return getEffect_l(sessionId, effectId);
 }
 
-sp<IAfEffectModule> AudioFlinger::ThreadBase::getEffect_l(audio_session_t sessionId,
-        int effectId)
+sp<IAfEffectModule> ThreadBase::getEffect_l(audio_session_t sessionId,
+        int effectId) const
 {
     sp<IAfEffectChain> chain = getEffectChain_l(sessionId);
     return chain != 0 ? chain->getEffectFromId_l(effectId) : 0;
 }
 
-std::vector<int> AudioFlinger::ThreadBase::getEffectIds_l(audio_session_t sessionId)
+std::vector<int> ThreadBase::getEffectIds_l(audio_session_t sessionId) const
 {
     sp<IAfEffectChain> chain = getEffectChain_l(sessionId);
     return chain != nullptr ? chain->getEffectIds() : std::vector<int>{};
@@ -1713,7 +1795,7 @@
 
 // PlaybackThread::addEffect_l() must be called with AudioFlinger::mLock and
 // PlaybackThread::mLock held
-status_t AudioFlinger::ThreadBase::addEffect_l(const sp<IAfEffectModule>& effect)
+status_t ThreadBase::addEffect_l(const sp<IAfEffectModule>& effect)
 {
     // check for existing effect chain with the requested audio session
     audio_session_t sessionId = effect->sessionId();
@@ -1752,13 +1834,13 @@
 
     effect->setDevices(outDeviceTypeAddrs());
     effect->setInputDevice(inDeviceTypeAddr());
-    effect->setMode(mAudioFlinger->getMode());
+    effect->setMode(mAfThreadCallback->getMode());
     effect->setAudioSource(mAudioSource);
 
     return NO_ERROR;
 }
 
-void AudioFlinger::ThreadBase::removeEffect_l(const sp<IAfEffectModule>& effect, bool release) {
+void ThreadBase::removeEffect_l(const sp<IAfEffectModule>& effect, bool release) {
 
     ALOGV("%s %p effect %p", __FUNCTION__, this, effect.get());
     effect_descriptor_t desc = effect->desc();
@@ -1777,7 +1859,7 @@
     }
 }
 
-void AudioFlinger::ThreadBase::lockEffectChains_l(
+void ThreadBase::lockEffectChains_l(
         Vector<sp<IAfEffectChain>>& effectChains)
 NO_THREAD_SAFETY_ANALYSIS  // calls EffectChain::lock()
 {
@@ -1787,7 +1869,7 @@
     }
 }
 
-void AudioFlinger::ThreadBase::unlockEffectChains(
+void ThreadBase::unlockEffectChains(
         const Vector<sp<IAfEffectChain>>& effectChains)
 NO_THREAD_SAFETY_ANALYSIS  // calls EffectChain::unlock()
 {
@@ -1796,13 +1878,13 @@
     }
 }
 
-sp<IAfEffectChain> AudioFlinger::ThreadBase::getEffectChain(audio_session_t sessionId)
+sp<IAfEffectChain> ThreadBase::getEffectChain(audio_session_t sessionId) const
 {
     Mutex::Autolock _l(mLock);
     return getEffectChain_l(sessionId);
 }
 
-sp<IAfEffectChain> AudioFlinger::ThreadBase::getEffectChain_l(audio_session_t sessionId)
+sp<IAfEffectChain> ThreadBase::getEffectChain_l(audio_session_t sessionId)
         const
 {
     size_t size = mEffectChains.size();
@@ -1814,7 +1896,7 @@
     return 0;
 }
 
-void AudioFlinger::ThreadBase::setMode(audio_mode_t mode)
+void ThreadBase::setMode(audio_mode_t mode)
 {
     Mutex::Autolock _l(mLock);
     size_t size = mEffectChains.size();
@@ -1823,7 +1905,7 @@
     }
 }
 
-void AudioFlinger::ThreadBase::toAudioPortConfig(struct audio_port_config *config)
+void ThreadBase::toAudioPortConfig(struct audio_port_config* config)
 {
     config->type = AUDIO_PORT_TYPE_MIX;
     config->ext.mix.handle = mId;
@@ -1834,7 +1916,7 @@
                             AUDIO_PORT_CONFIG_FORMAT;
 }
 
-void AudioFlinger::ThreadBase::systemReady()
+void ThreadBase::systemReady()
 {
     Mutex::Autolock _l(mLock);
     if (mSystemReady) {
@@ -1849,7 +1931,7 @@
 }
 
 template <typename T>
-ssize_t AudioFlinger::ThreadBase::ActiveTracks<T>::add(const sp<T> &track) {
+ssize_t ThreadBase::ActiveTracks<T>::add(const sp<T>& track) {
     ssize_t index = mActiveTracks.indexOf(track);
     if (index >= 0) {
         ALOGW("ActiveTracks<T>::add track %p already there", track.get());
@@ -1864,7 +1946,7 @@
 }
 
 template <typename T>
-ssize_t AudioFlinger::ThreadBase::ActiveTracks<T>::remove(const sp<T> &track) {
+ssize_t ThreadBase::ActiveTracks<T>::remove(const sp<T>& track) {
     ssize_t index = mActiveTracks.remove(track);
     if (index < 0) {
         ALOGW("ActiveTracks<T>::remove nonexistent track %p", track.get());
@@ -1883,7 +1965,7 @@
 }
 
 template <typename T>
-void AudioFlinger::ThreadBase::ActiveTracks<T>::clear() {
+void ThreadBase::ActiveTracks<T>::clear() {
     for (const sp<T> &track : mActiveTracks) {
         track->endBatteryAttribution();
         logTrack("clear", track);
@@ -1895,7 +1977,7 @@
 }
 
 template <typename T>
-void AudioFlinger::ThreadBase::ActiveTracks<T>::updatePowerState(
+void ThreadBase::ActiveTracks<T>::updatePowerState(
         const sp<ThreadBase>& thread, bool force) {
     // Updates ActiveTracks client uids to the thread wakelock.
     if (mActiveTracksGeneration != mLastActiveTracksGeneration || force) {
@@ -1905,7 +1987,7 @@
 }
 
 template <typename T>
-bool AudioFlinger::ThreadBase::ActiveTracks<T>::readAndClearHasChanged() {
+bool ThreadBase::ActiveTracks<T>::readAndClearHasChanged() {
     bool hasChanged = mHasChanged;
     mHasChanged = false;
 
@@ -1918,7 +2000,7 @@
 }
 
 template <typename T>
-void AudioFlinger::ThreadBase::ActiveTracks<T>::logTrack(
+void ThreadBase::ActiveTracks<T>::logTrack(
         const char *funcName, const sp<T> &track) const {
     if (mLocalLog != nullptr) {
         String8 result;
@@ -1927,7 +2009,7 @@
     }
 }
 
-void AudioFlinger::ThreadBase::broadcast_l()
+void ThreadBase::broadcast_l()
 {
     // Thread could be blocked waiting for async
     // so signal it to handle state changes immediately
@@ -1939,7 +2021,7 @@
 
 // Call only from threadLoop() or when it is idle.
 // Do not call from high performance code as this may do binder rpc to the MediaMetrics service.
-void AudioFlinger::ThreadBase::sendStatistics(bool force)
+void ThreadBase::sendStatistics(bool force)
 {
     // Do not log if we have no stats.
     // We choose the timestamp verifier because it is the most likely item to be present.
@@ -2002,16 +2084,16 @@
     item->selfrecord();
 }
 
-product_strategy_t AudioFlinger::ThreadBase::getStrategyForStream(audio_stream_type_t stream) const
+product_strategy_t ThreadBase::getStrategyForStream(audio_stream_type_t stream) const
 {
-    if (!mAudioFlinger->isAudioPolicyReady()) {
+    if (!mAfThreadCallback->isAudioPolicyReady()) {
         return PRODUCT_STRATEGY_NONE;
     }
     return AudioSystem::getStrategyForStream(stream);
 }
 
 // startMelComputation_l() must be called with AudioFlinger::mLock held
-void AudioFlinger::ThreadBase::startMelComputation_l(
+void ThreadBase::startMelComputation_l(
         const sp<audio_utils::MelProcessor>& /*processor*/)
 {
     // Do nothing
@@ -2019,7 +2101,7 @@
 }
 
 // stopMelComputation_l() must be called with AudioFlinger::mLock held
-void AudioFlinger::ThreadBase::stopMelComputation_l()
+void ThreadBase::stopMelComputation_l()
 {
     // Do nothing
     ALOGW("%s: ThreadBase does not support CSD", __func__);
@@ -2029,20 +2111,20 @@
 //      Playback
 // ----------------------------------------------------------------------------
 
-AudioFlinger::PlaybackThread::PlaybackThread(const sp<AudioFlinger>& audioFlinger,
+PlaybackThread::PlaybackThread(const sp<IAfThreadCallback>& afThreadCallback,
                                              AudioStreamOut* output,
                                              audio_io_handle_t id,
                                              type_t type,
                                              bool systemReady,
                                              audio_config_base_t *mixerConfig)
-    :   ThreadBase(audioFlinger, id, type, systemReady, true /* isOut */),
+    :   ThreadBase(afThreadCallback, id, type, systemReady, true /* isOut */),
         mNormalFrameCount(0), mSinkBuffer(NULL),
-        mMixerBufferEnabled(AudioFlinger::kEnableExtendedPrecision || type == SPATIALIZER),
+        mMixerBufferEnabled(kEnableExtendedPrecision || type == SPATIALIZER),
         mMixerBuffer(NULL),
         mMixerBufferSize(0),
         mMixerBufferFormat(AUDIO_FORMAT_INVALID),
         mMixerBufferValid(false),
-        mEffectBufferEnabled(AudioFlinger::kEnableExtendedPrecision || type == SPATIALIZER),
+        mEffectBufferEnabled(kEnableExtendedPrecision || type == SPATIALIZER),
         mEffectBuffer(NULL),
         mEffectBufferSize(0),
         mEffectBufferFormat(AUDIO_FORMAT_INVALID),
@@ -2057,13 +2139,13 @@
         mNumWrites(0), mNumDelayedWrites(0), mInWrite(false),
         mMixerStatus(MIXER_IDLE),
         mMixerStatusIgnoringFastTracks(MIXER_IDLE),
-        mStandbyDelayNs(AudioFlinger::mStandbyTimeInNsecs),
+        mStandbyDelayNs(getStandbyTimeInNanos()),
         mBytesRemaining(0),
         mCurrentWriteLength(0),
         mUseAsyncWrite(false),
         mWriteAckSequence(0),
         mDrainSequence(0),
-        mScreenState(AudioFlinger::mScreenState),
+        mScreenState(mAfThreadCallback->getScreenState()),
         // index 0 is reserved for normal mixer's submix
         mFastTrackAvailMask(((1 << FastMixerState::sMaxFastTracks) - 1) & ~1),
         mHwSupportsPause(false), mHwPaused(false), mFlushPending(false),
@@ -2072,7 +2154,7 @@
         mIsTimestampAdvancing(kMinimumTimeBetweenTimestampChecksNs)
 {
     snprintf(mThreadName, kThreadNameLength, "AudioOut_%X", id);
-    mNBLogWriter = audioFlinger->newWriter_l(kLogSize, mThreadName);
+    mNBLogWriter = afThreadCallback->newWriter_l(kLogSize, mThreadName);
 
     // Assumes constructor is called by AudioFlinger with it's mLock held, but
     // it would be safer to explicitly pass initial masterVolume/masterMute as
@@ -2081,8 +2163,8 @@
     // If the HAL we are using has support for master volume or master mute,
     // then do not attenuate or mute during mixing (just leave the volume at 1.0
     // and the mute set to false).
-    mMasterVolume = audioFlinger->masterVolume_l();
-    mMasterMute = audioFlinger->masterMute_l();
+    mMasterVolume = afThreadCallback->masterVolume_l();
+    mMasterMute = afThreadCallback->masterMute_l();
     if (mOutput->audioHwDev) {
         if (mOutput->audioHwDev->canSetMasterVolume()) {
             mMasterVolume = 1.0;
@@ -2120,7 +2202,7 @@
     for (int i = AUDIO_STREAM_MIN; i < AUDIO_STREAM_FOR_POLICY_CNT; ++i) {
         const audio_stream_type_t stream{static_cast<audio_stream_type_t>(i)};
         mStreamTypes[stream].volume = 0.0f;
-        mStreamTypes[stream].mute = mAudioFlinger->streamMute_l(stream);
+        mStreamTypes[stream].mute = mAfThreadCallback->streamMute_l(stream);
     }
     // Audio patch and call assistant volume are always max
     mStreamTypes[AUDIO_STREAM_PATCH].volume = 1.0f;
@@ -2129,9 +2211,9 @@
     mStreamTypes[AUDIO_STREAM_CALL_ASSISTANT].mute = false;
 }
 
-AudioFlinger::PlaybackThread::~PlaybackThread()
+PlaybackThread::~PlaybackThread()
 {
-    mAudioFlinger->unregisterWriter(mNBLogWriter);
+    mAfThreadCallback->unregisterWriter(mNBLogWriter);
     free(mSinkBuffer);
     free(mMixerBuffer);
     free(mEffectBuffer);
@@ -2140,7 +2222,7 @@
 
 // Thread virtuals
 
-void AudioFlinger::PlaybackThread::onFirstRef()
+void PlaybackThread::onFirstRef()
 {
     if (!isStreamInitialized()) {
         ALOGE("The stream is not open yet"); // This should not happen.
@@ -2155,7 +2237,7 @@
         if (mOutput->flags & AUDIO_OUTPUT_FLAG_NON_BLOCKING &&
                 mOutput->stream->setCallback(this) == OK) {
             mUseAsyncWrite = true;
-            mCallbackThread = new AudioFlinger::AsyncCallbackThread(this);
+            mCallbackThread = sp<AsyncCallbackThread>::make(this);
         }
 
         if (mOutput->stream->setEventCallback(this) != OK) {
@@ -2167,14 +2249,14 @@
 }
 
 // ThreadBase virtuals
-void AudioFlinger::PlaybackThread::preExit()
+void PlaybackThread::preExit()
 {
     ALOGV("  preExit()");
     status_t result = mOutput->stream->exit();
     ALOGE_IF(result != OK, "Error when calling exit(): %d", result);
 }
 
-void AudioFlinger::PlaybackThread::dumpTracks_l(int fd, const Vector<String16>& args __unused)
+void PlaybackThread::dumpTracks_l(int fd, const Vector<String16>& /* args */)
 {
     String8 result;
 
@@ -2208,7 +2290,7 @@
         result.append(prefix);
         mTracks[0]->appendDumpHeader(result);
         for (size_t i = 0; i < numtracks; ++i) {
-            sp<Track> track = mTracks[i];
+            sp<IAfTrack> track = mTracks[i];
             if (track != 0) {
                 bool active = mActiveTracks.indexOf(track) >= 0;
                 if (active) {
@@ -2228,7 +2310,7 @@
         result.append(prefix);
         mActiveTracks[0]->appendDumpHeader(result);
         for (size_t i = 0; i < numactive; ++i) {
-            sp<Track> track = mActiveTracks[i];
+            sp<IAfTrack> track = mActiveTracks[i];
             if (mTracks.indexOf(track) < 0) {
                 result.append(prefix);
                 track->appendDump(result, true /* active */);
@@ -2239,7 +2321,7 @@
     write(fd, result.string(), result.size());
 }
 
-void AudioFlinger::PlaybackThread::dumpInternals_l(int fd, const Vector<String16>& args)
+void PlaybackThread::dumpInternals_l(int fd, const Vector<String16>& args)
 {
     dprintf(fd, "  Master volume: %f\n", mMasterVolume);
     dprintf(fd, "  Master mute: %s\n", mMasterMute ? "on" : "off");
@@ -2275,7 +2357,7 @@
 }
 
 // PlaybackThread::createTrack_l() must be called with AudioFlinger::mLock held
-sp<AudioFlinger::PlaybackThread::Track> AudioFlinger::PlaybackThread::createTrack_l(
+sp<IAfTrack> PlaybackThread::createTrack_l(
         const sp<Client>& client,
         audio_stream_type_t streamType,
         const audio_attributes_t& attr,
@@ -2300,7 +2382,7 @@
 {
     size_t frameCount = *pFrameCount;
     size_t notificationFrameCount = *pNotificationFrameCount;
-    sp<Track> track;
+    sp<IAfTrack> track;
     status_t lStatus;
     audio_output_flags_t outputFlags = mOutput->flags;
     audio_output_flags_t requestedFlags = *flags;
@@ -2593,7 +2675,7 @@
         // manager
         product_strategy_t strategy = getStrategyForStream(streamType);
         for (size_t i = 0; i < mTracks.size(); ++i) {
-            sp<Track> t = mTracks[i];
+            sp<IAfTrack> t = mTracks[i];
             if (t != 0 && t->isExternalTrack()) {
                 product_strategy_t actual = getStrategyForStream(t->streamType());
                 if (sessionId == t->sessionId() && strategy != actual) {
@@ -2615,11 +2697,11 @@
             trackFlags = static_cast<audio_output_flags_t>(trackFlags | AUDIO_OUTPUT_FLAG_DIRECT);
         }
 
-        track = new Track(this, client, streamType, attr, sampleRate, format,
+        track = IAfTrack::create(this, client, streamType, attr, sampleRate, format,
                           channelMask, frameCount,
                           nullptr /* buffer */, (size_t)0 /* bufferSize */, sharedBuffer,
                           sessionId, creatorPid, attributionSource, trackFlags,
-                          TrackBase::TYPE_DEFAULT, portId, SIZE_MAX /*frameCountToBeReady*/,
+                          IAfTrackBase::TYPE_DEFAULT, portId, SIZE_MAX /*frameCountToBeReady*/,
                           speed, isSpatialized, isBitPerfect);
 
         lStatus = track != 0 ? track->initCheck() : (status_t) NO_MEMORY;
@@ -2660,7 +2742,7 @@
 }
 
 template<typename T>
-ssize_t AudioFlinger::PlaybackThread::Tracks<T>::remove(const sp<T> &track)
+ssize_t PlaybackThread::Tracks<T>::remove(const sp<T>& track)
 {
     const int trackId = track->id();
     const ssize_t index = mTracks.remove(track);
@@ -2675,17 +2757,17 @@
     return index;
 }
 
-uint32_t AudioFlinger::PlaybackThread::correctLatency_l(uint32_t latency) const
+uint32_t PlaybackThread::correctLatency_l(uint32_t latency) const
 {
     return latency;
 }
 
-uint32_t AudioFlinger::PlaybackThread::latency() const
+uint32_t PlaybackThread::latency() const
 {
     Mutex::Autolock _l(mLock);
     return latency_l();
 }
-uint32_t AudioFlinger::PlaybackThread::latency_l() const
+uint32_t PlaybackThread::latency_l() const
 {
     uint32_t latency;
     if (initCheck() == NO_ERROR && mOutput->stream->getLatency(&latency) == OK) {
@@ -2694,7 +2776,7 @@
     return 0;
 }
 
-void AudioFlinger::PlaybackThread::setMasterVolume(float value)
+void PlaybackThread::setMasterVolume(float value)
 {
     Mutex::Autolock _l(mLock);
     // Don't apply master volume in SW if our HAL can do it for us.
@@ -2706,12 +2788,12 @@
     }
 }
 
-void AudioFlinger::PlaybackThread::setMasterBalance(float balance)
+void PlaybackThread::setMasterBalance(float balance)
 {
     mMasterBalance.store(balance);
 }
 
-void AudioFlinger::PlaybackThread::setMasterMute(bool muted)
+void PlaybackThread::setMasterMute(bool muted)
 {
     if (isDuplicating()) {
         return;
@@ -2726,33 +2808,33 @@
     }
 }
 
-void AudioFlinger::PlaybackThread::setStreamVolume(audio_stream_type_t stream, float value)
+void PlaybackThread::setStreamVolume(audio_stream_type_t stream, float value)
 {
     Mutex::Autolock _l(mLock);
     mStreamTypes[stream].volume = value;
     broadcast_l();
 }
 
-void AudioFlinger::PlaybackThread::setStreamMute(audio_stream_type_t stream, bool muted)
+void PlaybackThread::setStreamMute(audio_stream_type_t stream, bool muted)
 {
     Mutex::Autolock _l(mLock);
     mStreamTypes[stream].mute = muted;
     broadcast_l();
 }
 
-float AudioFlinger::PlaybackThread::streamVolume(audio_stream_type_t stream) const
+float PlaybackThread::streamVolume(audio_stream_type_t stream) const
 {
     Mutex::Autolock _l(mLock);
     return mStreamTypes[stream].volume;
 }
 
-void AudioFlinger::PlaybackThread::setVolumeForOutput_l(float left, float right) const
+void PlaybackThread::setVolumeForOutput_l(float left, float right) const
 {
     mOutput->stream->setVolume(left, right);
 }
 
 // addTrack_l() must be called with ThreadBase::mLock held
-status_t AudioFlinger::PlaybackThread::addTrack_l(const sp<Track>& track)
+status_t PlaybackThread::addTrack_l(const sp<IAfTrack>& track)
 NO_THREAD_SAFETY_ANALYSIS  // release and re-acquire mLock
 {
     status_t status = ALREADY_EXISTS;
@@ -2762,12 +2844,12 @@
         // buffers before playing. This is to ensure the client will
         // effectively get the latency it requested.
         if (track->isExternalTrack()) {
-            TrackBase::track_state state = track->mState;
+            IAfTrackBase::track_state state = track->state();
             mLock.unlock();
             status = AudioSystem::startOutput(track->portId());
             mLock.lock();
             // abort track was stopped/paused while we released the lock
-            if (state != track->mState) {
+            if (state != track->state()) {
                 if (status == NO_ERROR) {
                     mLock.unlock();
                     AudioSystem::stopOutput(track->portId());
@@ -2793,15 +2875,15 @@
         // set retry count for buffer fill
         if (track->isOffloaded()) {
             if (track->isStopping_1()) {
-                track->mRetryCount = kMaxTrackStopRetriesOffload;
+                track->retryCount() = kMaxTrackStopRetriesOffload;
             } else {
-                track->mRetryCount = kMaxTrackStartupRetriesOffload;
+                track->retryCount() = kMaxTrackStartupRetriesOffload;
             }
-            track->mFillingUpStatus = mStandby ? Track::FS_FILLING : Track::FS_FILLED;
+            track->fillingStatus() = mStandby ? IAfTrack::FS_FILLING : IAfTrack::FS_FILLED;
         } else {
-            track->mRetryCount = kMaxTrackStartupRetries;
-            track->mFillingUpStatus =
-                    track->sharedBuffer() != 0 ? Track::FS_FILLED : Track::FS_FILLING;
+            track->retryCount() = kMaxTrackStartupRetries;
+            track->fillingStatus() =
+                    track->sharedBuffer() != 0 ? IAfTrack::FS_FILLED : IAfTrack::FS_FILLING;
         }
 
         sp<IAfEffectChain> chain = getEffectChain_l(track->sessionId());
@@ -2811,14 +2893,14 @@
             // Unlock due to VibratorService will lock for this call and will
             // call Tracks.mute/unmute which also require thread's lock.
             mLock.unlock();
-            const os::HapticScale intensity = AudioFlinger::onExternalVibrationStart(
+            const os::HapticScale intensity = afutils::onExternalVibrationStart(
                     track->getExternalVibration());
             std::optional<media::AudioVibratorInfo> vibratorInfo;
             {
                 // TODO(b/184194780): Use the vibrator information from the vibrator that will be
                 // used to play this track.
-                Mutex::Autolock _l(mAudioFlinger->mLock);
-                vibratorInfo = std::move(mAudioFlinger->getDefaultVibratorInfo_l());
+                Mutex::Autolock _l(mAfThreadCallback->mutex());
+                vibratorInfo = std::move(mAfThreadCallback->getDefaultVibratorInfo_l());
             }
             mLock.lock();
             track->setHapticIntensity(intensity);
@@ -2841,7 +2923,7 @@
             }
         }
 
-        track->mResetDone = false;
+        track->setResetDone(false);
         track->resetPresentationComplete();
         mActiveTracks.add(track);
         if (chain != 0) {
@@ -2858,25 +2940,25 @@
     return status;
 }
 
-bool AudioFlinger::PlaybackThread::destroyTrack_l(const sp<Track>& track)
+bool PlaybackThread::destroyTrack_l(const sp<IAfTrack>& track)
 {
     track->terminate();
     // active tracks are removed by threadLoop()
     bool trackActive = (mActiveTracks.indexOf(track) >= 0);
-    track->mState = TrackBase::STOPPED;
+    track->setState(IAfTrackBase::STOPPED);
     if (!trackActive) {
         removeTrack_l(track);
     } else if (track->isFastTrack() || track->isOffloaded() || track->isDirect()) {
         if (track->isPausePending()) {
             track->pauseAck();
         }
-        track->mState = TrackBase::STOPPING_1;
+        track->setState(IAfTrackBase::STOPPING_1);
     }
 
     return trackActive;
 }
 
-void AudioFlinger::PlaybackThread::removeTrack_l(const sp<Track>& track)
+void PlaybackThread::removeTrack_l(const sp<IAfTrack>& track)
 {
     track->triggerEvents(AudioSystem::SYNC_EVENT_PRESENTATION_COMPLETE);
 
@@ -2890,12 +2972,12 @@
         mAudioTrackCallbacks.erase(track);
     }
     if (track->isFastTrack()) {
-        int index = track->mFastIndex;
+        int index = track->fastIndex();
         ALOG_ASSERT(0 < index && index < (int)FastMixerState::sMaxFastTracks);
         ALOG_ASSERT(!(mFastTrackAvailMask & (1 << index)));
         mFastTrackAvailMask |= 1 << index;
         // redundant as track is about to be destroyed, for dumpsys only
-        track->mFastIndex = -1;
+        track->fastIndex() = -1;
     }
     sp<IAfEffectChain> chain = getEffectChain_l(track->sessionId());
     if (chain != 0) {
@@ -2903,7 +2985,7 @@
     }
 }
 
-String8 AudioFlinger::PlaybackThread::getParameters(const String8& keys)
+String8 PlaybackThread::getParameters(const String8& keys)
 {
     Mutex::Autolock _l(mLock);
     String8 out_s8;
@@ -2913,7 +2995,7 @@
     return {};
 }
 
-status_t AudioFlinger::DirectOutputThread::selectPresentation(int presentationId, int programId) {
+status_t DirectOutputThread::selectPresentation(int presentationId, int programId) {
     Mutex::Autolock _l(mLock);
     if (!isStreamInitialized()) {
         return NO_INIT;
@@ -2921,7 +3003,7 @@
     return mOutput->stream->selectPresentation(presentationId, programId);
 }
 
-void AudioFlinger::PlaybackThread::ioConfigChanged(audio_io_config_event_t event, pid_t pid,
+void PlaybackThread::ioConfigChanged(audio_io_config_event_t event, pid_t pid,
                                                    audio_port_handle_t portId) {
     ALOGV("PlaybackThread::ioConfigChanged, thread %p, event %d", this, event);
     sp<AudioIoDescriptor> desc;
@@ -2943,30 +3025,30 @@
         desc = sp<AudioIoDescriptor>::make(mId);
         break;
     }
-    mAudioFlinger->ioConfigChanged(event, desc, pid);
+    mAfThreadCallback->ioConfigChanged(event, desc, pid);
 }
 
-void AudioFlinger::PlaybackThread::onWriteReady()
+void PlaybackThread::onWriteReady()
 {
     mCallbackThread->resetWriteBlocked();
 }
 
-void AudioFlinger::PlaybackThread::onDrainReady()
+void PlaybackThread::onDrainReady()
 {
     mCallbackThread->resetDraining();
 }
 
-void AudioFlinger::PlaybackThread::onError()
+void PlaybackThread::onError()
 {
     mCallbackThread->setAsyncError();
 }
 
-void AudioFlinger::PlaybackThread::onCodecFormatChanged(
+void PlaybackThread::onCodecFormatChanged(
         const std::basic_string<uint8_t>& metadataBs)
 {
-    wp<AudioFlinger::PlaybackThread> weakPointerThis = this;
+    const auto weakPointerThis = wp<PlaybackThread>::fromExisting(this);
     std::thread([this, metadataBs, weakPointerThis]() {
-            sp<AudioFlinger::PlaybackThread> playbackThread = weakPointerThis.promote();
+            const sp<PlaybackThread> playbackThread = weakPointerThis.promote();
             if (playbackThread == nullptr) {
                 ALOGW("PlaybackThread was destroyed, skip codec format change event");
                 return;
@@ -2991,7 +3073,7 @@
     }).detach();
 }
 
-void AudioFlinger::PlaybackThread::resetWriteBlocked(uint32_t sequence)
+void PlaybackThread::resetWriteBlocked(uint32_t sequence)
 {
     Mutex::Autolock _l(mLock);
     // reject out of sequence requests
@@ -3001,7 +3083,7 @@
     }
 }
 
-void AudioFlinger::PlaybackThread::resetDraining(uint32_t sequence)
+void PlaybackThread::resetDraining(uint32_t sequence)
 {
     Mutex::Autolock _l(mLock);
     // reject out of sequence requests
@@ -3016,7 +3098,7 @@
     }
 }
 
-void AudioFlinger::PlaybackThread::readOutputParameters_l()
+void PlaybackThread::readOutputParameters_l()
 {
     // unfortunately we have no way of recovering from errors here, hence the LOG_ALWAYS_FATAL
     const audio_config_base_t audioConfig = mOutput->getAudioProperties();
@@ -3187,14 +3269,14 @@
     // create a copy of mEffectChains as calling moveEffectChain_l() can reorder some effect chains
     Vector<sp<IAfEffectChain>> effectChains = mEffectChains;
     for (size_t i = 0; i < effectChains.size(); i ++) {
-        mAudioFlinger->moveEffectChain_l(effectChains[i]->sessionId(),
+        mAfThreadCallback->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_ENCODING, IAfThreadBase::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)
@@ -3205,7 +3287,7 @@
         .set(AMEDIAMETRICS_PROP_PREFIX_HAPTIC AMEDIAMETRICS_PROP_CHANNELCOUNT,
                 (int32_t)mHapticChannelCount)
         .set(AMEDIAMETRICS_PROP_PREFIX_HAL    AMEDIAMETRICS_PROP_ENCODING,
-                formatToString(mHALFormat).c_str())
+                IAfThreadBase::formatToString(mHALFormat).c_str())
         .set(AMEDIAMETRICS_PROP_PREFIX_HAL    AMEDIAMETRICS_PROP_FRAMECOUNT,
                 (int32_t)mFrameCount) // sic - added HAL
         ;
@@ -3216,14 +3298,14 @@
     item.record();
 }
 
-AudioFlinger::ThreadBase::MetadataUpdate AudioFlinger::PlaybackThread::updateMetadata_l()
+ThreadBase::MetadataUpdate PlaybackThread::updateMetadata_l()
 {
     if (!isStreamInitialized() || !mActiveTracks.readAndClearHasChanged()) {
         return {}; // nothing to do
     }
     StreamOutHalInterface::SourceMetadata metadata;
     auto backInserter = std::back_inserter(metadata.tracks);
-    for (const sp<Track> &track : mActiveTracks) {
+    for (const sp<IAfTrack>& track : mActiveTracks) {
         // No track is invalid as this is called after prepareTrack_l in the same critical section
         track->copyMetadataTo(backInserter);
     }
@@ -3233,13 +3315,14 @@
     return change;
 }
 
-void AudioFlinger::PlaybackThread::sendMetadataToBackend_l(
+void PlaybackThread::sendMetadataToBackend_l(
         const StreamOutHalInterface::SourceMetadata& metadata)
 {
     mOutput->stream->updateSourceMetadata(metadata);
 };
 
-status_t AudioFlinger::PlaybackThread::getRenderPosition(uint32_t *halFrames, uint32_t *dspFrames)
+status_t PlaybackThread::getRenderPosition(
+        uint32_t* halFrames, uint32_t* dspFrames) const
 {
     if (halFrames == NULL || dspFrames == NULL) {
         return BAD_VALUE;
@@ -3266,7 +3349,7 @@
     }
 }
 
-product_strategy_t AudioFlinger::PlaybackThread::getStrategyForSession_l(audio_session_t sessionId)
+product_strategy_t PlaybackThread::getStrategyForSession_l(audio_session_t sessionId) const
 {
     // session AUDIO_SESSION_OUTPUT_MIX is placed in same strategy as MUSIC stream so that
     // it is moved to correct output by audio policy manager when A2DP is connected or disconnected
@@ -3274,7 +3357,7 @@
         return getStrategyForStream(AUDIO_STREAM_MUSIC);
     }
     for (size_t i = 0; i < mTracks.size(); i++) {
-        sp<Track> track = mTracks[i];
+        sp<IAfTrack> track = mTracks[i];
         if (sessionId == track->sessionId() && !track->isInvalid()) {
             return getStrategyForStream(track->streamType());
         }
@@ -3283,13 +3366,13 @@
 }
 
 
-AudioStreamOut* AudioFlinger::PlaybackThread::getOutput() const
+AudioStreamOut* PlaybackThread::getOutput() const
 {
     Mutex::Autolock _l(mLock);
     return mOutput;
 }
 
-AudioStreamOut* AudioFlinger::PlaybackThread::clearOutput()
+AudioStreamOut* PlaybackThread::clearOutput()
 {
     Mutex::Autolock _l(mLock);
     AudioStreamOut *output = mOutput;
@@ -3303,7 +3386,7 @@
 }
 
 // this method must always be called either with ThreadBase mLock held or inside the thread loop
-sp<StreamHalInterface> AudioFlinger::PlaybackThread::stream() const
+sp<StreamHalInterface> PlaybackThread::stream() const
 {
     if (mOutput == NULL) {
         return NULL;
@@ -3311,12 +3394,12 @@
     return mOutput->stream;
 }
 
-uint32_t AudioFlinger::PlaybackThread::activeSleepTimeUs() const
+uint32_t PlaybackThread::activeSleepTimeUs() const
 {
     return (uint32_t)((uint32_t)((mNormalFrameCount * 1000) / mSampleRate) * 1000);
 }
 
-status_t AudioFlinger::PlaybackThread::setSyncEvent(const sp<audioflinger::SyncEvent>& event)
+status_t PlaybackThread::setSyncEvent(const sp<SyncEvent>& event)
 {
     if (!isValidSyncEvent(event)) {
         return BAD_VALUE;
@@ -3325,7 +3408,7 @@
     Mutex::Autolock _l(mLock);
 
     for (size_t i = 0; i < mTracks.size(); ++i) {
-        sp<Track> track = mTracks[i];
+        sp<IAfTrack> track = mTracks[i];
         if (event->triggerSession() == track->sessionId()) {
             (void) track->setSyncEvent(event);
             return NO_ERROR;
@@ -3335,14 +3418,13 @@
     return NAME_NOT_FOUND;
 }
 
-bool AudioFlinger::PlaybackThread::isValidSyncEvent(
-        const sp<audioflinger::SyncEvent>& event) const
+bool PlaybackThread::isValidSyncEvent(const sp<SyncEvent>& event) const
 {
     return event->type() == AudioSystem::SYNC_EVENT_PRESENTATION_COMPLETE;
 }
 
-void AudioFlinger::PlaybackThread::threadLoop_removeTracks(
-        [[maybe_unused]] const Vector< sp<Track> >& tracksToRemove)
+void PlaybackThread::threadLoop_removeTracks(
+        [[maybe_unused]] const Vector<sp<IAfTrack>>& tracksToRemove)
 {
     // Miscellaneous track cleanup when removed from the active list,
     // called without Thread lock but synchronized with threadLoop processing.
@@ -3356,7 +3438,7 @@
 #endif
 }
 
-void AudioFlinger::PlaybackThread::checkSilentMode_l()
+void PlaybackThread::checkSilentMode_l()
 {
     if (!mMasterMute) {
         char value[PROPERTY_VALUE_MAX];
@@ -3382,7 +3464,7 @@
 }
 
 // shared by MIXER and DIRECT, overridden by DUPLICATING
-ssize_t AudioFlinger::PlaybackThread::threadLoop_write()
+ssize_t PlaybackThread::threadLoop_write()
 {
     LOG_HIST_TS();
     mInWrite = true;
@@ -3396,7 +3478,7 @@
 
         ATRACE_BEGIN("write");
         // update the setpoint when AudioFlinger::mScreenState changes
-        uint32_t screenState = AudioFlinger::mScreenState;
+        const uint32_t screenState = mAfThreadCallback->getScreenState();
         if (screenState != mScreenState) {
             mScreenState = screenState;
             MonoPipe *pipe = (MonoPipe *)mPipeSink.get();
@@ -3454,7 +3536,7 @@
 }
 
 // startMelComputation_l() must be called with AudioFlinger::mLock held
-void AudioFlinger::PlaybackThread::startMelComputation_l(
+void PlaybackThread::startMelComputation_l(
         const sp<audio_utils::MelProcessor>& processor)
 {
     auto outputSink = static_cast<AudioStreamOutSink*>(mOutputSink.get());
@@ -3464,7 +3546,7 @@
 }
 
 // stopMelComputation_l() must be called with AudioFlinger::mLock held
-void AudioFlinger::PlaybackThread::stopMelComputation_l()
+void PlaybackThread::stopMelComputation_l()
 {
     auto outputSink = static_cast<AudioStreamOutSink*>(mOutputSink.get());
     if (outputSink != nullptr) {
@@ -3472,7 +3554,7 @@
     }
 }
 
-void AudioFlinger::PlaybackThread::threadLoop_drain()
+void PlaybackThread::threadLoop_drain()
 {
     bool supportsDrain = false;
     if (mOutput->stream->supportsDrain(&supportsDrain) == OK && supportsDrain) {
@@ -3488,12 +3570,12 @@
     }
 }
 
-void AudioFlinger::PlaybackThread::threadLoop_exit()
+void PlaybackThread::threadLoop_exit()
 {
     {
         Mutex::Autolock _l(mLock);
         for (size_t i = 0; i < mTracks.size(); i++) {
-            sp<Track> track = mTracks[i];
+            sp<IAfTrack> track = mTracks[i];
             track->invalidate();
         }
         // Clear ActiveTracks to update BatteryNotifier in case active tracks remain.
@@ -3524,13 +3606,13 @@
  - idle sleep time
 */
 
-void AudioFlinger::PlaybackThread::cacheParameters_l()
+void PlaybackThread::cacheParameters_l()
 {
     mSinkBufferSize = mNormalFrameCount * mFrameSize;
     mActiveSleepTimeUs = activeSleepTimeUs();
     mIdleSleepTimeUs = idleSleepTimeUs();
 
-    mStandbyDelayNs = AudioFlinger::mStandbyTimeInNsecs;
+    mStandbyDelayNs = getStandbyTimeInNanos();
 
     // make sure standby delay is not too short when connected to an A2DP sink to avoid
     // truncating audio when going to standby.
@@ -3541,14 +3623,14 @@
     }
 }
 
-bool AudioFlinger::PlaybackThread::invalidateTracks_l(audio_stream_type_t streamType)
+bool PlaybackThread::invalidateTracks_l(audio_stream_type_t streamType)
 {
     ALOGV("MixerThread::invalidateTracks() mixer %p, streamType %d, mTracks.size %zu",
             this,  streamType, mTracks.size());
     bool trackMatch = false;
     size_t size = mTracks.size();
     for (size_t i = 0; i < size; i++) {
-        sp<Track> t = mTracks[i];
+        sp<IAfTrack> t = mTracks[i];
         if (t->streamType() == streamType && t->isExternalTrack()) {
             t->invalidate();
             trackMatch = true;
@@ -3557,22 +3639,22 @@
     return trackMatch;
 }
 
-void AudioFlinger::PlaybackThread::invalidateTracks(audio_stream_type_t streamType)
+void PlaybackThread::invalidateTracks(audio_stream_type_t streamType)
 {
     Mutex::Autolock _l(mLock);
     invalidateTracks_l(streamType);
 }
 
-void AudioFlinger::PlaybackThread::invalidateTracks(std::set<audio_port_handle_t>& portIds) {
+void PlaybackThread::invalidateTracks(std::set<audio_port_handle_t>& portIds) {
     Mutex::Autolock _l(mLock);
     invalidateTracks_l(portIds);
 }
 
-bool AudioFlinger::PlaybackThread::invalidateTracks_l(std::set<audio_port_handle_t>& portIds) {
+bool PlaybackThread::invalidateTracks_l(std::set<audio_port_handle_t>& portIds) {
     bool trackMatch = false;
     const size_t size = mTracks.size();
     for (size_t i = 0; i < size; i++) {
-        sp<Track> t = mTracks[i];
+        sp<IAfTrack> t = mTracks[i];
         if (t->isExternalTrack() && portIds.find(t->portId()) != portIds.end()) {
             t->invalidate();
             portIds.erase(t->portId());
@@ -3586,7 +3668,7 @@
 }
 
 // getTrackById_l must be called with holding thread lock
-AudioFlinger::PlaybackThread::Track* AudioFlinger::PlaybackThread::getTrackById_l(
+IAfTrack* PlaybackThread::getTrackById_l(
         audio_port_handle_t trackPortId) {
     for (size_t i = 0; i < mTracks.size(); i++) {
         if (mTracks[i]->portId() == trackPortId) {
@@ -3596,7 +3678,7 @@
     return nullptr;
 }
 
-status_t AudioFlinger::PlaybackThread::addEffectChain_l(const sp<IAfEffectChain>& chain)
+status_t PlaybackThread::addEffectChain_l(const sp<IAfEffectChain>& chain)
 {
     audio_session_t session = chain->sessionId();
     sp<EffectBufferHalInterface> halInBuffer, halOutBuffer;
@@ -3617,12 +3699,12 @@
             }
             size_t numSamples = mNormalFrameCount
                     * (audio_channel_count_from_out_mask(channelMask) + mHapticChannelCount);
-            status_t result = mAudioFlinger->mEffectsFactoryHal->allocateBuffer(
+            status_t result = mAfThreadCallback->getEffectsFactoryHal()->allocateBuffer(
                     numSamples * sizeof(float),
                     &halInBuffer);
             if (result != OK) return result;
 
-            result = mAudioFlinger->mEffectsFactoryHal->mirrorBuffer(
+            result = mAfThreadCallback->getEffectsFactoryHal()->mirrorBuffer(
                     isSessionSpatialized ? mEffectBuffer : mPostSpatializerBuffer,
                     isSessionSpatialized ? mEffectBufferSize : mPostSpatializerBufferSize,
                     &halOutBuffer);
@@ -3637,10 +3719,10 @@
             // - OUTPUT_STAGE session uses the mEffectBuffer as input buffer and
             // mPostSpatializerBuffer as output buffer
             // - DEVICE session uses the mPostSpatializerBuffer as input and output buffer.
-            status_t result = mAudioFlinger->mEffectsFactoryHal->mirrorBuffer(
+            status_t result = mAfThreadCallback->getEffectsFactoryHal()->mirrorBuffer(
                     mEffectBuffer, mEffectBufferSize, &halInBuffer);
             if (result != OK) return result;
-            result = mAudioFlinger->mEffectsFactoryHal->mirrorBuffer(
+            result = mAfThreadCallback->getEffectsFactoryHal()->mirrorBuffer(
                     mPostSpatializerBuffer, mPostSpatializerBufferSize, &halOutBuffer);
             if (result != OK) return result;
 
@@ -3649,7 +3731,7 @@
             }
         }
     } else {
-        status_t result = mAudioFlinger->mEffectsFactoryHal->mirrorBuffer(
+        status_t result = mAfThreadCallback->getEffectsFactoryHal()->mirrorBuffer(
                 mEffectBufferEnabled ? mEffectBuffer : mSinkBuffer,
                 mEffectBufferEnabled ? mEffectBufferSize : mSinkBufferSize,
                 &halInBuffer);
@@ -3665,7 +3747,8 @@
                 size_t numSamples = mNormalFrameCount
                         * (audio_channel_count_from_out_mask(mMixerChannelMask)
                                                              + mHapticChannelCount);
-                const status_t allocateStatus = mAudioFlinger->mEffectsFactoryHal->allocateBuffer(
+                const status_t allocateStatus =
+                        mAfThreadCallback->getEffectsFactoryHal()->allocateBuffer(
                         numSamples * sizeof(float),
                         &halInBuffer);
                 if (allocateStatus != OK) return allocateStatus;
@@ -3680,7 +3763,7 @@
     if (!audio_is_global_session(session)) {
         // Attach all tracks with same session ID to this chain.
         for (size_t i = 0; i < mTracks.size(); ++i) {
-            sp<Track> track = mTracks[i];
+            sp<IAfTrack> track = mTracks[i];
             if (session == track->sessionId()) {
                 ALOGV("addEffectChain_l() track->setMainBuffer track %p buffer %p",
                         track.get(), buffer);
@@ -3690,7 +3773,7 @@
         }
 
         // indicate all active tracks in the chain
-        for (const sp<Track> &track : mActiveTracks) {
+        for (const sp<IAfTrack>& track : mActiveTracks) {
             if (session == track->sessionId()) {
                 ALOGV("addEffectChain_l() activating track %p on session %d",
                         track.get(), session);
@@ -3732,7 +3815,7 @@
     return NO_ERROR;
 }
 
-size_t AudioFlinger::PlaybackThread::removeEffectChain_l(const sp<IAfEffectChain>& chain)
+size_t PlaybackThread::removeEffectChain_l(const sp<IAfEffectChain>& chain)
 {
     audio_session_t session = chain->sessionId();
 
@@ -3742,7 +3825,7 @@
         if (chain == mEffectChains[i]) {
             mEffectChains.removeAt(i);
             // detach all active tracks from the chain
-            for (const sp<Track> &track : mActiveTracks) {
+            for (const sp<IAfTrack>& track : mActiveTracks) {
                 if (session == track->sessionId()) {
                     ALOGV("removeEffectChain_l(): stopping track on chain %p for session Id: %d",
                             chain.get(), session);
@@ -3752,7 +3835,7 @@
 
             // detach all tracks with same session ID from this chain
             for (size_t j = 0; j < mTracks.size(); ++j) {
-                sp<Track> track = mTracks[j];
+                sp<IAfTrack> track = mTracks[j];
                 if (session == track->sessionId()) {
                     track->setMainBuffer(reinterpret_cast<float*>(mSinkBuffer));
                     chain->decTrackCnt();
@@ -3764,15 +3847,15 @@
     return mEffectChains.size();
 }
 
-status_t AudioFlinger::PlaybackThread::attachAuxEffect(
-        const sp<AudioFlinger::PlaybackThread::Track>& track, int EffectId)
+status_t PlaybackThread::attachAuxEffect(
+        const sp<IAfTrack>& track, int EffectId)
 {
     Mutex::Autolock _l(mLock);
     return attachAuxEffect_l(track, EffectId);
 }
 
-status_t AudioFlinger::PlaybackThread::attachAuxEffect_l(
-        const sp<AudioFlinger::PlaybackThread::Track>& track, int EffectId)
+status_t PlaybackThread::attachAuxEffect_l(
+        const sp<IAfTrack>& track, int EffectId)
 {
     status_t status = NO_ERROR;
 
@@ -3794,22 +3877,22 @@
     return status;
 }
 
-void AudioFlinger::PlaybackThread::detachAuxEffect_l(int effectId)
+void PlaybackThread::detachAuxEffect_l(int effectId)
 {
     for (size_t i = 0; i < mTracks.size(); ++i) {
-        sp<Track> track = mTracks[i];
+        sp<IAfTrack> track = mTracks[i];
         if (track->auxEffectId() == effectId) {
             attachAuxEffect_l(track, 0);
         }
     }
 }
 
-bool AudioFlinger::PlaybackThread::threadLoop()
+bool PlaybackThread::threadLoop()
 NO_THREAD_SAFETY_ANALYSIS  // manual locking of AudioFlinger
 {
     aflog::setThreadWriter(mNBLogWriter.get());
 
-    Vector< sp<Track> > tracksToRemove;
+    Vector<sp<IAfTrack>> tracksToRemove;
 
     mStandbyTimeNs = systemTime();
     int64_t lastLoopCountWritten = -2; // never matches "previous" loop, when loopCount = 0.
@@ -3857,14 +3940,14 @@
     {
         // Log merge requests are performed during AudioFlinger binder transactions, but
         // that does not cover audio playback. It's requested here for that reason.
-        mAudioFlinger->requestLogMerge();
+        mAfThreadCallback->requestLogMerge();
 
         cpuStats.sample(myName);
 
         Vector<sp<IAfEffectChain>> effectChains;
         audio_session_t activeHapticSessionId = AUDIO_SESSION_NONE;
         bool isHapticSessionSpatialized = false;
-        std::vector<sp<Track>> activeTracks;
+        std::vector<sp<IAfTrack>> activeTracks;
 
         // If the device is AUDIO_DEVICE_OUT_BUS, check for downstream latency.
         //
@@ -3872,12 +3955,13 @@
         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) {
-                std::vector<PatchPanel::SoftwarePatch> swPatches;
+            if (mAfThreadCallback->mutex().tryLock() == NO_ERROR) {
+                std::vector<SoftwarePatch> swPatches;
                 double latencyMs = 0.; // not required; initialized for clang-tidy
                 status_t status = INVALID_OPERATION;
                 audio_patch_handle_t downstreamPatchHandle = AUDIO_PATCH_HANDLE_NONE;
-                if (mAudioFlinger->mPatchPanel.getDownstreamSoftwarePatches(id(), &swPatches) == OK
+                if (mAfThreadCallback->getPatchPanel()->getDownstreamSoftwarePatches(
+                                id(), &swPatches) == OK
                         && swPatches.size() > 0) {
                         status = swPatches[0].getLatencyMs_l(&latencyMs);
                         downstreamPatchHandle = swPatches[0].getPatchHandle();
@@ -3898,7 +3982,7 @@
                     }
                     mDownstreamLatencyStatMs.add(latencyMs);
                 }
-                mAudioFlinger->mLock.unlock();
+                mAfThreadCallback->mutex().unlock();
             }
         } else {
             if (lastDownstreamPatchHandle != AUDIO_PATCH_HANDLE_NONE) {
@@ -4082,14 +4166,15 @@
 
                     // Tally underrun frames as we are inserting 0s here.
                     for (const auto& track : activeTracks) {
-                        if (track->mFillingUpStatus == Track::FS_ACTIVE
+                        if (track->fillingStatus() == IAfTrack::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);
+                            track->audioTrackServerProxy()->tallyUnderrunFrames(
+                                    mNormalFrameCount);
                         }
                     }
                 }
@@ -4258,7 +4343,7 @@
         unlockEffectChains(effectChains);
 
         if (!metadataUpdate.playbackMetadataUpdate.empty()) {
-            mAudioFlinger->mMelReporter->updateMetadataForCsd(id(),
+            mAfThreadCallback->getMelReporter()->updateMetadataForCsd(id(),
                     metadataUpdate.playbackMetadataUpdate);
         }
 
@@ -4459,7 +4544,7 @@
     return false;
 }
 
-void AudioFlinger::PlaybackThread::collectTimestamps_l()
+void PlaybackThread::collectTimestamps_l()
 {
     if (mStandby) {
         mTimestampVerifier.discontinuity(discontinuityForStandbyOrFlush());
@@ -4564,10 +4649,10 @@
                     ? systemTime() : mLastIoBeginNs;
         }
 
-        for (const sp<Track> &t : mActiveTracks) {
+        for (const sp<IAfTrack>& t : mActiveTracks) {
             if (!t->isFastTrack()) {
                 t->updateTrackFrameInfo(
-                        t->mAudioTrackServerProxy->framesReleased(),
+                        t->audioTrackServerProxy()->framesReleased(),
                         mFramesWritten,
                         mSampleRate,
                         mTimestamp);
@@ -4595,7 +4680,7 @@
 }
 
 // removeTracks_l() must be called with ThreadBase::mLock held
-void AudioFlinger::PlaybackThread::removeTracks_l(const Vector< sp<Track> >& tracksToRemove)
+void PlaybackThread::removeTracks_l(const Vector<sp<IAfTrack>>& tracksToRemove)
 NO_THREAD_SAFETY_ANALYSIS  // release and re-acquire mLock
 {
     for (const auto& track : tracksToRemove) {
@@ -4625,7 +4710,7 @@
             mLock.unlock();
             // Unlock due to VibratorService will lock for this call and will
             // call Tracks.mute/unmute which also require thread's lock.
-            AudioFlinger::onExternalVibrationStop(track->getExternalVibration());
+            afutils::onExternalVibrationStop(track->getExternalVibration());
             mLock.lock();
 
             // When the track is stop, set the haptic intensity as MUTE
@@ -4637,7 +4722,7 @@
     }
 }
 
-status_t AudioFlinger::PlaybackThread::getTimestamp_l(AudioTimestamp& timestamp)
+status_t PlaybackThread::getTimestamp_l(AudioTimestamp& timestamp)
 {
     if (mNormalSink != 0) {
         ExtendedTimestamp ets;
@@ -4666,7 +4751,7 @@
 // All tracks attached to a mixer with flag VOIP_RX are tied to the same
 // stream type STREAM_VOICE_CALL so this will only change the HAL volume once even
 // if more than one track are active
-status_t AudioFlinger::PlaybackThread::handleVoipVolume_l(float *volume)
+status_t PlaybackThread::handleVoipVolume_l(float* volume)
 {
     status_t result = NO_ERROR;
     if ((mOutput->flags & AUDIO_OUTPUT_FLAG_VOIP_RX) != 0) {
@@ -4688,7 +4773,7 @@
     return result;
 }
 
-status_t AudioFlinger::MixerThread::createAudioPatch_l(const struct audio_patch *patch,
+status_t MixerThread::createAudioPatch_l(const struct audio_patch* patch,
                                                           audio_patch_handle_t *handle)
 {
     status_t status;
@@ -4705,7 +4790,7 @@
     return status;
 }
 
-status_t AudioFlinger::PlaybackThread::createAudioPatch_l(const struct audio_patch *patch,
+status_t PlaybackThread::createAudioPatch_l(const struct audio_patch *patch,
                                                           audio_patch_handle_t *handle)
 {
     status_t status = NO_ERROR;
@@ -4789,7 +4874,7 @@
     return status;
 }
 
-status_t AudioFlinger::MixerThread::releaseAudioPatch_l(const audio_patch_handle_t handle)
+status_t MixerThread::releaseAudioPatch_l(const audio_patch_handle_t handle)
 {
     status_t status;
     if (property_get_bool("af.patch_park", false /* default_value */)) {
@@ -4803,7 +4888,7 @@
     return status;
 }
 
-status_t AudioFlinger::PlaybackThread::releaseAudioPatch_l(const audio_patch_handle_t handle)
+status_t PlaybackThread::releaseAudioPatch_l(const audio_patch_handle_t handle)
 {
     status_t status = NO_ERROR;
 
@@ -4822,19 +4907,19 @@
     return status;
 }
 
-void AudioFlinger::PlaybackThread::addPatchTrack(const sp<PatchTrack>& track)
+void PlaybackThread::addPatchTrack(const sp<IAfPatchTrack>& track)
 {
     Mutex::Autolock _l(mLock);
     mTracks.add(track);
 }
 
-void AudioFlinger::PlaybackThread::deletePatchTrack(const sp<PatchTrack>& track)
+void PlaybackThread::deletePatchTrack(const sp<IAfPatchTrack>& track)
 {
     Mutex::Autolock _l(mLock);
     destroyTrack_l(track);
 }
 
-void AudioFlinger::PlaybackThread::toAudioPortConfig(struct audio_port_config *config)
+void PlaybackThread::toAudioPortConfig(struct audio_port_config* config)
 {
     ThreadBase::toAudioPortConfig(config);
     config->role = AUDIO_PORT_ROLE_SOURCE;
@@ -4848,9 +4933,16 @@
 
 // ----------------------------------------------------------------------------
 
-AudioFlinger::MixerThread::MixerThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output,
+/* static */
+sp<IAfPlaybackThread> IAfPlaybackThread::createMixerThread(
+        const sp<IAfThreadCallback>& afThreadCallback, AudioStreamOut* output,
+        audio_io_handle_t id, bool systemReady, type_t type, audio_config_base_t* mixerConfig) {
+    return sp<MixerThread>::make(afThreadCallback, output, id, systemReady, type, mixerConfig);
+}
+
+MixerThread::MixerThread(const sp<IAfThreadCallback>& afThreadCallback, AudioStreamOut* output,
         audio_io_handle_t id, bool systemReady, type_t type, audio_config_base_t *mixerConfig)
-    :   PlaybackThread(audioFlinger, output, id, type, systemReady, mixerConfig),
+    :   PlaybackThread(afThreadCallback, output, id, type, systemReady, mixerConfig),
         // mAudioMixer below
         // mFastMixer below
         mBluetoothLatencyModesEnabled(false),
@@ -4860,7 +4952,7 @@
         // mPipeSink below
         // mNormalSink below
 {
-    setMasterBalance(audioFlinger->getMasterBalance_l());
+    setMasterBalance(afThreadCallback->getMasterBalance_l());
     ALOGV("MixerThread() id=%d type=%d", id, type);
     ALOGV("mSampleRate=%u, mChannelMask=%#x, mChannelCount=%u, mFormat=%#x, mFrameSize=%zu, "
             "mFrameCount=%zu, mNormalFrameCount=%zu",
@@ -4987,7 +5079,7 @@
         state->mColdFutexAddr = &mFastMixerFutex;
         state->mColdGen++;
         state->mDumpState = &mFastMixerDumpState;
-        mFastMixerNBLogWriter = audioFlinger->newWriter_l(kFastMixerLogSize, "FastMixer");
+        mFastMixerNBLogWriter = afThreadCallback->newWriter_l(kFastMixerLogSize, "FastMixer");
         state->mNBLogWriter = mFastMixerNBLogWriter.get();
         sq->end();
         sq->push(FastMixerStateQueue::BLOCK_UNTIL_PUSHED);
@@ -5033,7 +5125,7 @@
     }
 }
 
-AudioFlinger::MixerThread::~MixerThread()
+MixerThread::~MixerThread()
 {
     if (mFastMixer != 0) {
         FastMixerStateQueue *sq = mFastMixer->sq();
@@ -5066,11 +5158,11 @@
         }
 #endif
     }
-    mAudioFlinger->unregisterWriter(mFastMixerNBLogWriter);
+    mAfThreadCallback->unregisterWriter(mFastMixerNBLogWriter);
     delete mAudioMixer;
 }
 
-void AudioFlinger::MixerThread::onFirstRef() {
+void MixerThread::onFirstRef() {
     PlaybackThread::onFirstRef();
 
     Mutex::Autolock _l(mLock);
@@ -5086,7 +5178,7 @@
     }
 }
 
-uint32_t AudioFlinger::MixerThread::correctLatency_l(uint32_t latency) const
+uint32_t MixerThread::correctLatency_l(uint32_t latency) const
 {
     if (mFastMixer != 0) {
         MonoPipe *pipe = (MonoPipe *)mPipeSink.get();
@@ -5095,7 +5187,7 @@
     return latency;
 }
 
-ssize_t AudioFlinger::MixerThread::threadLoop_write()
+ssize_t MixerThread::threadLoop_write()
 {
     // FIXME we should only do one push per cycle; confirm this is true
     // Start the fast mixer if it's not already running
@@ -5123,7 +5215,7 @@
             }
             state->mCommand = FastMixerState::MIX_WRITE;
 #ifdef FAST_THREAD_STATISTICS
-            mFastMixerDumpState.increaseSamplingN(mAudioFlinger->isLowRamDevice() ?
+            mFastMixerDumpState.increaseSamplingN(mAfThreadCallback->isLowRamDevice() ?
                 FastThreadDumpState::kSamplingNforLowRamDevice : FastThreadDumpState::kSamplingN);
 #endif
             sq->end();
@@ -5138,7 +5230,7 @@
     return PlaybackThread::threadLoop_write();
 }
 
-void AudioFlinger::MixerThread::threadLoop_standby()
+void MixerThread::threadLoop_standby()
 {
     // Idle the fast mixer if it's currently running
     if (mFastMixer != 0) {
@@ -5176,24 +5268,24 @@
     PlaybackThread::threadLoop_standby();
 }
 
-bool AudioFlinger::PlaybackThread::waitingAsyncCallback_l()
+bool PlaybackThread::waitingAsyncCallback_l()
 {
     return false;
 }
 
-bool AudioFlinger::PlaybackThread::shouldStandby_l()
+bool PlaybackThread::shouldStandby_l()
 {
     return !mStandby;
 }
 
-bool AudioFlinger::PlaybackThread::waitingAsyncCallback()
+bool PlaybackThread::waitingAsyncCallback()
 {
     Mutex::Autolock _l(mLock);
     return waitingAsyncCallback_l();
 }
 
 // shared by MIXER and DIRECT, overridden by DUPLICATING
-void AudioFlinger::PlaybackThread::threadLoop_standby()
+void PlaybackThread::threadLoop_standby()
 {
     ALOGV("Audio hardware entering standby, mixer %p, suspend count %d", this, mSuspended);
     mOutput->standby();
@@ -5209,20 +5301,20 @@
     setHalLatencyMode_l();
 }
 
-void AudioFlinger::PlaybackThread::onAddNewTrack_l()
+void PlaybackThread::onAddNewTrack_l()
 {
     ALOGV("signal playback thread");
     broadcast_l();
 }
 
-void AudioFlinger::PlaybackThread::onAsyncError()
+void PlaybackThread::onAsyncError()
 {
     for (int i = AUDIO_STREAM_SYSTEM; i < (int)AUDIO_STREAM_CNT; i++) {
         invalidateTracks((audio_stream_type_t)i);
     }
 }
 
-void AudioFlinger::MixerThread::threadLoop_mix()
+void MixerThread::threadLoop_mix()
 {
     // mix buffers...
     mAudioMixer->process();
@@ -5240,7 +5332,7 @@
 
 }
 
-void AudioFlinger::MixerThread::threadLoop_sleepTime()
+void MixerThread::threadLoop_sleepTime()
 {
     // If no tracks are ready, sleep once for the duration of an output
     // buffer size, then write 0s to the output
@@ -5294,8 +5386,8 @@
 }
 
 // prepareTracks_l() must be called with ThreadBase::mLock held
-AudioFlinger::PlaybackThread::mixer_state AudioFlinger::MixerThread::prepareTracks_l(
-        Vector< sp<Track> > *tracksToRemove)
+PlaybackThread::mixer_state MixerThread::prepareTracks_l(
+        Vector<sp<IAfTrack>>* tracksToRemove)
 {
     // clean up deleted track ids in AudioMixer before allocating new tracks
     (void)mTracks.processDeletedTrackIds([this](int trackId) {
@@ -5371,23 +5463,23 @@
         // tallyUnderrunFrames() is called to update the track counters
         // with the number of underrun frames for a particular mixer period.
         // We defer tallying until we know the final mixer status.
-        void tallyUnderrunFrames(const sp<Track>& track, size_t underrunFrames) {
+        void tallyUnderrunFrames(const sp<IAfTrack>& track, size_t underrunFrames) {
             mUnderrunFrames.emplace_back(track, underrunFrames);
         }
 
     private:
         const mixer_state * const mMixerStatus;
         ThreadMetrics * const mThreadMetrics;
-        std::vector<std::pair<sp<Track>, size_t>> mUnderrunFrames;
+        std::vector<std::pair<sp<IAfTrack>, size_t>> mUnderrunFrames;
     } deferredOperations(&mixerStatus, &mThreadMetrics);
     // implicit nested scope for variable capture
 
     bool noFastHapticTrack = true;
     for (size_t i=0 ; i<count ; i++) {
-        const sp<Track> t = mActiveTracks[i];
+        const sp<IAfTrack> t = mActiveTracks[i];
 
         // this const just means the local variable doesn't change
-        Track* const track = t.get();
+        IAfTrack* const track = t.get();
 
         // process fast tracks
         if (track->isFastTrack()) {
@@ -5405,7 +5497,7 @@
             // The converse, of removing an (active) track and then creating a new track
             // at the identical fast mixer slot within the same normal mix cycle,
             // is impossible because the slot isn't marked available until the end of each cycle.
-            int j = track->mFastIndex;
+            int j = track->fastIndex();
             ALOG_ASSERT(0 < j && j < (int)FastMixerState::sMaxFastTracks);
             ALOG_ASSERT(!(mFastTrackAvailMask & (1 << j)));
             FastTrack *fastTrack = &state->mFastTracks[j];
@@ -5415,13 +5507,13 @@
             FastTrackDump *ftDump = &mFastMixerDumpState.mTracks[j];
             FastTrackUnderruns underruns = ftDump->mUnderruns;
             uint32_t recentFull = (underruns.mBitFields.mFull -
-                    track->mObservedUnderruns.mBitFields.mFull) & UNDERRUN_MASK;
+                    track->fastTrackUnderruns().mBitFields.mFull) & UNDERRUN_MASK;
             uint32_t recentPartial = (underruns.mBitFields.mPartial -
-                    track->mObservedUnderruns.mBitFields.mPartial) & UNDERRUN_MASK;
+                    track->fastTrackUnderruns().mBitFields.mPartial) & UNDERRUN_MASK;
             uint32_t recentEmpty = (underruns.mBitFields.mEmpty -
-                    track->mObservedUnderruns.mBitFields.mEmpty) & UNDERRUN_MASK;
+                    track->fastTrackUnderruns().mBitFields.mEmpty) & UNDERRUN_MASK;
             uint32_t recentUnderruns = recentPartial + recentEmpty;
-            track->mObservedUnderruns = underruns;
+            track->fastTrackUnderruns() = underruns;
             // don't count underruns that occur while stopping or pausing
             // or stopped which can occur when flush() is called while active
             size_t underrunFrames = 0;
@@ -5431,30 +5523,30 @@
                 underrunFrames = recentUnderruns * mFrameCount;
             }
             // Immediately account for FastTrack underruns.
-            track->mAudioTrackServerProxy->tallyUnderrunFrames(underrunFrames);
+            track->audioTrackServerProxy()->tallyUnderrunFrames(underrunFrames);
 
             // This is similar to the state machine for normal tracks,
             // with a few modifications for fast tracks.
             bool isActive = true;
-            switch (track->mState) {
-            case TrackBase::STOPPING_1:
+            switch (track->state()) {
+            case IAfTrackBase::STOPPING_1:
                 // track stays active in STOPPING_1 state until first underrun
                 if (recentUnderruns > 0 || track->isTerminated()) {
-                    track->mState = TrackBase::STOPPING_2;
+                    track->setState(IAfTrackBase::STOPPING_2);
                 }
                 break;
-            case TrackBase::PAUSING:
+            case IAfTrackBase::PAUSING:
                 // ramp down is not yet implemented
                 track->setPaused();
                 break;
-            case TrackBase::RESUMING:
+            case IAfTrackBase::RESUMING:
                 // ramp up is not yet implemented
-                track->mState = TrackBase::ACTIVE;
+                track->setState(IAfTrackBase::ACTIVE);
                 break;
-            case TrackBase::ACTIVE:
+            case IAfTrackBase::ACTIVE:
                 if (recentFull > 0 || recentPartial > 0) {
                     // track has provided at least some frames recently: reset retry count
-                    track->mRetryCount = kMaxTrackRetries;
+                    track->retryCount() = kMaxTrackRetries;
                 }
                 if (recentUnderruns == 0) {
                     // no recent underruns: stay active
@@ -5468,7 +5560,7 @@
                         break;
                     }
                     // there has recently been an "empty" underrun: decrement the retry counter
-                    if (--(track->mRetryCount) > 0) {
+                    if (--(track->retryCount()) > 0) {
                         break;
                     }
                     // indicate to client process that the track was disabled because of underrun;
@@ -5479,10 +5571,10 @@
                     break;
                 }
                 FALLTHROUGH_INTENDED;
-            case TrackBase::STOPPING_2:
-            case TrackBase::PAUSED:
-            case TrackBase::STOPPED:
-            case TrackBase::FLUSHED:   // flush() while active
+            case IAfTrackBase::STOPPING_2:
+            case IAfTrackBase::PAUSED:
+            case IAfTrackBase::STOPPED:
+            case IAfTrackBase::FLUSHED:   // flush() while active
                 // Check for presentation complete if track is inactive
                 // We have consumed all the buffers of this track.
                 // This would be incomplete if we auto-paused on underrun
@@ -5499,7 +5591,7 @@
                     }
                 }
                 if (track->isStopping_2()) {
-                    track->mState = TrackBase::STOPPED;
+                    track->setState(IAfTrackBase::STOPPED);
                 }
                 if (track->isStopped()) {
                     // Can't reset directly, as fast mixer is still polling this track
@@ -5509,20 +5601,20 @@
                 }
                 isActive = false;
                 break;
-            case TrackBase::IDLE:
+            case IAfTrackBase::IDLE:
             default:
-                LOG_ALWAYS_FATAL("unexpected track state %d", (int)track->mState);
+                LOG_ALWAYS_FATAL("unexpected track state %d", (int)track->state());
             }
 
             if (isActive) {
                 // was it previously inactive?
                 if (!(state->mTrackMask & (1 << j))) {
-                    ExtendedAudioBufferProvider *eabp = track;
-                    VolumeProvider *vp = track;
+                    ExtendedAudioBufferProvider *eabp = track->asExtendedAudioBufferProvider();
+                    VolumeProvider *vp = track->asVolumeProvider();
                     fastTrack->mBufferProvider = eabp;
                     fastTrack->mVolumeProvider = vp;
-                    fastTrack->mChannelMask = track->mChannelMask;
-                    fastTrack->mFormat = track->mFormat;
+                    fastTrack->mChannelMask = track->channelMask();
+                    fastTrack->mFormat = track->format();
                     fastTrack->mHapticPlaybackEnabled = track->getHapticPlaybackEnabled();
                     fastTrack->mHapticIntensity = track->getHapticIntensity();
                     fastTrack->mHapticMaxAmplitude = track->getHapticMaxAmplitude();
@@ -5531,7 +5623,7 @@
                     didModify = true;
                     // no acknowledgement required for newly active tracks
                 }
-                sp<AudioTrackServerProxy> proxy = track->mAudioTrackServerProxy;
+                sp<AudioTrackServerProxy> proxy = track->audioTrackServerProxy();
                 float volume;
                 if (track->isPlaybackRestricted() || mStreamTypes[track->streamType()].mute) {
                     volume = 0.f;
@@ -5546,12 +5638,12 @@
                 const float vh = track->getVolumeHandler()->getVolume(
                     proxy->framesReleased()).first;
                 volume *= vh;
-                track->mCachedVolume = volume;
+                track->setCachedVolume(volume);
                 gain_minifloat_packed_t vlr = proxy->getVolumeLR();
                 float vlf = float_from_gain(gain_minifloat_unpack_left(vlr));
                 float vrf = float_from_gain(gain_minifloat_unpack_right(vlr));
 
-                track->processMuteEvent_l(mAudioFlinger->getOrCreateAudioManager(),
+                track->processMuteEvent_l(mAfThreadCallback->getOrCreateAudioManager(),
                     /*muteState=*/{masterVolume == 0.f,
                                    mStreamTypes[track->streamType()].volume == 0.f,
                                    mStreamTypes[track->streamType()].mute,
@@ -5582,13 +5674,13 @@
                     // TODO Remove the ALOGW when this theory is confirmed.
                     ALOGW("fast track %d should have been active; "
                             "mState=%d, mTrackMask=%#x, recentUnderruns=%u, isShared=%d",
-                            j, (int)track->mState, state->mTrackMask, recentUnderruns,
+                            j, (int)track->state(), state->mTrackMask, recentUnderruns,
                             track->sharedBuffer() != 0);
                     // Since the FastMixer state already has the track inactive, do nothing here.
                 }
                 tracksToRemove->add(track);
                 // Avoids a misleading display in dumpsys
-                track->mObservedUnderruns.mBitFields.mMostRecent = UNDERRUN_FULL;
+                track->fastTrackUnderruns().mBitFields.mMostRecent = UNDERRUN_FULL;
             }
             if (fastTrack->mHapticPlaybackEnabled != track->getHapticPlaybackEnabled()) {
                 fastTrack->mHapticPlaybackEnabled = track->getHapticPlaybackEnabled();
@@ -5610,14 +5702,14 @@
         if (!mAudioMixer->exists(trackId)) {
             status_t status = mAudioMixer->create(
                     trackId,
-                    track->mChannelMask,
-                    track->mFormat,
-                    track->mSessionId);
+                    track->channelMask(),
+                    track->format(),
+                    track->sessionId());
             if (status != OK) {
                 ALOGW("%s(): AudioMixer cannot create track(%d)"
                         " mask %#x, format %#x, sessionId %d",
                         __func__, trackId,
-                        track->mChannelMask, track->mFormat, track->mSessionId);
+                        track->channelMask(), track->format(), track->sessionId());
                 tracksToRemove->add(track);
                 track->invalidate(); // consider it dead.
                 continue;
@@ -5630,8 +5722,8 @@
         // hence the test on (mMixerStatus == MIXER_TRACKS_READY) meaning the track was mixed
         // during last round
         size_t desiredFrames;
-        const uint32_t sampleRate = track->mAudioTrackServerProxy->getSampleRate();
-        const AudioPlaybackRate playbackRate = track->mAudioTrackServerProxy->getPlaybackRate();
+        const uint32_t sampleRate = track->audioTrackServerProxy()->getSampleRate();
+        const AudioPlaybackRate playbackRate = track->audioTrackServerProxy()->getPlaybackRate();
 
         desiredFrames = sourceFramesNeededWithTimestretch(
                 sampleRate, mNormalFrameCount, mSampleRate, playbackRate.mSpeed);
@@ -5681,11 +5773,11 @@
 
 
             int param = AudioMixer::VOLUME;
-            if (track->mFillingUpStatus == Track::FS_FILLED) {
+            if (track->fillingStatus() == IAfTrack::FS_FILLED) {
                 // no ramp for the first volume setting
-                track->mFillingUpStatus = Track::FS_ACTIVE;
-                if (track->mState == TrackBase::RESUMING) {
-                    track->mState = TrackBase::ACTIVE;
+                track->fillingStatus() = IAfTrack::FS_ACTIVE;
+                if (track->state() == IAfTrackBase::RESUMING) {
+                    track->setState(IAfTrackBase::ACTIVE);
                     // If a new track is paused immediately after start, do not ramp on resume.
                     if (cblk->mServer != 0) {
                         param = AudioMixer::RAMP_VOLUME;
@@ -5706,9 +5798,9 @@
             // read original volumes with volume control
             float v = masterVolume * mStreamTypes[track->streamType()].volume;
             // Always fetch volumeshaper volume to ensure state is updated.
-            const sp<AudioTrackServerProxy> proxy = track->mAudioTrackServerProxy;
+            const sp<AudioTrackServerProxy> proxy = track->audioTrackServerProxy();
             const float vh = track->getVolumeHandler()->getVolume(
-                    track->mAudioTrackServerProxy->framesReleased()).first;
+                    track->audioTrackServerProxy()->framesReleased()).first;
 
             if (mStreamTypes[track->streamType()].mute || track->isPlaybackRestricted()) {
                 v = 0;
@@ -5734,7 +5826,7 @@
                     vrf = GAIN_FLOAT_UNITY;
                 }
 
-                track->processMuteEvent_l(mAudioFlinger->getOrCreateAudioManager(),
+                track->processMuteEvent_l(mAfThreadCallback->getOrCreateAudioManager(),
                     /*muteState=*/{masterVolume == 0.f,
                                    mStreamTypes[track->streamType()].volume == 0.f,
                                    mStreamTypes[track->streamType()].mute,
@@ -5770,18 +5862,18 @@
                 // Update remaining floating point volume levels
                 vlf = (float)vl / (1 << 24);
                 vrf = (float)vr / (1 << 24);
-                track->mHasVolumeController = true;
+                track->setHasVolumeController(true);
             } else {
                 // force no volume ramp when volume controller was just disabled or removed
                 // from effect chain to avoid volume spike
-                if (track->mHasVolumeController) {
+                if (track->hasVolumeController()) {
                     param = AudioMixer::VOLUME;
                 }
-                track->mHasVolumeController = false;
+                track->setHasVolumeController(false);
             }
 
             // XXX: these things DON'T need to be done each time
-            mAudioMixer->setBufferProvider(trackId, track);
+            mAudioMixer->setBufferProvider(trackId, track->asExtendedAudioBufferProvider());
             mAudioMixer->enable(trackId);
 
             mAudioMixer->setParameter(trackId, param, AudioMixer::VOLUME0, &vlf);
@@ -5889,13 +5981,14 @@
                 trackId,
                 AudioMixer::TRACK,
                 AudioMixer::HAPTIC_INTENSITY, (void *)(uintptr_t)track->getHapticIntensity());
+            const float hapticMaxAmplitude = track->getHapticMaxAmplitude();
             mAudioMixer->setParameter(
                 trackId,
                 AudioMixer::TRACK,
-                AudioMixer::HAPTIC_MAX_AMPLITUDE, (void *)(&(track->mHapticMaxAmplitude)));
+                AudioMixer::HAPTIC_MAX_AMPLITUDE, (void *)&hapticMaxAmplitude);
 
             // reset retry count
-            track->mRetryCount = kMaxTrackRetries;
+            track->retryCount() = kMaxTrackRetries;
 
             // If one track is ready, set the mixer ready if:
             //  - the mixer was not ready during previous round OR
@@ -5947,7 +6040,7 @@
             } else {
                 // No buffers for this track. Give it a few chances to
                 // fill a buffer, then remove it from active list.
-                if (--(track->mRetryCount) <= 0) {
+                if (--(track->retryCount()) <= 0) {
                     ALOGI("BUFFER TIMEOUT: remove(%d) from active list on thread %p",
                             trackId, this);
                     tracksToRemove->add(track);
@@ -6023,7 +6116,7 @@
         size_t i = __builtin_ctz(resetMask);
         ALOG_ASSERT(i < count);
         resetMask &= ~(1 << i);
-        sp<Track> track = mActiveTracks[i];
+        sp<IAfTrack> track = mActiveTracks[i];
         ALOG_ASSERT(track->isFastTrack() && track->isStopped());
         track->reset();
     }
@@ -6089,7 +6182,7 @@
 }
 
 // trackCountForUid_l() must be called with ThreadBase::mLock held
-uint32_t AudioFlinger::PlaybackThread::trackCountForUid_l(uid_t uid) const
+uint32_t PlaybackThread::trackCountForUid_l(uid_t uid) const
 {
     uint32_t trackCount = 0;
     for (size_t i = 0; i < mTracks.size() ; i++) {
@@ -6100,7 +6193,7 @@
     return trackCount;
 }
 
-bool AudioFlinger::PlaybackThread::IsTimestampAdvancing::check(AudioStreamOut * output)
+bool PlaybackThread::IsTimestampAdvancing::check(AudioStreamOut* output)
 {
     // Check the timestamp to see if it's advancing once every 150ms. If we check too frequently, we
     // could falsely detect that the frame position has stalled due to underrun because we haven't
@@ -6124,7 +6217,7 @@
     return mLatchedValue;
 }
 
-void AudioFlinger::PlaybackThread::IsTimestampAdvancing::clear()
+void PlaybackThread::IsTimestampAdvancing::clear()
 {
     mLatchedValue = true;
     mPreviousPosition = 0;
@@ -6132,7 +6225,7 @@
 }
 
 // isTrackAllowed_l() must be called with ThreadBase::mLock held
-bool AudioFlinger::MixerThread::isTrackAllowed_l(
+bool MixerThread::isTrackAllowed_l(
         audio_channel_mask_t channelMask, audio_format_t format,
         audio_session_t sessionId, uid_t uid) const
 {
@@ -6152,7 +6245,7 @@
 }
 
 // checkForNewParameter_l() must be called with ThreadBase::mLock held
-bool AudioFlinger::MixerThread::checkForNewParameter_l(const String8& keyValuePair,
+bool MixerThread::checkForNewParameter_l(const String8& keyValuePair,
                                                        status_t& status)
 {
     bool reconfig = false;
@@ -6166,7 +6259,7 @@
         reconfig = true;
     }
     if (param.getInt(String8(AudioParameter::keyFormat), value) == NO_ERROR) {
-        if (!isValidPcmSinkFormat((audio_format_t) value)) {
+        if (!isValidPcmSinkFormat(static_cast<audio_format_t>(value))) {
             status = BAD_VALUE;
         } else {
             // no need to save value, since it's constant
@@ -6174,7 +6267,7 @@
         }
     }
     if (param.getInt(String8(AudioParameter::keyChannels), value) == NO_ERROR) {
-        if (!isValidPcmSinkChannelMask((audio_channel_mask_t) value)) {
+        if (!isValidPcmSinkChannelMask(static_cast<audio_channel_mask_t>(value))) {
             status = BAD_VALUE;
         } else {
             // no need to save value, since it's constant
@@ -6215,14 +6308,14 @@
                 const int trackId = track->id();
                 const status_t createStatus = mAudioMixer->create(
                         trackId,
-                        track->mChannelMask,
-                        track->mFormat,
-                        track->mSessionId);
+                        track->channelMask(),
+                        track->format(),
+                        track->sessionId());
                 ALOGW_IF(createStatus != NO_ERROR,
                         "%s(): AudioMixer cannot create track(%d)"
                         " mask %#x, format %#x, sessionId %d",
                         __func__,
-                        trackId, track->mChannelMask, track->mFormat, track->mSessionId);
+                        trackId, track->channelMask(), track->format(), track->sessionId());
             }
             sendIoConfigEvent_l(AUDIO_OUTPUT_CONFIG_CHANGED);
         }
@@ -6232,7 +6325,7 @@
 }
 
 
-void AudioFlinger::MixerThread::dumpInternals_l(int fd, const Vector<String16>& args)
+void MixerThread::dumpInternals_l(int fd, const Vector<String16>& args)
 {
     PlaybackThread::dumpInternals_l(fd, args);
     dprintf(fd, "  Thread throttle time (msecs): %u\n", mThreadThrottleTimeMs);
@@ -6279,17 +6372,17 @@
      dprintf(fd, "Supported latency modes: %s\n", toString(mSupportedLatencyModes).c_str());
 }
 
-uint32_t AudioFlinger::MixerThread::idleSleepTimeUs() const
+uint32_t MixerThread::idleSleepTimeUs() const
 {
     return (uint32_t)(((mNormalFrameCount * 1000) / mSampleRate) * 1000) / 2;
 }
 
-uint32_t AudioFlinger::MixerThread::suspendSleepTimeUs() const
+uint32_t MixerThread::suspendSleepTimeUs() const
 {
     return (uint32_t)(((mNormalFrameCount * 1000) / mSampleRate) * 1000);
 }
 
-void AudioFlinger::MixerThread::cacheParameters_l()
+void MixerThread::cacheParameters_l()
 {
     PlaybackThread::cacheParameters_l();
 
@@ -6300,11 +6393,11 @@
     maxPeriod = seconds(mNormalFrameCount) / mSampleRate * 15;
 }
 
-void AudioFlinger::MixerThread::onHalLatencyModesChanged_l() {
-    mAudioFlinger->onSupportedLatencyModesChanged(mId, mSupportedLatencyModes);
+void MixerThread::onHalLatencyModesChanged_l() {
+    mAfThreadCallback->onSupportedLatencyModesChanged(mId, mSupportedLatencyModes);
 }
 
-void AudioFlinger::MixerThread::setHalLatencyMode_l() {
+void MixerThread::setHalLatencyMode_l() {
     // Only handle latency mode if:
     // - mBluetoothLatencyModesEnabled is true
     // - the HAL supports latency modes
@@ -6346,7 +6439,7 @@
     }
 }
 
-void AudioFlinger::MixerThread::updateHalSupportedLatencyModes_l() {
+void MixerThread::updateHalSupportedLatencyModes_l() {
 
     if (mOutput == nullptr || mOutput->stream == nullptr) {
         return;
@@ -6364,7 +6457,7 @@
     }
 }
 
-status_t AudioFlinger::MixerThread::getSupportedLatencyModes(
+status_t MixerThread::getSupportedLatencyModes(
         std::vector<audio_latency_mode_t>* modes) {
     if (modes == nullptr) {
         return BAD_VALUE;
@@ -6374,7 +6467,7 @@
     return NO_ERROR;
 }
 
-void AudioFlinger::MixerThread::onRecommendedLatencyModeChanged(
+void MixerThread::onRecommendedLatencyModeChanged(
         std::vector<audio_latency_mode_t> modes) {
     Mutex::Autolock _l(mLock);
     if (modes != mSupportedLatencyModes) {
@@ -6385,7 +6478,7 @@
     }
 }
 
-status_t AudioFlinger::MixerThread::setBluetoothVariableLatencyEnabled(bool enabled) {
+status_t MixerThread::setBluetoothVariableLatencyEnabled(bool enabled) {
     if (mOutput == nullptr || mOutput->audioHwDev == nullptr
             || !mOutput->audioHwDev->supportsBluetoothVariableLatency()) {
         return INVALID_OPERATION;
@@ -6396,27 +6489,36 @@
 
 // ----------------------------------------------------------------------------
 
-AudioFlinger::DirectOutputThread::DirectOutputThread(const sp<AudioFlinger>& audioFlinger,
+/* static */
+sp<IAfPlaybackThread> IAfPlaybackThread::createDirectOutputThread(
+        const sp<IAfThreadCallback>& afThreadCallback,
+        AudioStreamOut* output, audio_io_handle_t id, bool systemReady,
+        const audio_offload_info_t& offloadInfo) {
+    return sp<DirectOutputThread>::make(
+            afThreadCallback, output, id, systemReady, offloadInfo);
+}
+
+DirectOutputThread::DirectOutputThread(const sp<IAfThreadCallback>& afThreadCallback,
         AudioStreamOut* output, audio_io_handle_t id, ThreadBase::type_t type, bool systemReady,
         const audio_offload_info_t& offloadInfo)
-    :   PlaybackThread(audioFlinger, output, id, type, systemReady)
+    :   PlaybackThread(afThreadCallback, output, id, type, systemReady)
     , mOffloadInfo(offloadInfo)
 {
-    setMasterBalance(audioFlinger->getMasterBalance_l());
+    setMasterBalance(afThreadCallback->getMasterBalance_l());
 }
 
-AudioFlinger::DirectOutputThread::~DirectOutputThread()
+DirectOutputThread::~DirectOutputThread()
 {
 }
 
-void AudioFlinger::DirectOutputThread::dumpInternals_l(int fd, const Vector<String16>& args)
+void DirectOutputThread::dumpInternals_l(int fd, const Vector<String16>& args)
 {
     PlaybackThread::dumpInternals_l(fd, args);
     dprintf(fd, "  Master balance: %f  Left: %f  Right: %f\n",
             mMasterBalance.load(), mMasterBalanceLeft, mMasterBalanceRight);
 }
 
-void AudioFlinger::DirectOutputThread::setMasterBalance(float balance)
+void DirectOutputThread::setMasterBalance(float balance)
 {
     Mutex::Autolock _l(mLock);
     if (mMasterBalance != balance) {
@@ -6426,12 +6528,12 @@
     }
 }
 
-void AudioFlinger::DirectOutputThread::processVolume_l(Track *track, bool lastTrack)
+void DirectOutputThread::processVolume_l(IAfTrack* track, bool lastTrack)
 {
     float left, right;
 
     // Ensure volumeshaper state always advances even when muted.
-    const sp<AudioTrackServerProxy> proxy = track->mAudioTrackServerProxy;
+    const sp<AudioTrackServerProxy> proxy = track->audioTrackServerProxy();
 
     const size_t framesReleased = proxy->framesReleased();
     const int64_t frames = mTimestamp.mPosition[ExtendedTimestamp::LOCATION_KERNEL];
@@ -6466,14 +6568,14 @@
         }
         left *= v;
         right *= v;
-        if (mAudioFlinger->getMode() != AUDIO_MODE_IN_COMMUNICATION
+        if (mAfThreadCallback->getMode() != AUDIO_MODE_IN_COMMUNICATION
                 || audio_channel_count_from_out_mask(mChannelMask) > 1) {
             left *= mMasterBalanceLeft; // DirectOutputThread balance applied as track volume
             right *= mMasterBalanceRight;
         }
     }
 
-    track->processMuteEvent_l(mAudioFlinger->getOrCreateAudioManager(),
+    track->processMuteEvent_l(mAfThreadCallback->getOrCreateAudioManager(),
         /*muteState=*/{mMasterMute,
                        mStreamTypes[track->streamType()].volume == 0.f,
                        mStreamTypes[track->streamType()].mute,
@@ -6505,10 +6607,10 @@
     }
 }
 
-void AudioFlinger::DirectOutputThread::onAddNewTrack_l()
+void DirectOutputThread::onAddNewTrack_l()
 {
-    sp<Track> previousTrack = mPreviousTrack.promote();
-    sp<Track> latestTrack = mActiveTracks.getLatest();
+    sp<IAfTrack> previousTrack = mPreviousTrack.promote();
+    sp<IAfTrack> latestTrack = mActiveTracks.getLatest();
 
     if (previousTrack != 0 && latestTrack != 0) {
         if (mType == DIRECT) {
@@ -6530,8 +6632,8 @@
     PlaybackThread::onAddNewTrack_l();
 }
 
-AudioFlinger::PlaybackThread::mixer_state AudioFlinger::DirectOutputThread::prepareTracks_l(
-    Vector< sp<Track> > *tracksToRemove
+PlaybackThread::mixer_state DirectOutputThread::prepareTracks_l(
+    Vector<sp<IAfTrack>>* tracksToRemove
 )
 {
     size_t count = mActiveTracks.size();
@@ -6540,14 +6642,14 @@
     bool doHwResume = false;
 
     // find out which tracks need to be processed
-    for (const sp<Track> &t : mActiveTracks) {
+    for (const sp<IAfTrack>& t : mActiveTracks) {
         if (t->isInvalid()) {
             ALOGW("An invalidated track shouldn't be in active list");
             tracksToRemove->add(t);
             continue;
         }
 
-        Track* const track = t.get();
+        IAfTrack* const track = t.get();
 #ifdef VERY_VERY_VERBOSE_LOGGING
         audio_track_cblk_t* cblk = track->cblk();
 #endif
@@ -6555,7 +6657,7 @@
         // In theory an older track could underrun and restart after the new one starts
         // but as we only care about the transition phase between two tracks on a
         // direct output, it is not a problem to ignore the underrun case.
-        sp<Track> l = mActiveTracks.getLatest();
+        sp<IAfTrack> l = mActiveTracks.getLatest();
         bool last = l.get() == track;
 
         if (track->isPausePending()) {
@@ -6591,8 +6693,8 @@
         // for all its buffers to be filled before processing it.
         // Allow draining the buffer in case the client
         // app does not call stop() and relies on underrun to stop:
-        // hence the test on (track->mRetryCount > 1).
-        // If track->mRetryCount <= 1 then track is about to be disabled, paused, removed,
+        // hence the test on (track->retryCount() > 1).
+        // If track->retryCount() <= 1 then track is about to be disabled, paused, removed,
         // so we accept any nonzero amount of data delivered by the AudioTrack (which will
         // reset the retry counter).
         // Do not use a high threshold for compressed audio.
@@ -6604,7 +6706,7 @@
         const int32_t retryThreshold = targetRetryCount > 2 ? targetRetryCount - 1 : 1;
         uint32_t minFrames;
         if ((track->sharedBuffer() == 0) && !track->isStopping_1() && !track->isPausing()
-            && (track->mRetryCount > retryThreshold) && audio_has_proportional_frames(mFormat)) {
+            && (track->retryCount() > retryThreshold) && audio_has_proportional_frames(mFormat)) {
             minFrames = mNormalFrameCount;
         } else {
             minFrames = 1;
@@ -6622,8 +6724,8 @@
         {
             ALOGVV("track(%d) s=%08x [OK]", trackId, cblk->mServer);
 
-            if (track->mFillingUpStatus == Track::FS_FILLED) {
-                track->mFillingUpStatus = Track::FS_ACTIVE;
+            if (track->fillingStatus() == IAfTrack::FS_FILLED) {
+                track->fillingStatus() = IAfTrack::FS_ACTIVE;
                 if (last) {
                     // make sure processVolume_l() will apply new volume even if 0
                     mLeftVolFloat = mRightVolFloat = -1.0;
@@ -6636,7 +6738,7 @@
             // compute volume for this track
             processVolume_l(track, last);
             if (last) {
-                sp<Track> previousTrack = mPreviousTrack.promote();
+                sp<IAfTrack> previousTrack = mPreviousTrack.promote();
                 if (previousTrack != 0) {
                     if (track != previousTrack.get()) {
                         // Flush any data still being written from last track
@@ -6648,7 +6750,7 @@
                 mPreviousTrack = track;
 
                 // reset retry count
-                track->mRetryCount = targetRetryCount;
+                track->retryCount() = targetRetryCount;
                 mActiveTrack = t;
                 mixerStatus = MIXER_TRACKS_READY;
                 if (mHwPaused) {
@@ -6663,7 +6765,7 @@
                 mEffectChains[0]->clearInputBuffer();
             }
             if (track->isStopping_1()) {
-                track->mState = TrackBase::STOPPING_2;
+                track->setState(IAfTrackBase::STOPPING_2);
                 if (last && mHwPaused) {
                      doHwResume = true;
                      mHwPaused = false;
@@ -6681,7 +6783,7 @@
                         mOutput->presentationComplete();
                     }
                     if (track->isStopping_2()) {
-                        track->mState = TrackBase::STOPPED;
+                        track->setState(IAfTrackBase::STOPPED);
                     }
                     if (track->isStopped()) {
                         track->reset();
@@ -6694,9 +6796,9 @@
                 // Only consider last track started for mixer state control
                 bool isTimestampAdvancing = mIsTimestampAdvancing.check(mOutput);
                 if (!isTunerStream()  // tuner streams remain active in underrun
-                        && --(track->mRetryCount) <= 0) {
+                        && --(track->retryCount()) <= 0) {
                     if (isTimestampAdvancing) { // HAL is still playing audio, give us more time.
-                        track->mRetryCount = kMaxTrackRetriesOffload;
+                        track->retryCount() = kMaxTrackRetriesOffload;
                     } else {
                         ALOGV("BUFFER TIMEOUT: remove track(%d) from active list", trackId);
                         tracksToRemove->add(track);
@@ -6753,7 +6855,7 @@
     return mixerStatus;
 }
 
-void AudioFlinger::DirectOutputThread::threadLoop_mix()
+void DirectOutputThread::threadLoop_mix()
 {
     size_t frameCount = mFrameCount;
     int8_t *curBuf = (int8_t *)mSinkBuffer;
@@ -6780,7 +6882,7 @@
     mActiveTrack.clear();
 }
 
-void AudioFlinger::DirectOutputThread::threadLoop_sleepTime()
+void DirectOutputThread::threadLoop_sleepTime()
 {
     // do not write to HAL when paused
     if (mHwPaused || (usesHwAvSync() && mStandby)) {
@@ -6796,7 +6898,7 @@
     // linear or proportional PCM direct tracks in underrun.
 }
 
-void AudioFlinger::DirectOutputThread::threadLoop_exit()
+void DirectOutputThread::threadLoop_exit()
 {
     {
         Mutex::Autolock _l(mLock);
@@ -6814,7 +6916,7 @@
 }
 
 // must be called with thread mutex locked
-bool AudioFlinger::DirectOutputThread::shouldStandby_l()
+bool DirectOutputThread::shouldStandby_l()
 {
     bool trackPaused = false;
     bool trackStopped = false;
@@ -6824,14 +6926,14 @@
     if (mTracks.size() > 0) {
         trackPaused = mTracks[mTracks.size() - 1]->isPaused();
         trackStopped = mTracks[mTracks.size() - 1]->isStopped() ||
-                           mTracks[mTracks.size() - 1]->mState == TrackBase::IDLE;
+                           mTracks[mTracks.size() - 1]->state() == IAfTrackBase::IDLE;
     }
 
     return !mStandby && !(trackPaused || (mHwPaused && !trackStopped));
 }
 
 // checkForNewParameter_l() must be called with ThreadBase::mLock held
-bool AudioFlinger::DirectOutputThread::checkForNewParameter_l(const String8& keyValuePair,
+bool DirectOutputThread::checkForNewParameter_l(const String8& keyValuePair,
                                                               status_t& status)
 {
     bool reconfig = false;
@@ -6873,7 +6975,7 @@
     return reconfig;
 }
 
-uint32_t AudioFlinger::DirectOutputThread::activeSleepTimeUs() const
+uint32_t DirectOutputThread::activeSleepTimeUs() const
 {
     uint32_t time;
     if (audio_has_proportional_frames(mFormat)) {
@@ -6884,7 +6986,7 @@
     return time;
 }
 
-uint32_t AudioFlinger::DirectOutputThread::idleSleepTimeUs() const
+uint32_t DirectOutputThread::idleSleepTimeUs() const
 {
     uint32_t time;
     if (audio_has_proportional_frames(mFormat)) {
@@ -6895,7 +6997,7 @@
     return time;
 }
 
-uint32_t AudioFlinger::DirectOutputThread::suspendSleepTimeUs() const
+uint32_t DirectOutputThread::suspendSleepTimeUs() const
 {
     uint32_t time;
     if (audio_has_proportional_frames(mFormat)) {
@@ -6906,7 +7008,7 @@
     return time;
 }
 
-void AudioFlinger::DirectOutputThread::cacheParameters_l()
+void DirectOutputThread::cacheParameters_l()
 {
     PlaybackThread::cacheParameters_l();
 
@@ -6922,7 +7024,7 @@
     }
 }
 
-void AudioFlinger::DirectOutputThread::flushHw_l()
+void DirectOutputThread::flushHw_l()
 {
     PlaybackThread::flushHw_l();
     mOutput->flush();
@@ -6933,7 +7035,7 @@
     mMonotonicFrameCounter.onFlush();
 }
 
-int64_t AudioFlinger::DirectOutputThread::computeWaitTimeNs_l() const {
+int64_t DirectOutputThread::computeWaitTimeNs_l() const {
     // If a VolumeShaper is active, we must wake up periodically to update volume.
     const int64_t NS_PER_MS = 1000000;
     return mVolumeShaperActive ?
@@ -6942,8 +7044,8 @@
 
 // ----------------------------------------------------------------------------
 
-AudioFlinger::AsyncCallbackThread::AsyncCallbackThread(
-        const wp<AudioFlinger::PlaybackThread>& playbackThread)
+AsyncCallbackThread::AsyncCallbackThread(
+        const wp<PlaybackThread>& playbackThread)
     :   Thread(false /*canCallJava*/),
         mPlaybackThread(playbackThread),
         mWriteAckSequence(0),
@@ -6952,16 +7054,12 @@
 {
 }
 
-AudioFlinger::AsyncCallbackThread::~AsyncCallbackThread()
-{
-}
-
-void AudioFlinger::AsyncCallbackThread::onFirstRef()
+void AsyncCallbackThread::onFirstRef()
 {
     run("Offload Cbk", ANDROID_PRIORITY_URGENT_AUDIO);
 }
 
-bool AudioFlinger::AsyncCallbackThread::threadLoop()
+bool AsyncCallbackThread::threadLoop()
 {
     while (!exitPending()) {
         uint32_t writeAckSequence;
@@ -6990,7 +7088,7 @@
             mAsyncError = false;
         }
         {
-            sp<AudioFlinger::PlaybackThread> playbackThread = mPlaybackThread.promote();
+            const sp<PlaybackThread> playbackThread = mPlaybackThread.promote();
             if (playbackThread != 0) {
                 if (writeAckSequence & 1) {
                     playbackThread->resetWriteBlocked(writeAckSequence >> 1);
@@ -7007,7 +7105,7 @@
     return false;
 }
 
-void AudioFlinger::AsyncCallbackThread::exit()
+void AsyncCallbackThread::exit()
 {
     ALOGV("AsyncCallbackThread::exit");
     Mutex::Autolock _l(mLock);
@@ -7015,14 +7113,14 @@
     mWaitWorkCV.broadcast();
 }
 
-void AudioFlinger::AsyncCallbackThread::setWriteBlocked(uint32_t sequence)
+void AsyncCallbackThread::setWriteBlocked(uint32_t sequence)
 {
     Mutex::Autolock _l(mLock);
     // bit 0 is cleared
     mWriteAckSequence = sequence << 1;
 }
 
-void AudioFlinger::AsyncCallbackThread::resetWriteBlocked()
+void AsyncCallbackThread::resetWriteBlocked()
 {
     Mutex::Autolock _l(mLock);
     // ignore unexpected callbacks
@@ -7032,14 +7130,14 @@
     }
 }
 
-void AudioFlinger::AsyncCallbackThread::setDraining(uint32_t sequence)
+void AsyncCallbackThread::setDraining(uint32_t sequence)
 {
     Mutex::Autolock _l(mLock);
     // bit 0 is cleared
     mDrainSequence = sequence << 1;
 }
 
-void AudioFlinger::AsyncCallbackThread::resetDraining()
+void AsyncCallbackThread::resetDraining()
 {
     Mutex::Autolock _l(mLock);
     // ignore unexpected callbacks
@@ -7049,7 +7147,7 @@
     }
 }
 
-void AudioFlinger::AsyncCallbackThread::setAsyncError()
+void AsyncCallbackThread::setAsyncError()
 {
     Mutex::Autolock _l(mLock);
     mAsyncError = true;
@@ -7058,10 +7156,19 @@
 
 
 // ----------------------------------------------------------------------------
-AudioFlinger::OffloadThread::OffloadThread(const sp<AudioFlinger>& audioFlinger,
+
+/* static */
+sp<IAfPlaybackThread> IAfPlaybackThread::createOffloadThread(
+        const sp<IAfThreadCallback>& afThreadCallback,
+        AudioStreamOut* output, audio_io_handle_t id, bool systemReady,
+        const audio_offload_info_t& offloadInfo) {
+    return sp<OffloadThread>::make(afThreadCallback, output, id, systemReady, offloadInfo);
+}
+
+OffloadThread::OffloadThread(const sp<IAfThreadCallback>& afThreadCallback,
         AudioStreamOut* output, audio_io_handle_t id, bool systemReady,
         const audio_offload_info_t& offloadInfo)
-    :   DirectOutputThread(audioFlinger, output, id, OFFLOAD, systemReady, offloadInfo),
+    :   DirectOutputThread(afThreadCallback, output, id, OFFLOAD, systemReady, offloadInfo),
         mPausedWriteLength(0), mPausedBytesRemaining(0), mKeepWakeLock(true)
 {
     //FIXME: mStandby should be set to true by ThreadBase constructo
@@ -7069,7 +7176,7 @@
     mKeepWakeLock = property_get_bool("ro.audio.offload_wakelock", true /* default_value */);
 }
 
-void AudioFlinger::OffloadThread::threadLoop_exit()
+void OffloadThread::threadLoop_exit()
 {
     if (mFlushPending || mHwPaused) {
         // If a flush is pending or track was paused, just discard buffered data
@@ -7085,8 +7192,8 @@
     PlaybackThread::threadLoop_exit();
 }
 
-AudioFlinger::PlaybackThread::mixer_state AudioFlinger::OffloadThread::prepareTracks_l(
-    Vector< sp<Track> > *tracksToRemove
+PlaybackThread::mixer_state OffloadThread::prepareTracks_l(
+    Vector<sp<IAfTrack>>* tracksToRemove
 )
 {
     size_t count = mActiveTracks.size();
@@ -7098,8 +7205,8 @@
     ALOGV("OffloadThread::prepareTracks_l active tracks %zu", count);
 
     // find out which tracks need to be processed
-    for (const sp<Track> &t : mActiveTracks) {
-        Track* const track = t.get();
+    for (const sp<IAfTrack>& t : mActiveTracks) {
+        IAfTrack* const track = t.get();
 #ifdef VERY_VERY_VERBOSE_LOGGING
         audio_track_cblk_t* cblk = track->cblk();
 #endif
@@ -7107,7 +7214,7 @@
         // In theory an older track could underrun and restart after the new one starts
         // but as we only care about the transition phase between two tracks on a
         // direct output, it is not a problem to ignore the underrun case.
-        sp<Track> l = mActiveTracks.getLatest();
+        sp<IAfTrack> l = mActiveTracks.getLatest();
         bool last = l.get() == track;
 
         if (track->isInvalid()) {
@@ -7116,7 +7223,7 @@
             continue;
         }
 
-        if (track->mState == TrackBase::IDLE) {
+        if (track->state() == IAfTrackBase::IDLE) {
             ALOGW("An idle track shouldn't be in active list");
             continue;
         }
@@ -7148,9 +7255,9 @@
             tracksToRemove->add(track);
         } else if (track->isFlushPending()) {
             if (track->isStopping_1()) {
-                track->mRetryCount = kMaxTrackStopRetriesOffload;
+                track->retryCount() = kMaxTrackStopRetriesOffload;
             } else {
-                track->mRetryCount = kMaxTrackRetriesOffload;
+                track->retryCount() = kMaxTrackRetriesOffload;
             }
             track->flushAck();
             if (last) {
@@ -7182,8 +7289,8 @@
         }  else if (track->framesReady() && track->isReady() &&
                 !track->isPaused() && !track->isTerminated() && !track->isStopping_2()) {
             ALOGVV("OffloadThread: track(%d) s=%08x [OK]", track->id(), cblk->mServer);
-            if (track->mFillingUpStatus == Track::FS_FILLED) {
-                track->mFillingUpStatus = Track::FS_ACTIVE;
+            if (track->fillingStatus() == IAfTrack::FS_FILLED) {
+                track->fillingStatus() = IAfTrack::FS_ACTIVE;
                 if (last) {
                     // make sure processVolume_l() will apply new volume even if 0
                     mLeftVolFloat = mRightVolFloat = -1.0;
@@ -7191,7 +7298,7 @@
             }
 
             if (last) {
-                sp<Track> previousTrack = mPreviousTrack.promote();
+                sp<IAfTrack> previousTrack = mPreviousTrack.promote();
                 if (previousTrack != 0) {
                     if (track != previousTrack.get()) {
                         // Flush any data still being written from last track
@@ -7217,9 +7324,9 @@
                 mPreviousTrack = track;
                 // reset retry count
                 if (track->isStopping_1()) {
-                    track->mRetryCount = kMaxTrackStopRetriesOffload;
+                    track->retryCount() = kMaxTrackStopRetriesOffload;
                 } else {
-                    track->mRetryCount = kMaxTrackRetriesOffload;
+                    track->retryCount() = kMaxTrackRetriesOffload;
                 }
                 mActiveTrack = t;
                 mixerStatus = MIXER_TRACKS_READY;
@@ -7227,7 +7334,7 @@
         } else {
             ALOGVV("OffloadThread: track(%d) s=%08x [NOT READY]", track->id(), cblk->mServer);
             if (track->isStopping_1()) {
-                if (--(track->mRetryCount) <= 0) {
+                if (--(track->retryCount()) <= 0) {
                     // Hardware buffer can hold a large amount of audio so we must
                     // wait for all current track's data to drain before we say
                     // that the track is stopped.
@@ -7235,7 +7342,8 @@
                         // Only start draining when all data in mixbuffer
                         // has been written
                         ALOGV("OffloadThread: underrun and STOPPING_1 -> draining, STOPPING_2");
-                        track->mState = TrackBase::STOPPING_2; // so presentation completes after
+                        track->setState(IAfTrackBase::STOPPING_2);
+                        // so presentation completes after
                         // drain do not drain if no data was ever sent to HAL (mStandby == true)
                         if (last && !mStandby) {
                             // do not modify drain sequence if we are already draining. This happens
@@ -7255,13 +7363,13 @@
                         }
                     }
                 } else if (last) {
-                    ALOGV("stopping1 underrun retries left %d", track->mRetryCount);
+                    ALOGV("stopping1 underrun retries left %d", track->retryCount());
                     mixerStatus = MIXER_TRACKS_ENABLED;
                 }
             } else if (track->isStopping_2()) {
                 // Drain has completed or we are in standby, signal presentation complete
                 if (!(mDrainSequence & 1) || !last || mStandby) {
-                    track->mState = TrackBase::STOPPED;
+                    track->setState(IAfTrackBase::STOPPED);
                     mOutput->presentationComplete();
                     track->presentationComplete(latency_l()); // always returns true
                     track->reset();
@@ -7281,9 +7389,9 @@
                 // fill a buffer, then remove it from active list.
                 bool isTimestampAdvancing = mIsTimestampAdvancing.check(mOutput);
                 if (!isTunerStream()  // tuner streams remain active in underrun
-                        && --(track->mRetryCount) <= 0) {
+                        && --(track->retryCount()) <= 0) {
                     if (isTimestampAdvancing) { // HAL is still playing audio, give us more time.
-                        track->mRetryCount = kMaxTrackRetriesOffload;
+                        track->retryCount() = kMaxTrackRetriesOffload;
                     } else {
                         ALOGV("OffloadThread: BUFFER TIMEOUT: remove track(%d) from active list",
                                 track->id());
@@ -7327,7 +7435,7 @@
 }
 
 // must be called with thread mutex locked
-bool AudioFlinger::OffloadThread::waitingAsyncCallback_l()
+bool OffloadThread::waitingAsyncCallback_l()
 {
     ALOGVV("waitingAsyncCallback_l mWriteAckSequence %d mDrainSequence %d",
           mWriteAckSequence, mDrainSequence);
@@ -7337,13 +7445,13 @@
     return false;
 }
 
-bool AudioFlinger::OffloadThread::waitingAsyncCallback()
+bool OffloadThread::waitingAsyncCallback()
 {
     Mutex::Autolock _l(mLock);
     return waitingAsyncCallback_l();
 }
 
-void AudioFlinger::OffloadThread::flushHw_l()
+void OffloadThread::flushHw_l()
 {
     DirectOutputThread::flushHw_l();
     // Flush anything still waiting in the mixbuffer
@@ -7364,7 +7472,7 @@
     }
 }
 
-void AudioFlinger::OffloadThread::invalidateTracks(audio_stream_type_t streamType)
+void OffloadThread::invalidateTracks(audio_stream_type_t streamType)
 {
     Mutex::Autolock _l(mLock);
     if (PlaybackThread::invalidateTracks_l(streamType)) {
@@ -7372,7 +7480,7 @@
     }
 }
 
-void AudioFlinger::OffloadThread::invalidateTracks(std::set<audio_port_handle_t>& portIds) {
+void OffloadThread::invalidateTracks(std::set<audio_port_handle_t>& portIds) {
     Mutex::Autolock _l(mLock);
     if (PlaybackThread::invalidateTracks_l(portIds)) {
         mFlushPending = true;
@@ -7381,23 +7489,30 @@
 
 // ----------------------------------------------------------------------------
 
-AudioFlinger::DuplicatingThread::DuplicatingThread(const sp<AudioFlinger>& audioFlinger,
-        AudioFlinger::MixerThread* mainThread, audio_io_handle_t id, bool systemReady)
-    :   MixerThread(audioFlinger, mainThread->getOutput(), id,
+/* static */
+sp<IAfDuplicatingThread> IAfDuplicatingThread::create(
+        const sp<IAfThreadCallback>& afThreadCallback,
+        IAfPlaybackThread* mainThread, audio_io_handle_t id, bool systemReady) {
+    return sp<DuplicatingThread>::make(afThreadCallback, mainThread, id, systemReady);
+}
+
+DuplicatingThread::DuplicatingThread(const sp<IAfThreadCallback>& afThreadCallback,
+       IAfPlaybackThread* mainThread, audio_io_handle_t id, bool systemReady)
+    :   MixerThread(afThreadCallback, mainThread->getOutput(), id,
                     systemReady, DUPLICATING),
         mWaitTimeMs(UINT_MAX)
 {
     addOutputTrack(mainThread);
 }
 
-AudioFlinger::DuplicatingThread::~DuplicatingThread()
+DuplicatingThread::~DuplicatingThread()
 {
     for (size_t i = 0; i < mOutputTracks.size(); i++) {
         mOutputTracks[i]->destroy();
     }
 }
 
-void AudioFlinger::DuplicatingThread::threadLoop_mix()
+void DuplicatingThread::threadLoop_mix()
 {
     // mix buffers...
     if (outputsReady()) {
@@ -7415,7 +7530,7 @@
     mStandbyTimeNs = systemTime() + mStandbyDelayNs;
 }
 
-void AudioFlinger::DuplicatingThread::threadLoop_sleepTime()
+void DuplicatingThread::threadLoop_sleepTime()
 {
     if (mSleepTimeUs == 0) {
         if (mMixerStatus == MIXER_TRACKS_ENABLED) {
@@ -7435,7 +7550,7 @@
     }
 }
 
-ssize_t AudioFlinger::DuplicatingThread::threadLoop_write()
+ssize_t DuplicatingThread::threadLoop_write()
 {
     for (size_t i = 0; i < outputTracks.size(); i++) {
         const ssize_t actualWritten = outputTracks[i]->write(mSinkBuffer, writeFrames);
@@ -7463,7 +7578,7 @@
     return (ssize_t)mSinkBufferSize;
 }
 
-void AudioFlinger::DuplicatingThread::threadLoop_standby()
+void DuplicatingThread::threadLoop_standby()
 {
     // DuplicatingThread implements standby by stopping all tracks
     for (size_t i = 0; i < outputTracks.size(); i++) {
@@ -7471,7 +7586,7 @@
     }
 }
 
-void AudioFlinger::DuplicatingThread::dumpInternals_l(int fd, const Vector<String16>& args)
+void DuplicatingThread::dumpInternals_l(int fd, const Vector<String16>& args)
 {
     MixerThread::dumpInternals_l(fd, args);
 
@@ -7481,7 +7596,7 @@
     if (numTracks > 0) {
         ss << ":";
         for (const auto &track : mOutputTracks) {
-            const sp<ThreadBase> thread = track->thread().promote();
+            const auto thread = track->thread().promote();
             ss << " (" << track->id() << " : ";
             if (thread.get() != nullptr) {
                 ss << thread.get() << ", " << thread->id();
@@ -7496,17 +7611,17 @@
     write(fd, result.c_str(), result.size());
 }
 
-void AudioFlinger::DuplicatingThread::saveOutputTracks()
+void DuplicatingThread::saveOutputTracks()
 {
     outputTracks = mOutputTracks;
 }
 
-void AudioFlinger::DuplicatingThread::clearOutputTracks()
+void DuplicatingThread::clearOutputTracks()
 {
     outputTracks.clear();
 }
 
-void AudioFlinger::DuplicatingThread::addOutputTrack(MixerThread *thread)
+void DuplicatingThread::addOutputTrack(IAfPlaybackThread* thread)
 {
     Mutex::Autolock _l(mLock);
     // The downstream MixerThread consumes thread->frameCount() amount of frames per mix pass.
@@ -7525,7 +7640,7 @@
     attributionSource.pid = VALUE_OR_FATAL(legacy2aidl_pid_t_int32_t(
       IPCThreadState::self()->getCallingPid()));
     attributionSource.token = sp<BBinder>::make();
-    sp<OutputTrack> outputTrack = new OutputTrack(thread,
+    sp<IAfOutputTrack> outputTrack = IAfOutputTrack::create(thread,
                                             this,
                                             mSampleRate,
                                             mFormat,
@@ -7543,7 +7658,7 @@
     updateWaitTime_l();
 }
 
-void AudioFlinger::DuplicatingThread::removeOutputTrack(MixerThread *thread)
+void DuplicatingThread::removeOutputTrack(IAfPlaybackThread* thread)
 {
     Mutex::Autolock _l(mLock);
     for (size_t i = 0; i < mOutputTracks.size(); i++) {
@@ -7561,11 +7676,11 @@
 }
 
 // caller must hold mLock
-void AudioFlinger::DuplicatingThread::updateWaitTime_l()
+void DuplicatingThread::updateWaitTime_l()
 {
     mWaitTimeMs = UINT_MAX;
     for (size_t i = 0; i < mOutputTracks.size(); i++) {
-        sp<ThreadBase> strong = mOutputTracks[i]->thread().promote();
+        const auto strong = mOutputTracks[i]->thread().promote();
         if (strong != 0) {
             uint32_t waitTimeMs = (strong->frameCount() * 2 * 1000) / strong->sampleRate();
             if (waitTimeMs < mWaitTimeMs) {
@@ -7575,18 +7690,18 @@
     }
 }
 
-bool AudioFlinger::DuplicatingThread::outputsReady()
+bool DuplicatingThread::outputsReady()
 {
     for (size_t i = 0; i < outputTracks.size(); i++) {
-        sp<ThreadBase> thread = outputTracks[i]->thread().promote();
+        const auto thread = outputTracks[i]->thread().promote();
         if (thread == 0) {
             ALOGW("DuplicatingThread::outputsReady() could not promote thread on output track %p",
                     outputTracks[i].get());
             return false;
         }
-        PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
+        IAfPlaybackThread* const playbackThread = thread->asIAfPlaybackThread().get();
         // see note at standby() declaration
-        if (playbackThread->standby() && !playbackThread->isSuspended()) {
+        if (playbackThread->inStandby() && !playbackThread->isSuspended()) {
             ALOGV("DuplicatingThread output track %p on thread %p Not Ready", outputTracks[i].get(),
                     thread.get());
             return false;
@@ -7595,7 +7710,7 @@
     return true;
 }
 
-void AudioFlinger::DuplicatingThread::sendMetadataToBackend_l(
+void DuplicatingThread::sendMetadataToBackend_l(
         const StreamOutHalInterface::SourceMetadata& metadata)
 {
     for (auto& outputTrack : outputTracks) { // not mOutputTracks
@@ -7603,12 +7718,12 @@
     }
 }
 
-uint32_t AudioFlinger::DuplicatingThread::activeSleepTimeUs() const
+uint32_t DuplicatingThread::activeSleepTimeUs() const
 {
     return (mWaitTimeMs * 1000) / 2;
 }
 
-void AudioFlinger::DuplicatingThread::cacheParameters_l()
+void DuplicatingThread::cacheParameters_l()
 {
     // updateWaitTime_l() sets mWaitTimeMs, which affects activeSleepTimeUs(), so call it first
     updateWaitTime_l();
@@ -7618,16 +7733,26 @@
 
 // ----------------------------------------------------------------------------
 
-AudioFlinger::SpatializerThread::SpatializerThread(const sp<AudioFlinger>& audioFlinger,
+/* static */
+sp<IAfPlaybackThread> IAfPlaybackThread::createSpatializerThread(
+        const sp<IAfThreadCallback>& afThreadCallback,
+        AudioStreamOut* output,
+        audio_io_handle_t id,
+        bool systemReady,
+        audio_config_base_t* mixerConfig) {
+    return sp<SpatializerThread>::make(afThreadCallback, output, id, systemReady, mixerConfig);
+}
+
+SpatializerThread::SpatializerThread(const sp<IAfThreadCallback>& afThreadCallback,
                                                              AudioStreamOut* output,
                                                              audio_io_handle_t id,
                                                              bool systemReady,
                                                              audio_config_base_t *mixerConfig)
-    : MixerThread(audioFlinger, output, id, systemReady, SPATIALIZER, mixerConfig)
+    : MixerThread(afThreadCallback, output, id, systemReady, SPATIALIZER, mixerConfig)
 {
 }
 
-void AudioFlinger::SpatializerThread::onFirstRef() {
+void SpatializerThread::onFirstRef() {
     MixerThread::onFirstRef();
 
     const pid_t tid = getTid();
@@ -7642,7 +7767,7 @@
     }
 }
 
-void AudioFlinger::SpatializerThread::setHalLatencyMode_l() {
+void SpatializerThread::setHalLatencyMode_l() {
     // if mSupportedLatencyModes is empty, the HAL stream does not support
     // latency mode control and we can exit.
     if (mSupportedLatencyModes.empty()) {
@@ -7680,7 +7805,7 @@
     }
 }
 
-status_t AudioFlinger::SpatializerThread::setRequestedLatencyMode(audio_latency_mode_t mode) {
+status_t SpatializerThread::setRequestedLatencyMode(audio_latency_mode_t mode) {
     if (mode != AUDIO_LATENCY_MODE_LOW && mode != AUDIO_LATENCY_MODE_FREE) {
         return BAD_VALUE;
     }
@@ -7689,7 +7814,7 @@
     return NO_ERROR;
 }
 
-void AudioFlinger::SpatializerThread::checkOutputStageEffects()
+void SpatializerThread::checkOutputStageEffects()
 {
     bool hasVirtualizer = false;
     bool hasDownMixer = false;
@@ -7714,7 +7839,7 @@
         finalDownMixer.clear();
     } else if (!hasDownMixer) {
         std::vector<effect_descriptor_t> descriptors;
-        status_t status = mAudioFlinger->mEffectsFactoryHal->getDescriptors(
+        status_t status = mAfThreadCallback->getEffectsFactoryHal()->getDescriptors(
                                                         EFFECT_UIID_DOWNMIX, &descriptors);
         if (status != NO_ERROR) {
             return;
@@ -7745,12 +7870,19 @@
 //      Record
 // ----------------------------------------------------------------------------
 
-AudioFlinger::RecordThread::RecordThread(const sp<AudioFlinger>& audioFlinger,
+sp<IAfRecordThread> IAfRecordThread::create(const sp<IAfThreadCallback>& afThreadCallback,
+        AudioStreamIn* input,
+        audio_io_handle_t id,
+        bool systemReady) {
+    return sp<RecordThread>::make(afThreadCallback, input, id, systemReady);
+}
+
+RecordThread::RecordThread(const sp<IAfThreadCallback>& afThreadCallback,
                                          AudioStreamIn *input,
                                          audio_io_handle_t id,
                                          bool systemReady
                                          ) :
-    ThreadBase(audioFlinger, id, RECORD, systemReady, false /* isOut */),
+    ThreadBase(afThreadCallback, id, RECORD, systemReady, false /* isOut */),
     mInput(input),
     mSource(mInput),
     mActiveTracks(&this->mLocalLog),
@@ -7771,7 +7903,7 @@
     , mBtNrecSuspended(false)
 {
     snprintf(mThreadName, kThreadNameLength, "AudioIn_%X", id);
-    mNBLogWriter = audioFlinger->newWriter_l(kLogSize, mThreadName);
+    mNBLogWriter = afThreadCallback->newWriter_l(kLogSize, mThreadName);
 
     if (mInput->audioHwDev != nullptr) {
         mIsMsdDevice = strcmp(
@@ -7879,7 +8011,8 @@
 #ifdef TEE_SINK
         // FIXME
 #endif
-        mFastCaptureNBLogWriter = audioFlinger->newWriter_l(kFastCaptureLogSize, "FastCapture");
+        mFastCaptureNBLogWriter =
+                afThreadCallback->newWriter_l(kFastCaptureLogSize, "FastCapture");
         state->mNBLogWriter = mFastCaptureNBLogWriter.get();
         sq->end();
         sq->push(FastCaptureStateQueue::BLOCK_UNTIL_PUSHED);
@@ -7904,7 +8037,7 @@
     // FIXME mNormalSource
 }
 
-AudioFlinger::RecordThread::~RecordThread()
+RecordThread::~RecordThread()
 {
     if (mFastCapture != 0) {
         FastCaptureStateQueue *sq = mFastCapture->sq();
@@ -7921,36 +8054,36 @@
         mFastCapture->join();
         mFastCapture.clear();
     }
-    mAudioFlinger->unregisterWriter(mFastCaptureNBLogWriter);
-    mAudioFlinger->unregisterWriter(mNBLogWriter);
+    mAfThreadCallback->unregisterWriter(mFastCaptureNBLogWriter);
+    mAfThreadCallback->unregisterWriter(mNBLogWriter);
     free(mRsmpInBuffer);
 }
 
-void AudioFlinger::RecordThread::onFirstRef()
+void RecordThread::onFirstRef()
 {
     run(mThreadName, PRIORITY_URGENT_AUDIO);
 }
 
-void AudioFlinger::RecordThread::preExit()
+void RecordThread::preExit()
 {
     ALOGV("  preExit()");
     Mutex::Autolock _l(mLock);
     for (size_t i = 0; i < mTracks.size(); i++) {
-        sp<RecordTrack> track = mTracks[i];
+        sp<IAfRecordTrack> track = mTracks[i];
         track->invalidate();
     }
     mActiveTracks.clear();
     mStartStopCond.broadcast();
 }
 
-bool AudioFlinger::RecordThread::threadLoop()
+bool RecordThread::threadLoop()
 {
     nsecs_t lastWarning = 0;
 
     inputStandBy();
 
 reacquire_wakelock:
-    sp<RecordTrack> activeTrack;
+    sp<IAfRecordTrack> activeTrack;
     {
         Mutex::Autolock _l(mLock);
         acquireWakeLock_l();
@@ -7966,13 +8099,13 @@
         Vector<sp<IAfEffectChain>> effectChains;
 
         // activeTracks accumulates a copy of a subset of mActiveTracks
-        Vector< sp<RecordTrack> > activeTracks;
+        Vector<sp<IAfRecordTrack>> activeTracks;
 
         // reference to the (first and only) active fast track
-        sp<RecordTrack> fastTrack;
+        sp<IAfRecordTrack> fastTrack;
 
         // reference to a fast track which is about to be removed
-        sp<RecordTrack> fastTrackToRemove;
+        sp<IAfRecordTrack> fastTrackToRemove;
 
         bool silenceFastCapture = false;
 
@@ -8025,40 +8158,40 @@
                     continue;
                 }
 
-                TrackBase::track_state activeTrackState = activeTrack->mState;
+                IAfTrackBase::track_state activeTrackState = activeTrack->state();
                 switch (activeTrackState) {
 
-                case TrackBase::PAUSING:
+                case IAfTrackBase::PAUSING:
                     mActiveTracks.remove(activeTrack);
-                    activeTrack->mState = TrackBase::PAUSED;
+                    activeTrack->setState(IAfTrackBase::PAUSED);
                     doBroadcast = true;
                     size--;
                     continue;
 
-                case TrackBase::STARTING_1:
+                case IAfTrackBase::STARTING_1:
                     sleepUs = 10000;
                     i++;
                     allStopped = false;
                     continue;
 
-                case TrackBase::STARTING_2:
+                case IAfTrackBase::STARTING_2:
                     doBroadcast = true;
                     if (mStandby) {
                         mThreadMetrics.logBeginInterval();
                         mThreadSnapshot.onBegin();
                         mStandby = false;
                     }
-                    activeTrack->mState = TrackBase::ACTIVE;
+                    activeTrack->setState(IAfTrackBase::ACTIVE);
                     allStopped = false;
                     break;
 
-                case TrackBase::ACTIVE:
+                case IAfTrackBase::ACTIVE:
                     allStopped = false;
                     break;
 
-                case TrackBase::IDLE:    // cannot be on ActiveTracks if idle
-                case TrackBase::PAUSED:  // cannot be on ActiveTracks if paused
-                case TrackBase::STOPPED: // cannot be on ActiveTracks if destroyed/terminated
+                case IAfTrackBase::IDLE:    // cannot be on ActiveTracks if idle
+                case IAfTrackBase::PAUSED:  // cannot be on ActiveTracks if paused
+                case IAfTrackBase::STOPPED: // cannot be on ActiveTracks if destroyed/terminated
                 default:
                     LOG_ALWAYS_FATAL("%s: Unexpected active track state:%d, id:%d, tracks:%zu",
                             __func__, activeTrackState, activeTrack->id(), size);
@@ -8150,7 +8283,7 @@
                 }
                 state->mCommand = FastCaptureState::READ_WRITE;
 #if 0   // FIXME
-                mFastCaptureDumpState.increaseSamplingN(mAudioFlinger->isLowRamDevice() ?
+                mFastCaptureDumpState.increaseSamplingN(mAfThreadCallback->isLowRamDevice() ?
                         FastThreadDumpState::kSamplingNforLowRamDevice :
                         FastThreadDumpState::kSamplingN);
 #endif
@@ -8305,7 +8438,7 @@
 
         // From the timestamp, input read latency is negative output write latency.
         const audio_input_flags_t flags = mInput != NULL ? mInput->flags : AUDIO_INPUT_FLAG_NONE;
-        const double latencyMs = RecordTrack::checkServerLatencySupported(mFormat, flags)
+        const double latencyMs = IAfRecordTrack::checkServerLatencySupported(mFormat, flags)
                 ? - mTimestamp.getOutputServerLatencyMs(mSampleRate) : 0.;
         if (latencyMs != 0.) { // note 0. means timestamp is empty.
             mLatencyMs.add(latencyMs);
@@ -8362,16 +8495,16 @@
             // loop over getNextBuffer to handle circular sink
             for (;;) {
 
-                activeTrack->mSink.frameCount = ~0;
-                status_t status = activeTrack->getNextBuffer(&activeTrack->mSink);
-                size_t framesOut = activeTrack->mSink.frameCount;
+                activeTrack->sinkBuffer().frameCount = ~0;
+                status_t status = activeTrack->getNextBuffer(&activeTrack->sinkBuffer());
+                size_t framesOut = activeTrack->sinkBuffer().frameCount;
                 LOG_ALWAYS_FATAL_IF((status == OK) != (framesOut > 0));
 
                 // check available frames and handle overrun conditions
                 // if the record track isn't draining fast enough.
                 bool hasOverrun;
                 size_t framesIn;
-                activeTrack->mResamplerBufferProvider->sync(&framesIn, &hasOverrun);
+                activeTrack->resamplerBufferProvider()->sync(&framesIn, &hasOverrun);
                 if (hasOverrun) {
                     overrun = OVERRUN_TRUE;
                 }
@@ -8385,7 +8518,7 @@
                 // RecordBufferConverter.  TODO: remove when no longer needed.
                 framesOut = min(framesOut,
                         destinationFramesPossible(
-                                framesIn, mSampleRate, activeTrack->mSampleRate));
+                                framesIn, mSampleRate, activeTrack->sampleRate()));
 
                 if (activeTrack->isDirect()) {
                     // No RecordBufferConverter used for direct streams. Pass
@@ -8393,14 +8526,15 @@
                     AudioBufferProvider::Buffer buffer;
                     buffer.frameCount = framesOut;
                     const status_t getNextBufferStatus =
-                            activeTrack->mResamplerBufferProvider->getNextBuffer(&buffer);
+                            activeTrack->resamplerBufferProvider()->getNextBuffer(&buffer);
                     if (getNextBufferStatus == OK && buffer.frameCount != 0) {
                         ALOGV_IF(buffer.frameCount != framesOut,
                                 "%s() read less than expected (%zu vs %zu)",
                                 __func__, buffer.frameCount, framesOut);
                         framesOut = buffer.frameCount;
-                        memcpy(activeTrack->mSink.raw, buffer.raw, buffer.frameCount * mFrameSize);
-                        activeTrack->mResamplerBufferProvider->releaseBuffer(&buffer);
+                        memcpy(activeTrack->sinkBuffer().raw,
+                                buffer.raw, buffer.frameCount * mFrameSize);
+                        activeTrack->resamplerBufferProvider()->releaseBuffer(&buffer);
                     } else {
                         framesOut = 0;
                         ALOGE("%s() cannot fill request, status: %d, frameCount: %zu",
@@ -8409,9 +8543,9 @@
                 } else {
                     // process frames from the RecordThread buffer provider to the RecordTrack
                     // buffer
-                    framesOut = activeTrack->mRecordBufferConverter->convert(
-                            activeTrack->mSink.raw,
-                            activeTrack->mResamplerBufferProvider,
+                    framesOut = activeTrack->recordBufferConverter()->convert(
+                            activeTrack->sinkBuffer().raw,
+                            activeTrack->resamplerBufferProvider(),
                             framesOut);
                 }
 
@@ -8421,17 +8555,18 @@
 
                 // MediaSyncEvent handling: Synchronize AudioRecord to AudioTrack completion.
                 const ssize_t framesToDrop =
-                        activeTrack->mSynchronizedRecordState.updateRecordFrames(framesOut);
+                        activeTrack->synchronizedRecordState().updateRecordFrames(framesOut);
                 if (framesToDrop == 0) {
                     // no sync event, process normally, otherwise ignore.
                     if (framesOut > 0) {
-                        activeTrack->mSink.frameCount = framesOut;
+                        activeTrack->sinkBuffer().frameCount = framesOut;
                         // Sanitize before releasing if the track has no access to the source data
                         // An idle UID receives silence from non virtual devices until active
                         if (activeTrack->isSilenced()) {
-                            memset(activeTrack->mSink.raw, 0, framesOut * activeTrack->frameSize());
+                            memset(activeTrack->sinkBuffer().raw,
+                                    0, framesOut * activeTrack->frameSize());
                         }
-                        activeTrack->releaseBuffer(&activeTrack->mSink);
+                        activeTrack->releaseBuffer(&activeTrack->sinkBuffer());
                     }
                 }
                 if (framesOut == 0) {
@@ -8460,7 +8595,7 @@
 
             // update frame information and push timestamp out
             activeTrack->updateTrackFrameInfo(
-                    activeTrack->mServerProxy->framesReleased(),
+                    activeTrack->serverProxy()->framesReleased(),
                     mTimestamp.mPosition[ExtendedTimestamp::LOCATION_SERVER],
                     mSampleRate, mTimestamp);
         }
@@ -8493,7 +8628,7 @@
     {
         Mutex::Autolock _l(mLock);
         for (size_t i = 0; i < mTracks.size(); i++) {
-            sp<RecordTrack> track = mTracks[i];
+            sp<IAfRecordTrack> track = mTracks[i];
             track->invalidate();
         }
         mActiveTracks.clear();
@@ -8506,7 +8641,7 @@
     return false;
 }
 
-void AudioFlinger::RecordThread::standbyIfNotAlreadyInStandby()
+void RecordThread::standbyIfNotAlreadyInStandby()
 {
     if (!mStandby) {
         inputStandBy();
@@ -8516,7 +8651,7 @@
     }
 }
 
-void AudioFlinger::RecordThread::inputStandBy()
+void RecordThread::inputStandBy()
 {
     // Idle the fast capture if it's currently running
     if (mFastCapture != 0) {
@@ -8557,7 +8692,7 @@
 }
 
 // RecordThread::createRecordTrack_l() must be called with AudioFlinger::mLock held
-sp<AudioFlinger::RecordThread::RecordTrack> AudioFlinger::RecordThread::createRecordTrack_l(
+sp<IAfRecordTrack> RecordThread::createRecordTrack_l(
         const sp<Client>& client,
         const audio_attributes_t& attr,
         uint32_t *pSampleRate,
@@ -8576,7 +8711,7 @@
 {
     size_t frameCount = *pFrameCount;
     size_t notificationFrameCount = *pNotificationFrameCount;
-    sp<RecordTrack> track;
+    sp<IAfRecordTrack> track;
     status_t lStatus;
     audio_input_flags_t inputFlags = mInput->flags;
     audio_input_flags_t requestedFlags = *flags;
@@ -8600,7 +8735,7 @@
             goto Exit;
         }
         if (maxSharedAudioHistoryMs < 0
-                || maxSharedAudioHistoryMs > AudioFlinger::kMaxSharedAudioHistoryMs) {
+                || maxSharedAudioHistoryMs > kMaxSharedAudioHistoryMs) {
             lStatus = BAD_VALUE;
             goto Exit;
         }
@@ -8722,10 +8857,10 @@
             startFrames = mSharedAudioStartFrames;
         }
 
-        track = new RecordTrack(this, client, attr, sampleRate,
+        track = IAfRecordTrack::create(this, client, attr, sampleRate,
                       format, channelMask, frameCount,
                       nullptr /* buffer */, (size_t)0 /* bufferSize */, sessionId, creatorPid,
-                      attributionSource, *flags, TrackBase::TYPE_DEFAULT, portId,
+                      attributionSource, *flags, IAfTrackBase::TYPE_DEFAULT, portId,
                       startFrames);
 
         lStatus = track->initCheck();
@@ -8755,7 +8890,7 @@
     return track;
 }
 
-status_t AudioFlinger::RecordThread::start(RecordThread::RecordTrack* recordTrack,
+status_t RecordThread::start(IAfRecordTrack* recordTrack,
                                            AudioSystem::sync_event_t event,
                                            audio_session_t triggerSession)
 {
@@ -8766,8 +8901,8 @@
     if (event == AudioSystem::SYNC_EVENT_NONE) {
         recordTrack->clearSyncStartEvent();
     } else if (event != AudioSystem::SYNC_EVENT_SAME) {
-        recordTrack->mSynchronizedRecordState.startRecording(
-                mAudioFlinger->createSyncEvent(
+        recordTrack->synchronizedRecordState().startRecording(
+                mAfThreadCallback->createSyncEvent(
                         event, triggerSession,
                         recordTrack->sessionId(), syncStartEventCallback, recordTrack));
     }
@@ -8781,13 +8916,13 @@
             return DEAD_OBJECT;
         }
         if (mActiveTracks.indexOf(recordTrack) >= 0) {
-            if (recordTrack->mState == TrackBase::PAUSING) {
+            if (recordTrack->state() == IAfTrackBase::PAUSING) {
                 // We haven't stopped yet (moved to PAUSED and not in mActiveTracks)
                 // so no need to startInput().
                 ALOGV("active record track PAUSING -> ACTIVE");
-                recordTrack->mState = TrackBase::ACTIVE;
+                recordTrack->setState(IAfTrackBase::ACTIVE);
             } else {
-                ALOGV("active record track state %d", (int)recordTrack->mState);
+                ALOGV("active record track state %d", (int)recordTrack->state());
             }
             return status;
         }
@@ -8795,7 +8930,7 @@
         // TODO consider other ways of handling this, such as changing the state to :STARTING and
         //      adding the track to mActiveTracks after returning from AudioSystem::startInput(),
         //      or using a separate command thread
-        recordTrack->mState = TrackBase::STARTING_1;
+        recordTrack->setState(IAfTrackBase::STARTING_1);
         mActiveTracks.add(recordTrack);
         if (recordTrack->isExternalTrack()) {
             mLock.unlock();
@@ -8803,16 +8938,16 @@
             mLock.lock();
             if (recordTrack->isInvalid()) {
                 recordTrack->clearSyncStartEvent();
-                if (status == NO_ERROR && recordTrack->mState == TrackBase::STARTING_1) {
-                    recordTrack->mState = TrackBase::STARTING_2;
+                if (status == NO_ERROR && recordTrack->state() == IAfTrackBase::STARTING_1) {
+                    recordTrack->setState(IAfTrackBase::STARTING_2);
                     // STARTING_2 forces destroy to call stopInput.
                 }
                 ALOGW("%s track %d: invalidated after startInput", __func__, recordTrack->portId());
                 return DEAD_OBJECT;
             }
-            if (recordTrack->mState != TrackBase::STARTING_1) {
+            if (recordTrack->state() != IAfTrackBase::STARTING_1) {
                 ALOGW("%s(%d): unsynchronized mState:%d change",
-                    __func__, recordTrack->id(), (int)recordTrack->mState);
+                    __func__, recordTrack->id(), (int)recordTrack->state());
                 // Someone else has changed state, let them take over,
                 // leave mState in the new state.
                 recordTrack->clearSyncStartEvent();
@@ -8839,67 +8974,66 @@
         // was initialized to some value closer to the thread's mRsmpInFront, then the track could
         // see previously buffered data before it called start(), but with greater risk of overrun.
 
-        recordTrack->mResamplerBufferProvider->reset();
+        recordTrack->resamplerBufferProvider()->reset();
         if (!recordTrack->isDirect()) {
             // clear any converter state as new data will be discontinuous
-            recordTrack->mRecordBufferConverter->reset();
+            recordTrack->recordBufferConverter()->reset();
         }
-        recordTrack->mState = TrackBase::STARTING_2;
+        recordTrack->setState(IAfTrackBase::STARTING_2);
         // signal thread to start
         mWaitWorkCV.broadcast();
         return status;
     }
 }
 
-void AudioFlinger::RecordThread::syncStartEventCallback(const wp<audioflinger::SyncEvent>& event)
+void RecordThread::syncStartEventCallback(const wp<SyncEvent>& event)
 {
-    sp<audioflinger::SyncEvent> strongEvent = event.promote();
+    const sp<SyncEvent> strongEvent = event.promote();
 
     if (strongEvent != 0) {
-        sp<RefBase> ptr = std::any_cast<const wp<RefBase>>(strongEvent->cookie()).promote();
-        if (ptr != 0) {
-            RecordTrack *recordTrack = (RecordTrack *)ptr.get();
-            recordTrack->handleSyncStartEvent(strongEvent);
+        sp<IAfTrackBase> ptr =
+                std::any_cast<const wp<IAfTrackBase>>(strongEvent->cookie()).promote();
+        if (ptr != nullptr) {
+            // TODO(b/291317898) handleSyncStartEvent is in IAfTrackBase not IAfRecordTrack.
+            ptr->handleSyncStartEvent(strongEvent);
         }
     }
 }
 
-bool AudioFlinger::RecordThread::stop(RecordThread::RecordTrack* recordTrack) {
+bool RecordThread::stop(IAfRecordTrack* recordTrack) {
     ALOGV("RecordThread::stop");
     AutoMutex _l(mLock);
     // if we're invalid, we can't be on the ActiveTracks.
-    if (mActiveTracks.indexOf(recordTrack) < 0 || recordTrack->mState == TrackBase::PAUSING) {
+    if (mActiveTracks.indexOf(recordTrack) < 0 || recordTrack->state() == IAfTrackBase::PAUSING) {
         return false;
     }
     // note that threadLoop may still be processing the track at this point [without lock]
-    recordTrack->mState = TrackBase::PAUSING;
+    recordTrack->setState(IAfTrackBase::PAUSING);
 
     // NOTE: Waiting here is important to keep stop synchronous.
     // This is needed for proper patchRecord peer release.
-    while (recordTrack->mState == TrackBase::PAUSING && !recordTrack->isInvalid()) {
+    while (recordTrack->state() == IAfTrackBase::PAUSING && !recordTrack->isInvalid()) {
         mWaitWorkCV.broadcast(); // signal thread to stop
         mStartStopCond.wait(mLock);
     }
 
-    if (recordTrack->mState == TrackBase::PAUSED) { // successful stop
+    if (recordTrack->state() == IAfTrackBase::PAUSED) { // successful stop
         ALOGV("Record stopped OK");
         return true;
     }
 
     // don't handle anything - we've been invalidated or restarted and in a different state
     ALOGW_IF("%s(%d): unsynchronized stop, state: %d",
-            __func__, recordTrack->id(), recordTrack->mState);
+            __func__, recordTrack->id(), recordTrack->state());
     return false;
 }
 
-bool AudioFlinger::RecordThread::isValidSyncEvent(
-        const sp<audioflinger::SyncEvent>& /* event */) const
+bool RecordThread::isValidSyncEvent(const sp<SyncEvent>& /* event */) const
 {
     return false;
 }
 
-status_t AudioFlinger::RecordThread::setSyncEvent(
-        const sp<audioflinger::SyncEvent>& event __unused)
+status_t RecordThread::setSyncEvent(const sp<SyncEvent>& /* event */)
 {
 #if 0   // This branch is currently dead code, but is preserved in case it will be needed in future
     if (!isValidSyncEvent(event)) {
@@ -8912,7 +9046,7 @@
     Mutex::Autolock _l(mLock);
 
     for (size_t i = 0; i < mTracks.size(); i++) {
-        sp<RecordTrack> track = mTracks[i];
+        sp<IAfRecordTrack> track = mTracks[i];
         if (eventSession == track->sessionId()) {
             (void) track->setSyncEvent(event);
             ret = NO_ERROR;
@@ -8924,8 +9058,8 @@
 #endif
 }
 
-status_t AudioFlinger::RecordThread::getActiveMicrophones(
-        std::vector<media::MicrophoneInfoFw>* activeMicrophones)
+status_t RecordThread::getActiveMicrophones(
+        std::vector<media::MicrophoneInfoFw>* activeMicrophones) const
 {
     ALOGV("RecordThread::getActiveMicrophones");
     AutoMutex _l(mLock);
@@ -8936,7 +9070,7 @@
     return status;
 }
 
-status_t AudioFlinger::RecordThread::setPreferredMicrophoneDirection(
+status_t RecordThread::setPreferredMicrophoneDirection(
             audio_microphone_direction_t direction)
 {
     ALOGV("setPreferredMicrophoneDirection(%d)", direction);
@@ -8947,7 +9081,7 @@
     return mInput->stream->setPreferredMicrophoneDirection(direction);
 }
 
-status_t AudioFlinger::RecordThread::setPreferredMicrophoneFieldDimension(float zoom)
+status_t RecordThread::setPreferredMicrophoneFieldDimension(float zoom)
 {
     ALOGV("setPreferredMicrophoneFieldDimension(%f)", zoom);
     AutoMutex _l(mLock);
@@ -8957,14 +9091,14 @@
     return mInput->stream->setPreferredMicrophoneFieldDimension(zoom);
 }
 
-status_t AudioFlinger::RecordThread::shareAudioHistory(
+status_t RecordThread::shareAudioHistory(
         const std::string& sharedAudioPackageName, audio_session_t sharedSessionId,
         int64_t sharedAudioStartMs) {
     AutoMutex _l(mLock);
     return shareAudioHistory_l(sharedAudioPackageName, sharedSessionId, sharedAudioStartMs);
 }
 
-status_t AudioFlinger::RecordThread::shareAudioHistory_l(
+status_t RecordThread::shareAudioHistory_l(
         const std::string& sharedAudioPackageName, audio_session_t sharedSessionId,
         int64_t sharedAudioStartMs) {
 
@@ -9004,20 +9138,20 @@
     return NO_ERROR;
 }
 
-void AudioFlinger::RecordThread::resetAudioHistory_l() {
+void RecordThread::resetAudioHistory_l() {
     mSharedAudioSessionId = AUDIO_SESSION_NONE;
     mSharedAudioStartFrames = -1;
     mSharedAudioPackageName = "";
 }
 
-AudioFlinger::ThreadBase::MetadataUpdate AudioFlinger::RecordThread::updateMetadata_l()
+ThreadBase::MetadataUpdate RecordThread::updateMetadata_l()
 {
     if (!isStreamInitialized() || !mActiveTracks.readAndClearHasChanged()) {
         return {}; // nothing to do
     }
     StreamInHalInterface::SinkMetadata metadata;
     auto backInserter = std::back_inserter(metadata.tracks);
-    for (const sp<RecordTrack> &track : mActiveTracks) {
+    for (const sp<IAfRecordTrack>& track : mActiveTracks) {
         track->copyMetadataTo(backInserter);
     }
     mInput->stream->updateSinkMetadata(metadata);
@@ -9027,10 +9161,10 @@
 }
 
 // destroyTrack_l() must be called with ThreadBase::mLock held
-void AudioFlinger::RecordThread::destroyTrack_l(const sp<RecordTrack>& track)
+void RecordThread::destroyTrack_l(const sp<IAfRecordTrack>& track)
 {
     track->terminate();
-    track->mState = TrackBase::STOPPED;
+    track->setState(IAfTrackBase::STOPPED);
 
     // active tracks are removed by threadLoop()
     if (mActiveTracks.indexOf(track) < 0) {
@@ -9038,7 +9172,7 @@
     }
 }
 
-void AudioFlinger::RecordThread::removeTrack_l(const sp<RecordTrack>& track)
+void RecordThread::removeTrack_l(const sp<IAfRecordTrack>& track)
 {
     String8 result;
     track->appendDump(result, false /* active */);
@@ -9052,7 +9186,7 @@
     }
 }
 
-void AudioFlinger::RecordThread::dumpInternals_l(int fd, const Vector<String16>& args __unused)
+void RecordThread::dumpInternals_l(int fd, const Vector<String16>& /* args */)
 {
     AudioStreamIn *input = mInput;
     audio_input_flags_t flags = input != NULL ? input->flags : AUDIO_INPUT_FLAG_NONE;
@@ -9080,7 +9214,7 @@
     copy->dump(fd);
 }
 
-void AudioFlinger::RecordThread::dumpTracks_l(int fd, const Vector<String16>& args __unused)
+void RecordThread::dumpTracks_l(int fd, const Vector<String16>& /* args */)
 {
     String8 result;
     size_t numtracks = mTracks.size();
@@ -9093,7 +9227,7 @@
         result.append(prefix);
         mTracks[0]->appendDumpHeader(result);
         for (size_t i = 0; i < numtracks ; ++i) {
-            sp<RecordTrack> track = mTracks[i];
+            sp<IAfRecordTrack> track = mTracks[i];
             if (track != 0) {
                 bool active = mActiveTracks.indexOf(track) >= 0;
                 if (active) {
@@ -9113,7 +9247,7 @@
         result.append(prefix);
         mActiveTracks[0]->appendDumpHeader(result);
         for (size_t i = 0; i < numactive; ++i) {
-            sp<RecordTrack> track = mActiveTracks[i];
+            sp<IAfRecordTrack> track = mActiveTracks[i];
             if (mTracks.indexOf(track) < 0) {
                 result.append(prefix);
                 track->appendDump(result, true /* active */);
@@ -9124,21 +9258,21 @@
     write(fd, result.string(), result.size());
 }
 
-void AudioFlinger::RecordThread::setRecordSilenced(audio_port_handle_t portId, bool silenced)
+void 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];
+        sp<IAfRecordTrack> track = mTracks[i];
         if (track != 0 && track->portId() == portId) {
             track->setSilenced(silenced);
         }
     }
 }
 
-void AudioFlinger::RecordThread::ResamplerBufferProvider::reset()
+void ResamplerBufferProvider::reset()
 {
-    sp<ThreadBase> threadBase = mRecordTrack->mThread.promote();
-    RecordThread *recordThread = (RecordThread *) threadBase.get();
+    const auto threadBase = mRecordTrack->thread().promote();
+    auto* const recordThread = static_cast<RecordThread *>(threadBase->asIAfRecordThread().get());
     mRsmpInUnrel = 0;
     const int32_t rear = recordThread->mRsmpInRear;
     ssize_t deltaFrames = 0;
@@ -9158,11 +9292,11 @@
     mRsmpInFront = audio_utils::safe_sub_overflow(rear, static_cast<int32_t>(deltaFrames));
 }
 
-void AudioFlinger::RecordThread::ResamplerBufferProvider::sync(
+void ResamplerBufferProvider::sync(
         size_t *framesAvailable, bool *hasOverrun)
 {
-    sp<ThreadBase> threadBase = mRecordTrack->mThread.promote();
-    RecordThread *recordThread = (RecordThread *) threadBase.get();
+    const auto threadBase = mRecordTrack->thread().promote();
+    auto* const recordThread = static_cast<RecordThread *>(threadBase->asIAfRecordThread().get());
     const int32_t rear = recordThread->mRsmpInRear;
     const int32_t front = mRsmpInFront;
     const ssize_t filled = audio_utils::safe_sub_overflow(rear, front);
@@ -9192,16 +9326,16 @@
 }
 
 // AudioBufferProvider interface
-status_t AudioFlinger::RecordThread::ResamplerBufferProvider::getNextBuffer(
+status_t ResamplerBufferProvider::getNextBuffer(
         AudioBufferProvider::Buffer* buffer)
 {
-    sp<ThreadBase> threadBase = mRecordTrack->mThread.promote();
+    const auto threadBase = mRecordTrack->thread().promote();
     if (threadBase == 0) {
         buffer->frameCount = 0;
         buffer->raw = NULL;
         return NOT_ENOUGH_DATA;
     }
-    RecordThread *recordThread = (RecordThread *) threadBase.get();
+    auto* const recordThread = static_cast<RecordThread *>(threadBase->asIAfRecordThread().get());
     int32_t rear = recordThread->mRsmpInRear;
     int32_t front = mRsmpInFront;
     ssize_t filled = audio_utils::safe_sub_overflow(rear, front);
@@ -9235,7 +9369,7 @@
 }
 
 // AudioBufferProvider interface
-void AudioFlinger::RecordThread::ResamplerBufferProvider::releaseBuffer(
+void ResamplerBufferProvider::releaseBuffer(
         AudioBufferProvider::Buffer* buffer)
 {
     int32_t stepCount = static_cast<int32_t>(buffer->frameCount);
@@ -9249,18 +9383,18 @@
     buffer->frameCount = 0;
 }
 
-void AudioFlinger::RecordThread::checkBtNrec()
+void RecordThread::checkBtNrec()
 {
     Mutex::Autolock _l(mLock);
     checkBtNrec_l();
 }
 
-void AudioFlinger::RecordThread::checkBtNrec_l()
+void RecordThread::checkBtNrec_l()
 {
     // disable AEC and NS if the device is a BT SCO headset supporting those
     // pre processings
     bool suspend = audio_is_bluetooth_sco_device(inDeviceType()) &&
-                        mAudioFlinger->btNrecIsOff();
+                        mAfThreadCallback->btNrecIsOff();
     if (mBtNrecSuspended.exchange(suspend) != suspend) {
         for (size_t i = 0; i < mEffectChains.size(); i++) {
             setEffectSuspended_l(FX_IID_AEC, suspend, mEffectChains[i]->sessionId());
@@ -9270,7 +9404,7 @@
 }
 
 
-bool AudioFlinger::RecordThread::checkForNewParameter_l(const String8& keyValuePair,
+bool RecordThread::checkForNewParameter_l(const String8& keyValuePair,
                                                         status_t& status)
 {
     bool reconfig = false;
@@ -9358,7 +9492,7 @@
     return reconfig;
 }
 
-String8 AudioFlinger::RecordThread::getParameters(const String8& keys)
+String8 RecordThread::getParameters(const String8& keys)
 {
     Mutex::Autolock _l(mLock);
     if (initCheck() == NO_ERROR) {
@@ -9370,7 +9504,7 @@
     return {};
 }
 
-void AudioFlinger::RecordThread::ioConfigChanged(audio_io_config_event_t event, pid_t pid,
+void RecordThread::ioConfigChanged(audio_io_config_event_t event, pid_t pid,
                                                  audio_port_handle_t portId) {
     sp<AudioIoDescriptor> desc;
     switch (event) {
@@ -9388,10 +9522,10 @@
         desc = sp<AudioIoDescriptor>::make(mId);
         break;
     }
-    mAudioFlinger->ioConfigChanged(event, desc, pid);
+    mAfThreadCallback->ioConfigChanged(event, desc, pid);
 }
 
-void AudioFlinger::RecordThread::readInputParameters_l()
+void RecordThread::readInputParameters_l()
 {
     status_t result = mInput->stream->getAudioProperties(&mSampleRate, &mChannelMask, &mHALFormat);
     LOG_ALWAYS_FATAL_IF(result != OK, "Error retrieving audio properties from HAL: %d", result);
@@ -9425,7 +9559,7 @@
     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_ENCODING, IAfThreadBase::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)
@@ -9434,7 +9568,7 @@
         .record();
 }
 
-uint32_t AudioFlinger::RecordThread::getInputFramesLost()
+uint32_t RecordThread::getInputFramesLost() const
 {
     Mutex::Autolock _l(mLock);
     uint32_t result;
@@ -9444,12 +9578,12 @@
     return 0;
 }
 
-KeyedVector<audio_session_t, bool> AudioFlinger::RecordThread::sessionIds() const
+KeyedVector<audio_session_t, bool> RecordThread::sessionIds() const
 {
     KeyedVector<audio_session_t, bool> ids;
     Mutex::Autolock _l(mLock);
     for (size_t j = 0; j < mTracks.size(); ++j) {
-        sp<RecordThread::RecordTrack> track = mTracks[j];
+        sp<IAfRecordTrack> track = mTracks[j];
         audio_session_t sessionId = track->sessionId();
         if (ids.indexOfKey(sessionId) < 0) {
             ids.add(sessionId, true);
@@ -9458,7 +9592,7 @@
     return ids;
 }
 
-AudioFlinger::AudioStreamIn* AudioFlinger::RecordThread::clearInput()
+AudioStreamIn* RecordThread::clearInput()
 {
     Mutex::Autolock _l(mLock);
     AudioStreamIn *input = mInput;
@@ -9467,7 +9601,7 @@
 }
 
 // this method must always be called either with ThreadBase mLock held or inside the thread loop
-sp<StreamHalInterface> AudioFlinger::RecordThread::stream() const
+sp<StreamHalInterface> RecordThread::stream() const
 {
     if (mInput == NULL) {
         return NULL;
@@ -9475,7 +9609,7 @@
     return mInput->stream;
 }
 
-status_t AudioFlinger::RecordThread::addEffectChain_l(const sp<IAfEffectChain>& chain)
+status_t RecordThread::addEffectChain_l(const sp<IAfEffectChain>& chain)
 {
     ALOGV("addEffectChain_l() %p on thread %p", chain.get(), this);
     chain->setThread(this);
@@ -9493,7 +9627,7 @@
     return NO_ERROR;
 }
 
-size_t AudioFlinger::RecordThread::removeEffectChain_l(const sp<IAfEffectChain>& chain)
+size_t RecordThread::removeEffectChain_l(const sp<IAfEffectChain>& chain)
 {
     ALOGV("removeEffectChain_l() %p from thread %p", chain.get(), this);
 
@@ -9506,7 +9640,7 @@
     return mEffectChains.size();
 }
 
-status_t AudioFlinger::RecordThread::createAudioPatch_l(const struct audio_patch *patch,
+status_t RecordThread::createAudioPatch_l(const struct audio_patch* patch,
                                                           audio_patch_handle_t *handle)
 {
     status_t status = NO_ERROR;
@@ -9563,7 +9697,7 @@
     return status;
 }
 
-status_t AudioFlinger::RecordThread::releaseAudioPatch_l(const audio_patch_handle_t handle)
+status_t RecordThread::releaseAudioPatch_l(const audio_patch_handle_t handle)
 {
     status_t status = NO_ERROR;
 
@@ -9582,7 +9716,7 @@
     return status;
 }
 
-void AudioFlinger::RecordThread::updateOutDevices(const DeviceDescriptorBaseVector& outDevices)
+void RecordThread::updateOutDevices(const DeviceDescriptorBaseVector& outDevices)
 {
     Mutex::Autolock _l(mLock);
     mOutDevices = outDevices;
@@ -9592,7 +9726,7 @@
     }
 }
 
-int32_t AudioFlinger::RecordThread::getOldestFront_l()
+int32_t RecordThread::getOldestFront_l()
 {
     if (mTracks.size() == 0) {
         return mRsmpInRear;
@@ -9600,7 +9734,7 @@
     int32_t oldestFront = mRsmpInRear;
     int32_t maxFilled = 0;
     for (size_t i = 0; i < mTracks.size(); i++) {
-        int32_t front = mTracks[i]->mResamplerBufferProvider->getFront();
+        int32_t front = mTracks[i]->resamplerBufferProvider()->getFront();
         int32_t filled;
         (void)__builtin_sub_overflow(mRsmpInRear, front, &filled);
         if (filled > maxFilled) {
@@ -9614,19 +9748,19 @@
     return oldestFront;
 }
 
-void AudioFlinger::RecordThread::updateFronts_l(int32_t offset)
+void RecordThread::updateFronts_l(int32_t offset)
 {
     if (offset == 0) {
         return;
     }
     for (size_t i = 0; i < mTracks.size(); i++) {
-        int32_t front = mTracks[i]->mResamplerBufferProvider->getFront();
+        int32_t front = mTracks[i]->resamplerBufferProvider()->getFront();
         front = audio_utils::safe_sub_overflow(front, offset);
-        mTracks[i]->mResamplerBufferProvider->setFront(front);
+        mTracks[i]->resamplerBufferProvider()->setFront(front);
     }
 }
 
-void AudioFlinger::RecordThread::resizeInputBuffer_l(int32_t maxSharedAudioHistoryMs)
+void RecordThread::resizeInputBuffer_l(int32_t maxSharedAudioHistoryMs)
 {
     // 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
@@ -9650,7 +9784,7 @@
     mRsmpInRear = 0;
 
     ALOG_ASSERT(maxSharedAudioHistoryMs >= 0
-            && maxSharedAudioHistoryMs <= AudioFlinger::kMaxSharedAudioHistoryMs,
+            && maxSharedAudioHistoryMs <= kMaxSharedAudioHistoryMs,
             "resizeInputBuffer_l() called with invalid max shared history %d",
             maxSharedAudioHistoryMs);
     if (maxSharedAudioHistoryMs != 0) {
@@ -9719,7 +9853,7 @@
     mRsmpInBuffer = rsmpInBuffer;
 }
 
-void AudioFlinger::RecordThread::addPatchTrack(const sp<PatchRecord>& record)
+void RecordThread::addPatchTrack(const sp<IAfPatchRecord>& record)
 {
     Mutex::Autolock _l(mLock);
     mTracks.add(record);
@@ -9728,7 +9862,7 @@
     }
 }
 
-void AudioFlinger::RecordThread::deletePatchTrack(const sp<PatchRecord>& record)
+void RecordThread::deletePatchTrack(const sp<IAfPatchRecord>& record)
 {
     Mutex::Autolock _l(mLock);
     if (mSource == record->getSource()) {
@@ -9737,7 +9871,7 @@
     destroyTrack_l(record);
 }
 
-void AudioFlinger::RecordThread::toAudioPortConfig(struct audio_port_config *config)
+void RecordThread::toAudioPortConfig(struct audio_port_config* config)
 {
     ThreadBase::toAudioPortConfig(config);
     config->role = AUDIO_PORT_ROLE_SINK;
@@ -9753,59 +9887,88 @@
 //      Mmap
 // ----------------------------------------------------------------------------
 
-AudioFlinger::MmapThreadHandle::MmapThreadHandle(const sp<MmapThread>& thread)
+// Mmap stream control interface implementation. Each MmapThreadHandle controls one
+// MmapPlaybackThread or MmapCaptureThread instance.
+class MmapThreadHandle : public MmapStreamInterface {
+public:
+    explicit MmapThreadHandle(const sp<IAfMmapThread>& thread);
+    ~MmapThreadHandle() override;
+
+    // MmapStreamInterface virtuals
+    status_t createMmapBuffer(int32_t minSizeFrames,
+        struct audio_mmap_buffer_info* info) final;
+    status_t getMmapPosition(struct audio_mmap_position* position) final;
+    status_t getExternalPosition(uint64_t* position, int64_t* timeNanos) final;
+    status_t start(const AudioClient& client,
+           const audio_attributes_t* attr, audio_port_handle_t* handle) final;
+    status_t stop(audio_port_handle_t handle) final;
+    status_t standby() final;
+    status_t reportData(const void* buffer, size_t frameCount) final;
+private:
+    const sp<IAfMmapThread> mThread;
+};
+
+/* static */
+sp<MmapStreamInterface> IAfMmapThread::createMmapStreamInterfaceAdapter(
+        const sp<IAfMmapThread>& mmapThread) {
+    return sp<MmapThreadHandle>::make(mmapThread);
+}
+
+MmapThreadHandle::MmapThreadHandle(const sp<IAfMmapThread>& thread)
     : mThread(thread)
 {
     assert(thread != 0); // thread must start non-null and stay non-null
 }
 
-AudioFlinger::MmapThreadHandle::~MmapThreadHandle()
+// MmapStreamInterface could be directly implemented by MmapThread excepting this
+// special handling on adapter dtor.
+MmapThreadHandle::~MmapThreadHandle()
 {
     mThread->disconnect();
 }
 
-status_t AudioFlinger::MmapThreadHandle::createMmapBuffer(int32_t minSizeFrames,
+status_t MmapThreadHandle::createMmapBuffer(int32_t minSizeFrames,
                                   struct audio_mmap_buffer_info *info)
 {
     return mThread->createMmapBuffer(minSizeFrames, info);
 }
 
-status_t AudioFlinger::MmapThreadHandle::getMmapPosition(struct audio_mmap_position *position)
+status_t MmapThreadHandle::getMmapPosition(struct audio_mmap_position* position)
 {
     return mThread->getMmapPosition(position);
 }
 
-status_t AudioFlinger::MmapThreadHandle::getExternalPosition(uint64_t *position,
+status_t MmapThreadHandle::getExternalPosition(uint64_t* position,
                                                              int64_t *timeNanos) {
     return mThread->getExternalPosition(position, timeNanos);
 }
 
-status_t AudioFlinger::MmapThreadHandle::start(const AudioClient& client,
+status_t MmapThreadHandle::start(const AudioClient& client,
         const audio_attributes_t *attr, audio_port_handle_t *handle)
-
 {
     return mThread->start(client, attr, handle);
 }
 
-status_t AudioFlinger::MmapThreadHandle::stop(audio_port_handle_t handle)
+status_t MmapThreadHandle::stop(audio_port_handle_t handle)
 {
     return mThread->stop(handle);
 }
 
-status_t AudioFlinger::MmapThreadHandle::standby()
+status_t MmapThreadHandle::standby()
 {
     return mThread->standby();
 }
 
-status_t AudioFlinger::MmapThreadHandle::reportData(const void* buffer, size_t frameCount) {
+status_t MmapThreadHandle::reportData(const void* buffer, size_t frameCount)
+{
     return mThread->reportData(buffer, frameCount);
 }
 
 
-AudioFlinger::MmapThread::MmapThread(
-        const sp<AudioFlinger>& audioFlinger, audio_io_handle_t id,
+MmapThread::MmapThread(
+        const sp<IAfThreadCallback>& afThreadCallback, audio_io_handle_t id,
         AudioHwDevice *hwDev, const sp<StreamHalInterface>& stream, bool systemReady, bool isOut)
-    : ThreadBase(audioFlinger, id, (isOut ? MMAP_PLAYBACK : MMAP_CAPTURE), systemReady, isOut),
+    : ThreadBase(afThreadCallback, id, (isOut ? MMAP_PLAYBACK : MMAP_CAPTURE), systemReady, isOut),
       mSessionId(AUDIO_SESSION_NONE),
       mPortId(AUDIO_PORT_HANDLE_NONE),
       mHalStream(stream), mHalDevice(hwDev->hwDevice()), mAudioHwDev(hwDev),
@@ -9817,25 +9980,21 @@
     readHalParameters_l();
 }
 
-AudioFlinger::MmapThread::~MmapThread()
-{
-}
-
-void AudioFlinger::MmapThread::onFirstRef()
+void MmapThread::onFirstRef()
 {
     run(mThreadName, ANDROID_PRIORITY_URGENT_AUDIO);
 }
 
-void AudioFlinger::MmapThread::disconnect()
+void MmapThread::disconnect()
 {
-    ActiveTracks<MmapTrack> activeTracks;
+    ActiveTracks<IAfMmapTrack> activeTracks;
     {
         Mutex::Autolock _l(mLock);
-        for (const sp<MmapTrack> &t : mActiveTracks) {
+        for (const sp<IAfMmapTrack>& t : mActiveTracks) {
             activeTracks.add(t);
         }
     }
-    for (const sp<MmapTrack> &t : activeTracks) {
+    for (const sp<IAfMmapTrack>& t : activeTracks) {
         stop(t->portId());
     }
     // This will decrement references and may cause the destruction of this thread.
@@ -9847,7 +10006,7 @@
 }
 
 
-void AudioFlinger::MmapThread::configure(const audio_attributes_t *attr,
+void MmapThread::configure(const audio_attributes_t* attr,
                                                 audio_stream_type_t streamType __unused,
                                                 audio_session_t sessionId,
                                                 const sp<MmapStreamCallback>& callback,
@@ -9861,7 +10020,7 @@
     mPortId = portId;
 }
 
-status_t AudioFlinger::MmapThread::createMmapBuffer(int32_t minSizeFrames,
+status_t MmapThread::createMmapBuffer(int32_t minSizeFrames,
                                   struct audio_mmap_buffer_info *info)
 {
     if (mHalStream == 0) {
@@ -9871,7 +10030,7 @@
     return mHalStream->createMmapBuffer(minSizeFrames, info);
 }
 
-status_t AudioFlinger::MmapThread::getMmapPosition(struct audio_mmap_position *position)
+status_t MmapThread::getMmapPosition(struct audio_mmap_position* position) const
 {
     if (mHalStream == 0) {
         return NO_INIT;
@@ -9879,7 +10038,7 @@
     return mHalStream->getMmapPosition(position);
 }
 
-status_t AudioFlinger::MmapThread::exitStandby_l()
+status_t MmapThread::exitStandby_l()
 {
     // The HAL must receive track metadata before starting the stream
     updateMetadata_l();
@@ -9896,7 +10055,7 @@
     return NO_ERROR;
 }
 
-status_t AudioFlinger::MmapThread::start(const AudioClient& client,
+status_t MmapThread::start(const AudioClient& client,
                                          const audio_attributes_t *attr,
                                          audio_port_handle_t *handle)
 {
@@ -9917,7 +10076,7 @@
     audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE;
 
     audio_io_handle_t io = mId;
-    AttributionSourceState adjAttributionSource = AudioFlinger::checkAttributionSourcePackage(
+    const AttributionSourceState adjAttributionSource = afutils::checkAttributionSourcePackage(
             client.attributionSource);
 
     if (isOutput()) {
@@ -10000,7 +10159,8 @@
     }
 
     // Given that MmapThread::mAttr is mutable, should a MmapTrack have attributes ?
-    sp<MmapTrack> track = new MmapTrack(this, attr == nullptr ? mAttr : *attr, mSampleRate, mFormat,
+    sp<IAfMmapTrack> track = IAfMmapTrack::create(
+            this, attr == nullptr ? mAttr : *attr, mSampleRate, mFormat,
                                         mChannelMask, mSessionId, isOutput(),
                                         client.attributionSource,
                                         IPCThreadState::self()->getCallingPid(), portId);
@@ -10012,7 +10172,7 @@
         // force volume update when a new track is added
         mHalVolFloat = -1.0f;
     } else if (!track->isSilenced_l()) {
-        for (const sp<MmapTrack> &t : mActiveTracks) {
+        for (const sp<IAfMmapTrack>& t : mActiveTracks) {
             if (t->isSilenced_l()
                     && t->uid() != static_cast<uid_t>(client.attributionSource.uid)) {
                 t->invalidate();
@@ -10042,7 +10202,7 @@
     return ret;
 }
 
-status_t AudioFlinger::MmapThread::stop(audio_port_handle_t handle)
+status_t MmapThread::stop(audio_port_handle_t handle)
 {
     ALOGV("%s handle %d", __FUNCTION__, handle);
 
@@ -10057,8 +10217,8 @@
 
     Mutex::Autolock _l(mLock);
 
-    sp<MmapTrack> track;
-    for (const sp<MmapTrack> &t : mActiveTracks) {
+    sp<IAfMmapTrack> track;
+    for (const sp<IAfMmapTrack>& t : mActiveTracks) {
         if (handle == t->portId()) {
             track = t;
             break;
@@ -10096,7 +10256,7 @@
     return NO_ERROR;
 }
 
-status_t AudioFlinger::MmapThread::standby()
+status_t MmapThread::standby()
 {
     ALOGV("%s", __FUNCTION__);
 
@@ -10116,12 +10276,12 @@
     return NO_ERROR;
 }
 
-status_t AudioFlinger::MmapThread::reportData(const void* /*buffer*/, size_t /*frameCount*/) {
+status_t MmapThread::reportData(const void* /*buffer*/, size_t /*frameCount*/) {
     // This is a stub implementation. The MmapPlaybackThread overrides this function.
     return INVALID_OPERATION;
 }
 
-void AudioFlinger::MmapThread::readHalParameters_l()
+void MmapThread::readHalParameters_l()
 {
     status_t result = mHalStream->getAudioProperties(&mSampleRate, &mChannelMask, &mHALFormat);
     LOG_ALWAYS_FATAL_IF(result != OK, "Error retrieving audio properties from HAL: %d", result);
@@ -10138,7 +10298,7 @@
     // 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_ENCODING, IAfThreadBase::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)
@@ -10151,13 +10311,13 @@
                 (int32_t)mHapticChannelCount)
         */
         .set(AMEDIAMETRICS_PROP_PREFIX_HAL    AMEDIAMETRICS_PROP_ENCODING,
-                formatToString(mHALFormat).c_str())
+                IAfThreadBase::formatToString(mHALFormat).c_str())
         .set(AMEDIAMETRICS_PROP_PREFIX_HAL    AMEDIAMETRICS_PROP_FRAMECOUNT,
                 (int32_t)mFrameCount) // sic - added HAL
         .record();
 }
 
-bool AudioFlinger::MmapThread::threadLoop()
+bool MmapThread::threadLoop()
 {
     checkSilentMode_l();
 
@@ -10228,7 +10388,7 @@
 }
 
 // checkForNewParameter_l() must be called with ThreadBase::mLock held
-bool AudioFlinger::MmapThread::checkForNewParameter_l(const String8& keyValuePair,
+bool MmapThread::checkForNewParameter_l(const String8& keyValuePair,
                                                               status_t& status)
 {
     AudioParameter param = AudioParameter(keyValuePair);
@@ -10246,7 +10406,7 @@
     return false;
 }
 
-String8 AudioFlinger::MmapThread::getParameters(const String8& keys)
+String8 MmapThread::getParameters(const String8& keys)
 {
     Mutex::Autolock _l(mLock);
     String8 out_s8;
@@ -10256,7 +10416,7 @@
     return {};
 }
 
-void AudioFlinger::MmapThread::ioConfigChanged(audio_io_config_event_t event, pid_t pid,
+void MmapThread::ioConfigChanged(audio_io_config_event_t event, pid_t pid,
                                                audio_port_handle_t portId __unused) {
     sp<AudioIoDescriptor> desc;
     bool isInput = false;
@@ -10278,10 +10438,10 @@
         desc = sp<AudioIoDescriptor>::make(mId);
         break;
     }
-    mAudioFlinger->ioConfigChanged(event, desc, pid);
+    mAfThreadCallback->ioConfigChanged(event, desc, pid);
 }
 
-status_t AudioFlinger::MmapThread::createAudioPatch_l(const struct audio_patch *patch,
+status_t MmapThread::createAudioPatch_l(const struct audio_patch* patch,
                                                           audio_patch_handle_t *handle)
 NO_THREAD_SAFETY_ANALYSIS  // elease and re-acquire mLock
 {
@@ -10372,7 +10532,7 @@
     return status;
 }
 
-status_t AudioFlinger::MmapThread::releaseAudioPatch_l(const audio_patch_handle_t handle)
+status_t MmapThread::releaseAudioPatch_l(const audio_patch_handle_t handle)
 {
     status_t status = NO_ERROR;
 
@@ -10394,7 +10554,7 @@
     return status;
 }
 
-void AudioFlinger::MmapThread::toAudioPortConfig(struct audio_port_config *config)
+void MmapThread::toAudioPortConfig(struct audio_port_config* config)
 {
     ThreadBase::toAudioPortConfig(config);
     if (isOutput()) {
@@ -10408,14 +10568,14 @@
     }
 }
 
-status_t AudioFlinger::MmapThread::addEffectChain_l(const sp<IAfEffectChain>& chain)
+status_t MmapThread::addEffectChain_l(const sp<IAfEffectChain>& chain)
 {
     audio_session_t session = chain->sessionId();
 
     ALOGV("addEffectChain_l() %p on thread %p for session %d", chain.get(), this, session);
     // Attach all tracks with same session ID to this chain.
     // indicate all active tracks in the chain
-    for (const sp<MmapTrack> &track : mActiveTracks) {
+    for (const sp<IAfMmapTrack>& track : mActiveTracks) {
         if (session == track->sessionId()) {
             chain->incTrackCnt();
             chain->incActiveTrackCnt();
@@ -10432,7 +10592,7 @@
     return NO_ERROR;
 }
 
-size_t AudioFlinger::MmapThread::removeEffectChain_l(const sp<IAfEffectChain>& chain)
+size_t MmapThread::removeEffectChain_l(const sp<IAfEffectChain>& chain)
 {
     audio_session_t session = chain->sessionId();
 
@@ -10443,7 +10603,7 @@
             mEffectChains.removeAt(i);
             // detach all active tracks from the chain
             // detach all tracks with same session ID from this chain
-            for (const sp<MmapTrack> &track : mActiveTracks) {
+            for (const sp<IAfMmapTrack>& track : mActiveTracks) {
                 if (session == track->sessionId()) {
                     chain->decActiveTrackCnt();
                     chain->decTrackCnt();
@@ -10455,29 +10615,29 @@
     return mEffectChains.size();
 }
 
-void AudioFlinger::MmapThread::threadLoop_standby()
+void MmapThread::threadLoop_standby()
 {
     mHalStream->standby();
 }
 
-void AudioFlinger::MmapThread::threadLoop_exit()
+void MmapThread::threadLoop_exit()
 {
     // Do not call callback->onTearDown() because it is redundant for thread exit
     // and because it can cause a recursive mutex lock on stop().
 }
 
-status_t AudioFlinger::MmapThread::setSyncEvent(const sp<audioflinger::SyncEvent>& /* event */)
+status_t MmapThread::setSyncEvent(const sp<SyncEvent>& /* event */)
 {
     return BAD_VALUE;
 }
 
-bool AudioFlinger::MmapThread::isValidSyncEvent(
-        const sp<audioflinger::SyncEvent>& /* event */) const
+bool MmapThread::isValidSyncEvent(
+        const sp<SyncEvent>& /* event */) const
 {
     return false;
 }
 
-status_t AudioFlinger::MmapThread::checkEffectCompatibility_l(
+status_t MmapThread::checkEffectCompatibility_l(
         const effect_descriptor_t *desc, audio_session_t sessionId)
 {
     // No global effect sessions on mmap threads
@@ -10511,11 +10671,11 @@
     return NO_ERROR;
 }
 
-void AudioFlinger::MmapThread::checkInvalidTracks_l()
+void MmapThread::checkInvalidTracks_l()
 NO_THREAD_SAFETY_ANALYSIS  // release and re-acquire mLock
 {
     sp<MmapStreamCallback> callback;
-    for (const sp<MmapTrack> &track : mActiveTracks) {
+    for (const sp<IAfMmapTrack>& track : mActiveTracks) {
         if (track->isInvalid()) {
             callback = mCallback.promote();
             if (callback == nullptr &&  mNoCallbackWarningCount < kMaxNoCallbackWarnings) {
@@ -10532,7 +10692,7 @@
     }
 }
 
-void AudioFlinger::MmapThread::dumpInternals_l(int fd, const Vector<String16>& args __unused)
+void MmapThread::dumpInternals_l(int fd, const Vector<String16>& /* args */)
 {
     dprintf(fd, "  Attributes: content type %d usage %d source %d\n",
             mAttr.content_type, mAttr.usage, mAttr.source);
@@ -10542,7 +10702,7 @@
     }
 }
 
-void AudioFlinger::MmapThread::dumpTracks_l(int fd, const Vector<String16>& args __unused)
+void MmapThread::dumpTracks_l(int fd, const Vector<String16>& /* args */)
 {
     String8 result;
     size_t numtracks = mActiveTracks.size();
@@ -10552,7 +10712,7 @@
         result.append(prefix);
         mActiveTracks[0]->appendDumpHeader(result);
         for (size_t i = 0; i < numtracks ; ++i) {
-            sp<MmapTrack> track = mActiveTracks[i];
+            sp<IAfMmapTrack> track = mActiveTracks[i];
             result.append(prefix);
             track->appendDump(result, true /* active */);
         }
@@ -10562,19 +10722,36 @@
     write(fd, result.string(), result.size());
 }
 
-AudioFlinger::MmapPlaybackThread::MmapPlaybackThread(
-        const sp<AudioFlinger>& audioFlinger, audio_io_handle_t id,
+/* static */
+sp<IAfMmapPlaybackThread> IAfMmapPlaybackThread::create(
+        const sp<IAfThreadCallback>& afThreadCallback, audio_io_handle_t id,
+        AudioHwDevice* hwDev,  AudioStreamOut* output, bool systemReady) {
+    return sp<MmapPlaybackThread>::make(afThreadCallback, id, hwDev, output, systemReady);
+}
+
+MmapPlaybackThread::MmapPlaybackThread(
+        const sp<IAfThreadCallback>& afThreadCallback, audio_io_handle_t id,
         AudioHwDevice *hwDev,  AudioStreamOut *output, bool systemReady)
-    : MmapThread(audioFlinger, id, hwDev, output->stream, systemReady, true /* isOut */),
+    : MmapThread(afThreadCallback, id, hwDev, output->stream, systemReady, true /* isOut */),
       mStreamType(AUDIO_STREAM_MUSIC),
-      mStreamVolume(1.0),
-      mStreamMute(false),
       mOutput(output)
 {
     snprintf(mThreadName, kThreadNameLength, "AudioMmapOut_%X", id);
     mChannelCount = audio_channel_count_from_out_mask(mChannelMask);
-    mMasterVolume = audioFlinger->masterVolume_l();
-    mMasterMute = audioFlinger->masterMute_l();
+    mMasterVolume = afThreadCallback->masterVolume_l();
+    mMasterMute = afThreadCallback->masterMute_l();
+
+    for (int i = AUDIO_STREAM_MIN; i < AUDIO_STREAM_FOR_POLICY_CNT; ++i) {
+        const audio_stream_type_t stream{static_cast<audio_stream_type_t>(i)};
+        mStreamTypes[stream].volume = 0.0f;
+        mStreamTypes[stream].mute = mAfThreadCallback->streamMute_l(stream);
+    }
+    // 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;
+
     if (mAudioHwDev) {
         if (mAudioHwDev->canSetMasterVolume()) {
             mMasterVolume = 1.0;
@@ -10586,7 +10763,7 @@
     }
 }
 
-void AudioFlinger::MmapPlaybackThread::configure(const audio_attributes_t *attr,
+void MmapPlaybackThread::configure(const audio_attributes_t* attr,
                                                 audio_stream_type_t streamType,
                                                 audio_session_t sessionId,
                                                 const sp<MmapStreamCallback>& callback,
@@ -10597,7 +10774,7 @@
     mStreamType = streamType;
 }
 
-AudioStreamOut* AudioFlinger::MmapPlaybackThread::clearOutput()
+AudioStreamOut* MmapPlaybackThread::clearOutput()
 {
     Mutex::Autolock _l(mLock);
     AudioStreamOut *output = mOutput;
@@ -10605,7 +10782,7 @@
     return output;
 }
 
-void AudioFlinger::MmapPlaybackThread::setMasterVolume(float value)
+void MmapPlaybackThread::setMasterVolume(float value)
 {
     Mutex::Autolock _l(mLock);
     // Don't apply master volume in SW if our HAL can do it for us.
@@ -10617,7 +10794,7 @@
     }
 }
 
-void AudioFlinger::MmapPlaybackThread::setMasterMute(bool muted)
+void MmapPlaybackThread::setMasterMute(bool muted)
 {
     Mutex::Autolock _l(mLock);
     // Don't apply master mute in SW if our HAL can do it for us.
@@ -10628,49 +10805,46 @@
     }
 }
 
-void AudioFlinger::MmapPlaybackThread::setStreamVolume(audio_stream_type_t stream, float value)
+void MmapPlaybackThread::setStreamVolume(audio_stream_type_t stream, float value)
 {
     Mutex::Autolock _l(mLock);
+    mStreamTypes[stream].volume = value;
     if (stream == mStreamType) {
-        mStreamVolume = value;
         broadcast_l();
     }
 }
 
-float AudioFlinger::MmapPlaybackThread::streamVolume(audio_stream_type_t stream) const
+float MmapPlaybackThread::streamVolume(audio_stream_type_t stream) const
 {
     Mutex::Autolock _l(mLock);
-    if (stream == mStreamType) {
-        return mStreamVolume;
-    }
-    return 0.0f;
+    return mStreamTypes[stream].volume;
 }
 
-void AudioFlinger::MmapPlaybackThread::setStreamMute(audio_stream_type_t stream, bool muted)
+void MmapPlaybackThread::setStreamMute(audio_stream_type_t stream, bool muted)
 {
     Mutex::Autolock _l(mLock);
+    mStreamTypes[stream].mute = muted;
     if (stream == mStreamType) {
-        mStreamMute= muted;
         broadcast_l();
     }
 }
 
-void AudioFlinger::MmapPlaybackThread::invalidateTracks(audio_stream_type_t streamType)
+void MmapPlaybackThread::invalidateTracks(audio_stream_type_t streamType)
 {
     Mutex::Autolock _l(mLock);
     if (streamType == mStreamType) {
-        for (const sp<MmapTrack> &track : mActiveTracks) {
+        for (const sp<IAfMmapTrack>& track : mActiveTracks) {
             track->invalidate();
         }
         broadcast_l();
     }
 }
 
-void AudioFlinger::MmapPlaybackThread::invalidateTracks(std::set<audio_port_handle_t>& portIds)
+void MmapPlaybackThread::invalidateTracks(std::set<audio_port_handle_t>& portIds)
 {
     Mutex::Autolock _l(mLock);
     bool trackMatch = false;
-    for (const sp<MmapTrack> &track : mActiveTracks) {
+    for (const sp<IAfMmapTrack>& track : mActiveTracks) {
         if (portIds.find(track->portId()) != portIds.end()) {
             track->invalidate();
             trackMatch = true;
@@ -10685,19 +10859,18 @@
     }
 }
 
-void AudioFlinger::MmapPlaybackThread::processVolume_l()
+void MmapPlaybackThread::processVolume_l()
 NO_THREAD_SAFETY_ANALYSIS // access of track->processMuteEvent_l
 {
     float volume;
 
-    if (mMasterMute || mStreamMute) {
+    if (mMasterMute || streamMuted_l()) {
         volume = 0;
     } else {
-        volume = mMasterVolume * mStreamVolume;
+        volume = mMasterVolume * streamVolume_l();
     }
 
     if (volume != mHalVolFloat) {
-
         // Convert volumes from float to 8.24
         uint32_t vol = (uint32_t)(volume * (1 << 24));
 
@@ -10727,12 +10900,12 @@
                 }
             }
         }
-        for (const sp<MmapTrack> &track : mActiveTracks) {
+        for (const sp<IAfMmapTrack>& track : mActiveTracks) {
             track->setMetadataHasChanged();
-            track->processMuteEvent_l(mAudioFlinger->getOrCreateAudioManager(),
+            track->processMuteEvent_l(mAfThreadCallback->getOrCreateAudioManager(),
                 /*muteState=*/{mMasterMute,
-                               mStreamVolume == 0.f,
-                               mStreamMute,
+                               streamVolume_l() == 0.f,
+                               streamMuted_l(),
                                // TODO(b/241533526): adjust logic to include mute from AppOps
                                false /*muteFromPlaybackRestricted*/,
                                false /*muteFromClientVolume*/,
@@ -10741,13 +10914,13 @@
     }
 }
 
-AudioFlinger::ThreadBase::MetadataUpdate AudioFlinger::MmapPlaybackThread::updateMetadata_l()
+ThreadBase::MetadataUpdate MmapPlaybackThread::updateMetadata_l()
 {
     if (!isStreamInitialized() || !mActiveTracks.readAndClearHasChanged()) {
         return {}; // nothing to do
     }
     StreamOutHalInterface::SourceMetadata metadata;
-    for (const sp<MmapTrack> &track : mActiveTracks) {
+    for (const sp<IAfMmapTrack>& track : mActiveTracks) {
         // No track is invalid as this is called after prepareTrack_l in the same critical section
         playback_track_metadata_v7_t trackMetadata;
         trackMetadata.base = {
@@ -10766,7 +10939,7 @@
     return change;
 };
 
-void AudioFlinger::MmapPlaybackThread::checkSilentMode_l()
+void MmapPlaybackThread::checkSilentMode_l()
 {
     if (!mMasterMute) {
         char value[PROPERTY_VALUE_MAX];
@@ -10783,7 +10956,7 @@
     }
 }
 
-void AudioFlinger::MmapPlaybackThread::toAudioPortConfig(struct audio_port_config *config)
+void MmapPlaybackThread::toAudioPortConfig(struct audio_port_config* config)
 {
     MmapThread::toAudioPortConfig(config);
     if (mOutput && mOutput->flags != AUDIO_OUTPUT_FLAG_NONE) {
@@ -10792,8 +10965,8 @@
     }
 }
 
-status_t AudioFlinger::MmapPlaybackThread::getExternalPosition(uint64_t *position,
-                                                               int64_t *timeNanos)
+status_t MmapPlaybackThread::getExternalPosition(uint64_t* position,
+        int64_t* timeNanos) const
 {
     if (mOutput == nullptr) {
         return NO_INIT;
@@ -10806,7 +10979,7 @@
     return status;
 }
 
-status_t AudioFlinger::MmapPlaybackThread::reportData(const void* buffer, size_t frameCount) {
+status_t MmapPlaybackThread::reportData(const void* buffer, size_t frameCount) {
     // Send to MelProcessor for sound dose measurement.
     auto processor = mMelProcessor.load();
     if (processor) {
@@ -10817,7 +10990,7 @@
 }
 
 // startMelComputation_l() must be called with AudioFlinger::mLock held
-void AudioFlinger::MmapPlaybackThread::startMelComputation_l(
+void MmapPlaybackThread::startMelComputation_l(
         const sp<audio_utils::MelProcessor>& processor)
 {
     ALOGV("%s: starting mel processor for thread %d", __func__, id());
@@ -10831,7 +11004,7 @@
 }
 
 // stopMelComputation_l() must be called with AudioFlinger::mLock held
-void AudioFlinger::MmapPlaybackThread::stopMelComputation_l()
+void MmapPlaybackThread::stopMelComputation_l()
 {
     ALOGV("%s: pausing mel processor for thread %d", __func__, id());
     auto melProcessor = mMelProcessor.load();
@@ -10840,26 +11013,33 @@
     }
 }
 
-void AudioFlinger::MmapPlaybackThread::dumpInternals_l(int fd, const Vector<String16>& args)
+void MmapPlaybackThread::dumpInternals_l(int fd, const Vector<String16>& args)
 {
     MmapThread::dumpInternals_l(fd, args);
 
     dprintf(fd, "  Stream type: %d Stream volume: %f HAL volume: %f Stream mute %d\n",
-            mStreamType, mStreamVolume, mHalVolFloat, mStreamMute);
+            mStreamType, streamVolume_l(), mHalVolFloat, streamMuted_l());
     dprintf(fd, "  Master volume: %f Master mute %d\n", mMasterVolume, mMasterMute);
 }
 
-AudioFlinger::MmapCaptureThread::MmapCaptureThread(
-        const sp<AudioFlinger>& audioFlinger, audio_io_handle_t id,
+/* static */
+sp<IAfMmapCaptureThread> IAfMmapCaptureThread::create(
+        const sp<IAfThreadCallback>& afThreadCallback, audio_io_handle_t id,
+        AudioHwDevice* hwDev,  AudioStreamIn* input, bool systemReady) {
+    return sp<MmapCaptureThread>::make(afThreadCallback, id, hwDev, input, systemReady);
+}
+
+MmapCaptureThread::MmapCaptureThread(
+        const sp<IAfThreadCallback>& afThreadCallback, audio_io_handle_t id,
         AudioHwDevice *hwDev,  AudioStreamIn *input, bool systemReady)
-    : MmapThread(audioFlinger, id, hwDev, input->stream, systemReady, false /* isOut */),
+    : MmapThread(afThreadCallback, id, hwDev, input->stream, systemReady, false /* isOut */),
       mInput(input)
 {
     snprintf(mThreadName, kThreadNameLength, "AudioMmapIn_%X", id);
     mChannelCount = audio_channel_count_from_in_mask(mChannelMask);
 }
 
-status_t AudioFlinger::MmapCaptureThread::exitStandby_l()
+status_t MmapCaptureThread::exitStandby_l()
 {
     {
         // mInput might have been cleared by clearInput()
@@ -10870,7 +11050,7 @@
     return MmapThread::exitStandby_l();
 }
 
-AudioFlinger::AudioStreamIn* AudioFlinger::MmapCaptureThread::clearInput()
+AudioStreamIn* MmapCaptureThread::clearInput()
 {
     Mutex::Autolock _l(mLock);
     AudioStreamIn *input = mInput;
@@ -10878,8 +11058,7 @@
     return input;
 }
 
-
-void AudioFlinger::MmapCaptureThread::processVolume_l()
+void MmapCaptureThread::processVolume_l()
 {
     bool changed = false;
     bool silenced = false;
@@ -10906,13 +11085,13 @@
     }
 }
 
-AudioFlinger::ThreadBase::MetadataUpdate AudioFlinger::MmapCaptureThread::updateMetadata_l()
+ThreadBase::MetadataUpdate MmapCaptureThread::updateMetadata_l()
 {
     if (!isStreamInitialized() || !mActiveTracks.readAndClearHasChanged()) {
         return {}; // nothing to do
     }
     StreamInHalInterface::SinkMetadata metadata;
-    for (const sp<MmapTrack> &track : mActiveTracks) {
+    for (const sp<IAfMmapTrack>& track : mActiveTracks) {
         // No track is invalid as this is called after prepareTrack_l in the same critical section
         record_track_metadata_v7_t trackMetadata;
         trackMetadata.base = {
@@ -10929,7 +11108,7 @@
     return change;
 }
 
-void AudioFlinger::MmapCaptureThread::setRecordSilenced(audio_port_handle_t portId, bool silenced)
+void MmapCaptureThread::setRecordSilenced(audio_port_handle_t portId, bool silenced)
 {
     Mutex::Autolock _l(mLock);
     for (size_t i = 0; i < mActiveTracks.size() ; i++) {
@@ -10941,7 +11120,7 @@
     setClientSilencedIfExists_l(portId, silenced);
 }
 
-void AudioFlinger::MmapCaptureThread::toAudioPortConfig(struct audio_port_config *config)
+void MmapCaptureThread::toAudioPortConfig(struct audio_port_config* config)
 {
     MmapThread::toAudioPortConfig(config);
     if (mInput && mInput->flags != AUDIO_INPUT_FLAG_NONE) {
@@ -10950,8 +11129,8 @@
     }
 }
 
-status_t AudioFlinger::MmapCaptureThread::getExternalPosition(
-        uint64_t *position, int64_t *timeNanos)
+status_t MmapCaptureThread::getExternalPosition(
+        uint64_t* position, int64_t* timeNanos) const
 {
     if (mInput == nullptr) {
         return NO_INIT;
@@ -10961,12 +11140,19 @@
 
 // ----------------------------------------------------------------------------
 
-AudioFlinger::BitPerfectThread::BitPerfectThread(const sp<AudioFlinger> &audioflinger,
-        AudioStreamOut *output, audio_io_handle_t id, bool systemReady)
-        : MixerThread(audioflinger, output, id, systemReady, BIT_PERFECT) {}
+/* static */
+sp<IAfPlaybackThread> IAfPlaybackThread::createBitPerfectThread(
+        const sp<IAfThreadCallback>& afThreadCallback,
+        AudioStreamOut* output, audio_io_handle_t id, bool systemReady) {
+    return sp<BitPerfectThread>::make(afThreadCallback, output, id, systemReady);
+}
 
-AudioFlinger::PlaybackThread::mixer_state AudioFlinger::BitPerfectThread::prepareTracks_l(
-        Vector<sp<Track>> *tracksToRemove) {
+BitPerfectThread::BitPerfectThread(const sp<IAfThreadCallback> &afThreadCallback,
+        AudioStreamOut *output, audio_io_handle_t id, bool systemReady)
+        : MixerThread(afThreadCallback, output, id, systemReady, BIT_PERFECT) {}
+
+PlaybackThread::mixer_state BitPerfectThread::prepareTracks_l(
+        Vector<sp<IAfTrack>>* tracksToRemove) {
     mixer_state result = MixerThread::prepareTracks_l(tracksToRemove);
     // If there is only one active track and it is bit-perfect, enable tee buffer.
     float volumeLeft = 1.0f;
@@ -10998,7 +11184,7 @@
     return result;
 }
 
-void AudioFlinger::BitPerfectThread::threadLoop_mix() {
+void BitPerfectThread::threadLoop_mix() {
     MixerThread::threadLoop_mix();
     mHasDataCopiedToSinkBuffer = mIsBitPerfect;
 }
diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h
index 8b420c0..474da8e 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -15,38 +15,43 @@
 ** limitations under the License.
 */
 
-#ifndef INCLUDING_FROM_AUDIOFLINGER_H
-    #error This header file should only be included from AudioFlinger.h
-#endif
+#pragma once
 
-public: // TODO(b/288339104) extract out of AudioFlinger class
-class ThreadBase : public Thread {
+// ADD_BATTERY_DATA AUDIO_WATCHDOG FAST_THREAD_STATISTICS STATE_QUEUE_DUMP TEE_SINK
+#include "Configuration.h"
+#include "IAfThread.h"
+#include "IAfTrack.h"
+
+#include <android-base/macros.h>  // DISALLOW_COPY_AND_ASSIGN
+#include <android/os/IPowerManager.h>
+#include <afutils/AudioWatchdog.h>
+#include <afutils/NBAIO_Tee.h>
+#include <audio_utils/Balance.h>
+#include <audio_utils/SimpleLog.h>
+#include <datapath/ThreadMetrics.h>
+#include <fastpath/FastCapture.h>
+#include <fastpath/FastMixer.h>
+#include <mediautils/Synchronization.h>
+#include <mediautils/ThreadSnapshot.h>
+#include <timing/MonotonicFrameCounter.h>
+#include <utils/Log.h>
+
+namespace android {
+
+class AsyncCallbackThread;
+
+class ThreadBase : public virtual IAfThreadBase, public Thread {
 public:
-
-#include "TrackBase.h"
-
-    enum type_t {
-        MIXER,              // Thread class is MixerThread
-        DIRECT,             // Thread class is DirectOutputThread
-        DUPLICATING,        // Thread class is DuplicatingThread
-        RECORD,             // Thread class is RecordThread
-        OFFLOAD,            // Thread class is OffloadThread
-        MMAP_PLAYBACK,      // Thread class for MMAP playback stream
-        MMAP_CAPTURE,       // Thread class for MMAP capture stream
-        SPATIALIZER,  //
-        BIT_PERFECT,        // Thread class for BitPerfectThread
-        // 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,
+    IAfThreadCallback* afThreadCallback() const final { return mAfThreadCallback.get(); }
+
+    ThreadBase(const sp<IAfThreadCallback>& afThreadCallback, audio_io_handle_t id,
                type_t type, bool systemReady, bool isOut);
-    virtual             ~ThreadBase();
+    ~ThreadBase() override;
 
-    virtual status_t    readyToRun();
-
-    void clearPowerManager();
+    status_t readyToRun() final;
+    void clearPowerManager() final;
 
     // base for record and playback
     enum {
@@ -90,8 +95,6 @@
 
     class ConfigEvent: public RefBase {
     public:
-        virtual ~ConfigEvent() {}
-
         void dump(char *buffer, size_t size) {
             snprintf(buffer, size, "Event type: %d\n", mType);
             if (mData != nullptr) {
@@ -135,7 +138,6 @@
             ConfigEvent(CFG_EVENT_IO) {
             mData = new IoConfigEventData(event, pid, portId);
         }
-        virtual ~IoConfigEvent() {}
     };
 
     class PrioConfigEventData : public ConfigEventData {
@@ -160,7 +162,6 @@
             ConfigEvent(CFG_EVENT_PRIO, true) {
             mData = new PrioConfigEventData(pid, tid, prio, forApp);
         }
-        virtual ~PrioConfigEvent() {}
     };
 
     class SetParameterConfigEventData : public ConfigEventData {
@@ -182,7 +183,6 @@
             mData = new SetParameterConfigEventData(keyValuePairs);
             mWaitStatus = true;
         }
-        virtual ~SetParameterConfigEvent() {}
     };
 
     class CreateAudioPatchConfigEventData : public ConfigEventData {
@@ -207,7 +207,6 @@
             mData = new CreateAudioPatchConfigEventData(patch, handle);
             mWaitStatus = true;
         }
-        virtual ~CreateAudioPatchConfigEvent() {}
     };
 
     class ReleaseAudioPatchConfigEventData : public ConfigEventData {
@@ -229,7 +228,6 @@
             mData = new ReleaseAudioPatchConfigEventData(handle);
             mWaitStatus = true;
         }
-        virtual ~ReleaseAudioPatchConfigEvent() {}
     };
 
     class UpdateOutDevicesConfigEventData : public ConfigEventData {
@@ -250,8 +248,6 @@
             ConfigEvent(CFG_EVENT_UPDATE_OUT_DEVICE) {
             mData = new UpdateOutDevicesConfigEventData(outDevices);
         }
-
-        virtual ~UpdateOutDevicesConfigEvent();
     };
 
     class ResizeBufferConfigEventData : public ConfigEventData {
@@ -272,8 +268,6 @@
             ConfigEvent(CFG_EVENT_RESIZE_BUFFER) {
             mData = new ResizeBufferConfigEventData(maxSharedAudioHistoryMs);
         }
-
-        virtual ~ResizeBufferConfigEvent() {}
     };
 
     class CheckOutputStageEffectsEvent : public ConfigEvent {
@@ -281,8 +275,6 @@
         CheckOutputStageEffectsEvent() :
             ConfigEvent(CFG_EVENT_CHECK_OUTPUT_STAGE_EFFECTS) {
         }
-
-        virtual ~CheckOutputStageEffectsEvent() {}
     };
 
     class HalLatencyModesChangedEvent : public ConfigEvent {
@@ -290,8 +282,6 @@
         HalLatencyModesChangedEvent() :
             ConfigEvent(CFG_EVENT_HAL_LATENCY_MODES_CHANGED) {
         }
-
-        virtual ~HalLatencyModesChangedEvent() {}
     };
 
 
@@ -309,108 +299,87 @@
         wp<ThreadBase> mThread;
     };
 
-    virtual     status_t    initCheck() const = 0;
+    type_t type() const final { return mType; }
+    bool isDuplicating() const final { return (mType == DUPLICATING); }
+    audio_io_handle_t id() const final { return mId;}
 
-                // static externally-visible
-                type_t      type() const { return mType; }
-                bool isDuplicating() const { return (mType == DUPLICATING); }
-
-                audio_io_handle_t id() const { return mId;}
-
-                // dynamic externally-visible
-                uint32_t    sampleRate() const { return mSampleRate; }
-                audio_channel_mask_t channelMask() const { return mChannelMask; }
-    virtual     audio_channel_mask_t mixerChannelMask() const { return mChannelMask; }
-
-                audio_format_t format() const { return mHALFormat; }
-                uint32_t channelCount() const { return mChannelCount; }
-
-                // 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     audio_channel_mask_t hapticChannelMask() const { return AUDIO_CHANNEL_NONE; }
-    virtual     uint32_t    latency_l() const { return 0; }
-    virtual     void        setVolumeForOutput_l(float left __unused, float right __unused) const {}
+    uint32_t sampleRate() const final { return mSampleRate; }
+    audio_channel_mask_t channelMask() const final { return mChannelMask; }
+    audio_channel_mask_t mixerChannelMask() const override { return mChannelMask; }
+    audio_format_t format() const final { return mHALFormat; }
+    uint32_t channelCount() const final { return mChannelCount; }
+    audio_channel_mask_t hapticChannelMask() const override { return AUDIO_CHANNEL_NONE; }
+    uint32_t hapticChannelCount() const override { return 0; }
+    uint32_t latency_l() const override { return 0; }
+    void setVolumeForOutput_l(float /* left */, float /* right */) const override {}
 
                 // Return's the HAL's frame count i.e. fast mixer buffer size.
-                size_t      frameCountHAL() const { return mFrameCount; }
-
-                size_t      frameSize() const { return mFrameSize; }
+    size_t frameCountHAL() const final { return mFrameCount; }
+    size_t frameSize() const final { return mFrameSize; }
 
     // Should be "virtual status_t requestExitAndWait()" and override same
     // method in Thread, but Thread::requestExitAndWait() is not yet virtual.
-                void        exit();
-    virtual     bool        checkForNewParameter_l(const String8& keyValuePair,
-                                                    status_t& status) = 0;
-    virtual     status_t    setParameters(const String8& keyValuePairs);
-    virtual     String8     getParameters(const String8& keys) = 0;
-    virtual     void        ioConfigChanged(audio_io_config_event_t event, pid_t pid = 0,
-                                        audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE) = 0;
+    void exit() final;
+    status_t setParameters(const String8& keyValuePairs) final;
+
                 // sendConfigEvent_l() must be called with ThreadBase::mLock held
                 // Can temporarily release the lock if waiting for a reply from
                 // processConfigEvents_l().
-                status_t    sendConfigEvent_l(sp<ConfigEvent>& event);
-                void        sendIoConfigEvent(audio_io_config_event_t event, pid_t pid = 0,
-                                              audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE);
-                void        sendIoConfigEvent_l(audio_io_config_event_t event, pid_t pid = 0,
-                                            audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE);
-                void        sendPrioConfigEvent(pid_t pid, pid_t tid, int32_t prio, bool forApp);
-                void        sendPrioConfigEvent_l(pid_t pid, pid_t tid, int32_t prio, bool forApp);
-                status_t    sendSetParameterConfigEvent_l(const String8& keyValuePair);
-                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        sendResizeBufferConfigEvent_l(int32_t maxSharedAudioHistoryMs);
-                void        sendCheckOutputStageEffectsEvent();
-                void        sendCheckOutputStageEffectsEvent_l();
-                void        sendHalLatencyModesChangedEvent_l();
+    status_t sendConfigEvent_l(sp<ConfigEvent>& event);
+    void sendIoConfigEvent(audio_io_config_event_t event, pid_t pid = 0,
+            audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE) final;
+    void sendIoConfigEvent_l(audio_io_config_event_t event, pid_t pid = 0,
+            audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE) final;
+    void sendPrioConfigEvent(pid_t pid, pid_t tid, int32_t prio, bool forApp) final;
+    void sendPrioConfigEvent_l(pid_t pid, pid_t tid, int32_t prio, bool forApp) final;
+    status_t sendSetParameterConfigEvent_l(const String8& keyValuePair) final;
+    status_t sendCreateAudioPatchConfigEvent(const struct audio_patch* patch,
+            audio_patch_handle_t* handle) final;
+    status_t sendReleaseAudioPatchConfigEvent(audio_patch_handle_t handle) final;
+    status_t sendUpdateOutDeviceConfigEvent(
+            const DeviceDescriptorBaseVector& outDevices) final;
+    void sendResizeBufferConfigEvent_l(int32_t maxSharedAudioHistoryMs) final;
+    void sendCheckOutputStageEffectsEvent() final;
+    void sendCheckOutputStageEffectsEvent_l() final;
+    void sendHalLatencyModesChangedEvent_l() final;
 
-                void        processConfigEvents_l();
-    virtual     void        setCheckOutputStageEffects() {}
-    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;
+    void processConfigEvents_l() final;
+    void setCheckOutputStageEffects() override {}
+    void updateOutDevices(const DeviceDescriptorBaseVector& outDevices) override;
+    void toAudioPortConfig(struct audio_port_config* config) override;
+    void resizeInputBuffer_l(int32_t maxSharedAudioHistoryMs) override;
 
-    virtual     void        resizeInputBuffer_l(int32_t maxSharedAudioHistoryMs);
+    // see note at declaration of mStandby, mOutDevice and mInDevice
+    bool inStandby() const override { return mStandby; }
+    const DeviceTypeSet outDeviceTypes() const final {
+        return getAudioDeviceTypes(mOutDeviceTypeAddrs);
+    }
+    audio_devices_t inDeviceType() const final { return mInDeviceTypeAddr.mType; }
+    DeviceTypeSet getDeviceTypes() const final {
+        return isOutput() ? outDeviceTypes() : DeviceTypeSet({inDeviceType()});
+    }
 
-                // see note at declaration of mStandby, mOutDevice and mInDevice
-                bool        standby() const { return mStandby; }
-                const DeviceTypeSet outDeviceTypes() const {
-                    return getAudioDeviceTypes(mOutDeviceTypeAddrs);
-                }
-                audio_devices_t inDeviceType() const { return mInDeviceTypeAddr.mType; }
-                DeviceTypeSet getDeviceTypes() const {
-                    return isOutput() ? outDeviceTypes() : DeviceTypeSet({inDeviceType()});
-                }
+    const AudioDeviceTypeAddrVector& outDeviceTypeAddrs() const final {
+        return mOutDeviceTypeAddrs;
+    }
+    const AudioDeviceTypeAddr& inDeviceTypeAddr() const final {
+        return mInDeviceTypeAddr;
+    }
 
-                const AudioDeviceTypeAddrVector& outDeviceTypeAddrs() const {
-                    return mOutDeviceTypeAddrs;
-                }
-                const AudioDeviceTypeAddr& inDeviceTypeAddr() const {
-                    return mInDeviceTypeAddr;
-                }
+    bool isOutput() const final { return mIsOut; }
 
-                bool        isOutput() const { return mIsOut; }
+    bool isOffloadOrMmap() const final {
+        switch (mType) {
+        case OFFLOAD:
+        case MMAP_PLAYBACK:
+        case MMAP_CAPTURE:
+            return true;
+        default:
+            return false;
+        }
+    }
 
-                bool        isOffloadOrMmap() const {
-                    switch (mType) {
-                    case OFFLOAD:
-                    case MMAP_PLAYBACK:
-                    case MMAP_CAPTURE:
-                        return true;
-                    default:
-                        return false;
-                    }
-                }
-
-    virtual     sp<StreamHalInterface> stream() const = 0;
-
-                sp<IAfEffectHandle> createEffect_l(
+    sp<IAfEffectHandle> createEffect_l(
                                     const sp<Client>& client,
                                     const sp<media::IEffectClient>& effectClient,
                                     int32_t priority,
@@ -420,7 +389,7 @@
                                     status_t *status /*non-NULL*/,
                                     bool pinned,
                                     bool probe,
-                                    bool notifyFramesProcessed);
+                                    bool notifyFramesProcessed) final;
 
                 // return values for hasAudioSession (bit field)
                 enum effect_state {
@@ -436,47 +405,40 @@
                                                // bit-perfect track
                 };
 
-                // get effect chain corresponding to session Id.
-                sp<IAfEffectChain> getEffectChain(audio_session_t sessionId);
-                // same as getEffectChain() but must be called with ThreadBase mutex locked
-                sp<IAfEffectChain> getEffectChain_l(audio_session_t sessionId) const;
-                std::vector<int> getEffectIds_l(audio_session_t sessionId);
-                // add an effect chain to the chain list (mEffectChains)
-    virtual     status_t addEffectChain_l(const sp<IAfEffectChain>& chain) = 0;
-                // remove an effect chain from the chain list (mEffectChains)
-    virtual     size_t removeEffectChain_l(const sp<IAfEffectChain>& chain) = 0;
+    // get effect chain corresponding to session Id.
+    sp<IAfEffectChain> getEffectChain(audio_session_t sessionId) const final;
+    // same as getEffectChain() but must be called with ThreadBase mutex locked
+    sp<IAfEffectChain> getEffectChain_l(audio_session_t sessionId) const final;
+    std::vector<int> getEffectIds_l(audio_session_t sessionId) const final;
+
                 // lock all effect chains Mutexes. Must be called before releasing the
                 // ThreadBase mutex before processing the mixer and effects. This guarantees the
                 // integrity of the chains during the process.
                 // Also sets the parameter 'effectChains' to current value of mEffectChains.
-                void lockEffectChains_l(Vector<sp<IAfEffectChain>>& effectChains);
+    void lockEffectChains_l(Vector<sp<IAfEffectChain>>& effectChains) final;
                 // unlock effect chains after process
-                void unlockEffectChains(const Vector<sp<IAfEffectChain>>& effectChains);
+    void unlockEffectChains(const Vector<sp<IAfEffectChain>>& effectChains) final;
                 // get a copy of mEffectChains vector
-                Vector<sp<IAfEffectChain>> getEffectChains_l() const { return mEffectChains; };
+    Vector<sp<IAfEffectChain>> getEffectChains_l() const final { return mEffectChains; };
                 // set audio mode to all effect chains
-                void setMode(audio_mode_t mode);
+    void setMode(audio_mode_t mode) final;
                 // get effect module with corresponding ID on specified audio session
-                sp<IAfEffectModule> getEffect(audio_session_t sessionId, int effectId);
-                sp<IAfEffectModule> getEffect_l(audio_session_t sessionId, int effectId);
+    sp<IAfEffectModule> getEffect(audio_session_t sessionId, int effectId) const final;
+    sp<IAfEffectModule> getEffect_l(audio_session_t sessionId, int effectId) const final;
                 // add and effect module. Also creates the effect chain is none exists for
                 // the effects audio session. Only called in a context of moving an effect
                 // from one thread to another
-                status_t addEffect_l(const sp<IAfEffectModule>& effect);
+    status_t addEffect_l(const sp<IAfEffectModule>& effect) final;
                 // remove and effect module. Also removes the effect chain is this was the last
                 // effect
-                void removeEffect_l(const sp<IAfEffectModule>& effect, bool release = false);
+    void removeEffect_l(const sp<IAfEffectModule>& effect, bool release = false) final;
                 // disconnect an effect handle from module and destroy module if last handle
-                void disconnectEffectHandle(IAfEffectHandle *handle, bool unpinIfLast);
+    void disconnectEffectHandle(IAfEffectHandle* handle, bool unpinIfLast) final;
                 // detach all tracks connected to an auxiliary effect
-    virtual     void detachAuxEffect_l(int effectId __unused) {}
-                // returns a combination of:
-                // - EFFECT_SESSION if effects on this audio session exist in one chain
-                // - TRACK_SESSION if tracks on this audio session exist
-                // - FAST_SESSION if fast tracks on this audio session exist
-                // - SPATIALIZED_SESSION if spatialized tracks on this audio session exist
-    virtual     uint32_t hasAudioSession_l(audio_session_t sessionId) const = 0;
-                uint32_t hasAudioSession(audio_session_t sessionId) const {
+    void detachAuxEffect_l(int /* effectId */) override {}
+    // TODO(b/291317898) - remove hasAudioSession_l below.
+    uint32_t hasAudioSession_l(audio_session_t sessionId) const override = 0;
+    uint32_t hasAudioSession(audio_session_t sessionId) const final {
                     Mutex::Autolock _l(mLock);
                     return hasAudioSession_l(sessionId);
                 }
@@ -488,7 +450,7 @@
                         result = EFFECT_SESSION;
                     }
                     for (size_t i = 0; i < tracks.size(); ++i) {
-                        const sp<TrackBase>& track = tracks[i];
+                        const sp<IAfTrackBase>& track = tracks[i];
                         if (sessionId == track->sessionId()
                                 && !track->isInvalid()       // not yet removed from tracks.
                                 && !track->isTerminated()) {
@@ -510,19 +472,17 @@
 
                 // the value returned by default implementation is not important as the
                 // strategy is only meaningful for PlaybackThread which implements this method
-                virtual product_strategy_t getStrategyForSession_l(
-                        audio_session_t sessionId __unused) {
+    product_strategy_t getStrategyForSession_l(
+            audio_session_t /* sessionId */) const override {
                     return static_cast<product_strategy_t>(0);
                 }
 
                 // check if some effects must be suspended/restored when an effect is enabled
                 // or disabled
-                void checkSuspendOnEffectEnabled(bool enabled,
+    void checkSuspendOnEffectEnabled(bool enabled,
                                                  audio_session_t sessionId,
-                                                 bool threadLocked);
+                                                 bool threadLocked) final;
 
-                virtual status_t setSyncEvent(const sp<audioflinger::SyncEvent>& event) = 0;
-                virtual bool isValidSyncEvent(const sp<audioflinger::SyncEvent>& event) const = 0;
 
                 // Return a reference to a per-thread heap which can be used to allocate IMemory
                 // objects that will be read-only to client processes, read/write to mediaserver,
@@ -530,36 +490,35 @@
                 // The heap is per-thread rather than common across all threads, because
                 // clients can't be trusted not to modify the offset of the IMemory they receive.
                 // If a thread does not have such a heap, this method returns 0.
-                virtual sp<MemoryDealer>    readOnlyHeap() const { return 0; }
+    sp<MemoryDealer> readOnlyHeap() const override { return nullptr; }
 
-                virtual sp<IMemory> pipeMemory() const { return 0; }
+    sp<IMemory> pipeMemory() const override { return nullptr; }
 
-                        void systemReady();
+    void systemReady() final;
 
-                // checkEffectCompatibility_l() must be called with ThreadBase::mLock held
-                virtual status_t    checkEffectCompatibility_l(const effect_descriptor_t *desc,
-                                                               audio_session_t sessionId) = 0;
+    void broadcast_l() final;
 
-                        void        broadcast_l();
+    bool isTimestampCorrectionEnabled() const override { return false; }
 
-                virtual bool        isTimestampCorrectionEnabled() const { return false; }
+    bool isMsdDevice() const final { return mIsMsdDevice; }
 
-                bool                isMsdDevice() const { return mIsMsdDevice; }
-
-                void                dump(int fd, const Vector<String16>& args);
+    void dump(int fd, const Vector<String16>& args) override;
 
                 // deliver stats to mediametrics.
-                void                sendStatistics(bool force);
+    void sendStatistics(bool force) final;
 
+    Mutex& mutex() const final {
+        return mLock;
+    }
     mutable     Mutex                   mLock;
 
-                void onEffectEnable(const sp<IAfEffectModule>& effect);
-                void onEffectDisable();
+    void onEffectEnable(const sp<IAfEffectModule>& effect) final;
+    void onEffectDisable() final;
 
                 // invalidateTracksForAudioSession_l must be called with holding mLock.
-    virtual     void invalidateTracksForAudioSession_l(audio_session_t sessionId __unused) const { }
+    void invalidateTracksForAudioSession_l(audio_session_t /* sessionId */) const override {}
                 // Invalidate all the tracks with the given audio session.
-                void invalidateTracksForAudioSession(audio_session_t sessionId) const {
+    void invalidateTracksForAudioSession(audio_session_t sessionId) const final {
                     Mutex::Autolock _l(mLock);
                     invalidateTracksForAudioSession_l(sessionId);
                 }
@@ -568,17 +527,15 @@
                 void invalidateTracksForAudioSession_l(audio_session_t sessionId,
                                                        const T& tracks) const {
                     for (size_t i = 0; i < tracks.size(); ++i) {
-                        const sp<TrackBase>& track = tracks[i];
+                        const sp<IAfTrackBase>& track = tracks[i];
                         if (sessionId == track->sessionId()) {
                             track->invalidate();
                         }
                     }
                 }
 
-    virtual     bool isStreamInitialized() = 0;
-
-    virtual     void startMelComputation_l(const sp<audio_utils::MelProcessor>& processor);
-    virtual     void stopMelComputation_l();
+    void startMelComputation_l(const sp<audio_utils::MelProcessor>& processor) override;
+    void stopMelComputation_l() override;
 
 protected:
 
@@ -602,7 +559,7 @@
                 // occurs when all suspend requests are cancelled.
                 void setEffectSuspended_l(const effect_uuid_t *type,
                                           bool suspend,
-                                          audio_session_t sessionId);
+                                          audio_session_t sessionId) final;
                 // updated mSuspendedSessions when an effect is suspended or restored
                 void        updateSuspendedSessions_l(const effect_uuid_t *type,
                                                       bool suspend,
@@ -629,7 +586,7 @@
                                 return INVALID_OPERATION;
                             }
 public:
-// TODO(b/288339104) organize with publics
+// TODO(b/291317898) organize with publics
                 product_strategy_t getStrategyForStream(audio_stream_type_t stream) const;
 protected:
 
@@ -639,15 +596,12 @@
                             { }
     virtual     void        dumpTracks_l(int fd __unused, const Vector<String16>& args __unused) { }
 
-
-    friend class AudioFlinger;      // for mEffectChains and mAudioManager
-
                 const type_t            mType;
 
                 // Used by parameters, config events, addTrack_l, exit
                 Condition               mWaitWorkCV;
 
-                const sp<AudioFlinger>  mAudioFlinger;
+                const sp<IAfThreadCallback>  mAfThreadCallback;
                 ThreadMetrics           mThreadMetrics;
                 const bool              mIsOut;
 
@@ -784,7 +738,7 @@
                     bool            isEmpty() const {
                         return mActiveTracks.isEmpty();
                     }
-                    ssize_t         indexOf(const sp<T>& item) {
+                    ssize_t indexOf(const sp<T>& item) const {
                         return mActiveTracks.indexOf(item);
                     }
                     sp<T>           operator[](size_t index) const {
@@ -845,35 +799,14 @@
                 void dumpEffectChains_l(int fd, const Vector<String16>& args);
 };
 
-class VolumeInterface {
- public:
-
-    virtual ~VolumeInterface() {}
-
-    virtual void        setMasterVolume(float value) = 0;
-    virtual void        setMasterMute(bool muted) = 0;
-    virtual void        setStreamVolume(audio_stream_type_t stream, float value) = 0;
-    virtual void        setStreamMute(audio_stream_type_t stream, bool muted) = 0;
-    virtual float       streamVolume(audio_stream_type_t stream) const = 0;
-
-};
-
 // --- PlaybackThread ---
-class PlaybackThread : public ThreadBase, public StreamOutHalInterfaceCallback,
-                       public VolumeInterface, public StreamOutHalInterfaceEventCallback {
+class PlaybackThread : public ThreadBase, public virtual IAfPlaybackThread,
+                       public StreamOutHalInterfaceCallback,
+                       public virtual VolumeInterface, public StreamOutHalInterfaceEventCallback {
 public:
-
-#include "PlaybackTracks.h"
-
-    enum mixer_state {
-        MIXER_IDLE,             // no active tracks
-        MIXER_TRACKS_ENABLED,   // at least one active track, but no track has any data ready
-        MIXER_TRACKS_READY,      // at least one active track, and at least one track has data
-        MIXER_DRAIN_TRACK,      // drain currently playing track
-        MIXER_DRAIN_ALL,        // fully drain the hardware
-        // standby mode does not have an enum value
-        // suspend by audio policy manager is orthogonal to mixer state
-    };
+    sp<IAfPlaybackThread> asIAfPlaybackThread() final {
+        return sp<IAfPlaybackThread>::fromExisting(this);
+    }
 
     // retry count before removing active track in case of underrun on offloaded thread:
     // we need to make sure that AudioTrack client has enough time to send large buffers
@@ -881,7 +814,6 @@
     // handled for offloaded tracks
     static const int8_t kMaxTrackRetriesOffload = 20;
     static const int8_t kMaxTrackStartupRetriesOffload = 100;
-    static const int8_t kMaxTrackStopRetriesOffload = 2;
     static constexpr uint32_t kMaxTracksPerUid = 40;
     static constexpr size_t kMaxTracks = 256;
 
@@ -891,19 +823,23 @@
     // for initial conditions or large delays.
     static const nsecs_t kMaxNextBufferDelayNs = 100000000;
 
-    PlaybackThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output,
+    PlaybackThread(const sp<IAfThreadCallback>& afThreadCallback, AudioStreamOut* output,
                    audio_io_handle_t id, type_t type, bool systemReady,
                    audio_config_base_t *mixerConfig = nullptr);
-    virtual             ~PlaybackThread();
+    ~PlaybackThread() override;
 
     // Thread virtuals
-    virtual     bool        threadLoop();
+    bool threadLoop() final;
 
     // RefBase
-    virtual     void        onFirstRef();
+    void onFirstRef() override;
 
-    virtual     status_t    checkEffectCompatibility_l(const effect_descriptor_t *desc,
-                                                       audio_session_t sessionId);
+    status_t checkEffectCompatibility_l(
+            const effect_descriptor_t* desc, audio_session_t sessionId) final;
+
+    void addOutputTrack_l(const sp<IAfTrack>& track) final {
+        mTracks.add(track);
+    }
 
 protected:
     // Code snippets that were lifted up out of threadLoop()
@@ -913,14 +849,14 @@
     virtual     void        threadLoop_drain();
     virtual     void        threadLoop_standby();
     virtual     void        threadLoop_exit();
-    virtual     void        threadLoop_removeTracks(const Vector< sp<Track> >& tracksToRemove);
+    virtual     void        threadLoop_removeTracks(const Vector<sp<IAfTrack>>& tracksToRemove);
 
                 // prepareTracks_l reads and writes mActiveTracks, and returns
                 // the pending set of tracks to remove via Vector 'tracksToRemove'.  The caller
                 // is responsible for clearing or destroying this Vector later on, when it
                 // is safe to do so. That will drop the final ref count and destroy the tracks.
-    virtual     mixer_state prepareTracks_l(Vector< sp<Track> > *tracksToRemove) = 0;
-                void        removeTracks_l(const Vector< sp<Track> >& tracksToRemove);
+    virtual     mixer_state prepareTracks_l(Vector<sp<IAfTrack>>* tracksToRemove) = 0;
+                void        removeTracks_l(const Vector<sp<IAfTrack>>& tracksToRemove);
                 status_t    handleVoipVolume_l(float *volume);
 
     // StreamOutHalInterfaceCallback implementation
@@ -928,18 +864,21 @@
     virtual     void        onDrainReady();
     virtual     void        onError();
 
+public: // AsyncCallbackThread
                 void        resetWriteBlocked(uint32_t sequence);
                 void        resetDraining(uint32_t sequence);
+protected:
 
     virtual     bool        waitingAsyncCallback();
     virtual     bool        waitingAsyncCallback_l();
     virtual     bool        shouldStandby_l();
     virtual     void        onAddNewTrack_l();
+public:  // AsyncCallbackThread
                 void        onAsyncError(); // error reported by AsyncCallbackThread
-
+protected:
     // StreamHalInterfaceCodecFormatCallback implementation
                 void        onCodecFormatChanged(
-                                const std::basic_string<uint8_t>& metadataBs) override;
+            const std::basic_string<uint8_t>& metadataBs) final;
 
     // ThreadBase virtuals
     virtual     void        preExit();
@@ -954,29 +893,28 @@
     virtual     void        setHalLatencyMode_l() {}
 
 
-                void        dumpInternals_l(int fd, const Vector<String16>& args) override;
-                void        dumpTracks_l(int fd, const Vector<String16>& args) override;
+    void dumpInternals_l(int fd, const Vector<String16>& args) override;
+    void dumpTracks_l(int fd, const Vector<String16>& args) final;
 
 public:
 
-    virtual     status_t    initCheck() const { return (mOutput == NULL) ? NO_INIT : NO_ERROR; }
+    status_t initCheck() const final { return mOutput == nullptr ? NO_INIT : NO_ERROR; }
 
                 // return estimated latency in milliseconds, as reported by HAL
-                uint32_t    latency() const;
+    uint32_t latency() const final;
                 // same, but lock must already be held
-                uint32_t    latency_l() const override;
+    uint32_t latency_l() const final;
 
                 // VolumeInterface
-    virtual     void        setMasterVolume(float value);
-    virtual     void        setMasterBalance(float balance);
-    virtual     void        setMasterMute(bool muted);
-    virtual     void        setStreamVolume(audio_stream_type_t stream, float value);
-    virtual     void        setStreamMute(audio_stream_type_t stream, bool muted);
-    virtual     float       streamVolume(audio_stream_type_t stream) const;
+    void setMasterVolume(float value) final;
+    void setMasterBalance(float balance) override;
+    void setMasterMute(bool muted) final;
+    void setStreamVolume(audio_stream_type_t stream, float value) final;
+    void setStreamMute(audio_stream_type_t stream, bool muted) final;
+    float streamVolume(audio_stream_type_t stream) const final;
+    void setVolumeForOutput_l(float left, float right) const final;
 
-                void        setVolumeForOutput_l(float left, float right) const override;
-
-                sp<Track>   createTrack_l(
+    sp<IAfTrack> createTrack_l(
                                 const sp<Client>& client,
                                 audio_stream_type_t streamType,
                                 const audio_attributes_t& attr,
@@ -997,15 +935,20 @@
                                 audio_port_handle_t portId,
                                 const sp<media::IAudioTrackCallback>& callback,
                                 bool isSpatialized,
-                                bool isBitPerfect);
+                                bool isBitPerfect) final;
 
-                AudioStreamOut* getOutput() const;
-                AudioStreamOut* clearOutput();
-                virtual sp<StreamHalInterface> stream() const;
+    bool isTrackActive(const sp<IAfTrack>& track) const final {
+        return mActiveTracks.indexOf(track) >= 0;
+    }
+
+    AudioStreamOut* getOutput_l() const final { return mOutput; }
+    AudioStreamOut* getOutput() const final;
+    AudioStreamOut* clearOutput() final;
+    sp<StreamHalInterface> stream() const final;
 
                 // a very large number of suspend() will eventually wraparound, but unlikely
-                void        suspend() { (void) android_atomic_inc(&mSuspended); }
-                void        restore()
+    void suspend() final { (void) android_atomic_inc(&mSuspended); }
+    void restore() final
                                 {
                                     // if restore() is done without suspend(), get back into
                                     // range so that the next suspend() will operate correctly
@@ -1013,123 +956,127 @@
                                         android_atomic_release_store(0, &mSuspended);
                                     }
                                 }
-                bool        isSuspended() const
+    bool isSuspended() const final
                                 { return android_atomic_acquire_load(&mSuspended) > 0; }
 
-    virtual     String8     getParameters(const String8& keys);
-    virtual     void        ioConfigChanged(audio_io_config_event_t event, pid_t pid = 0,
-                                            audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE);
-                status_t    getRenderPosition(uint32_t *halFrames, uint32_t *dspFrames);
+    String8 getParameters(const String8& keys);
+    void ioConfigChanged(audio_io_config_event_t event, pid_t pid = 0,
+            audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE) final;
+    status_t getRenderPosition(uint32_t* halFrames, uint32_t* dspFrames) const final;
                 // Consider also removing and passing an explicit mMainBuffer initialization
-                // parameter to AF::PlaybackThread::Track::Track().
-                float *sinkBuffer() const {
+                // parameter to AF::IAfTrack::Track().
+    float* sinkBuffer() const final {
                     return reinterpret_cast<float *>(mSinkBuffer); };
 
-    virtual     void detachAuxEffect_l(int effectId);
-                status_t attachAuxEffect(const sp<AudioFlinger::PlaybackThread::Track>& track,
-                        int EffectId);
-                status_t attachAuxEffect_l(const sp<AudioFlinger::PlaybackThread::Track>& track,
-                        int EffectId);
+    void detachAuxEffect_l(int effectId) final;
 
-                virtual status_t addEffectChain_l(const sp<IAfEffectChain>& chain);
-                virtual size_t removeEffectChain_l(const sp<IAfEffectChain>& chain);
-                        uint32_t hasAudioSession_l(audio_session_t sessionId) const override {
+    status_t attachAuxEffect(const sp<IAfTrack>& track, int EffectId) final;
+    status_t attachAuxEffect_l(const sp<IAfTrack>& track, int EffectId) final;
+
+    status_t addEffectChain_l(const sp<IAfEffectChain>& chain) final;
+    size_t removeEffectChain_l(const sp<IAfEffectChain>& chain) final;
+    uint32_t hasAudioSession_l(audio_session_t sessionId) const final {
                             return ThreadBase::hasAudioSession_l(sessionId, mTracks);
                         }
-                virtual product_strategy_t getStrategyForSession_l(audio_session_t sessionId);
+    product_strategy_t getStrategyForSession_l(audio_session_t sessionId) const final;
 
 
-                status_t setSyncEvent(const sp<audioflinger::SyncEvent>& event) override;
-                bool     isValidSyncEvent(const sp<audioflinger::SyncEvent>& event) const override;
+    status_t setSyncEvent(const sp<audioflinger::SyncEvent>& event) final;
+    bool isValidSyncEvent(const sp<audioflinger::SyncEvent>& event) const final;
 
                 // called with AudioFlinger lock held
-                        bool     invalidateTracks_l(audio_stream_type_t streamType);
-                        bool     invalidateTracks_l(std::set<audio_port_handle_t>& portIds);
-                virtual void     invalidateTracks(audio_stream_type_t streamType);
+    bool invalidateTracks_l(audio_stream_type_t streamType) final;
+    bool invalidateTracks_l(std::set<audio_port_handle_t>& portIds) final;
+    void invalidateTracks(audio_stream_type_t streamType) override;
                 // Invalidate tracks by a set of port ids. The port id will be removed from
                 // the given set if the corresponding track is found and invalidated.
-                virtual void     invalidateTracks(std::set<audio_port_handle_t>& portIds);
+    void invalidateTracks(std::set<audio_port_handle_t>& portIds) override;
 
-    virtual     size_t      frameCount() const { return mNormalFrameCount; }
+    size_t frameCount() const final { return mNormalFrameCount; }
 
-                audio_channel_mask_t mixerChannelMask() const override {
+    audio_channel_mask_t mixerChannelMask() const final {
                     return mMixerChannelMask;
                 }
 
-                status_t    getTimestamp_l(AudioTimestamp& timestamp);
+    status_t getTimestamp_l(AudioTimestamp& timestamp) final;
 
-                void        addPatchTrack(const sp<PatchTrack>& track);
-                void        deletePatchTrack(const sp<PatchTrack>& track);
+    void addPatchTrack(const sp<IAfPatchTrack>& track) final;
+    void deletePatchTrack(const sp<IAfPatchTrack>& track) final;
 
-    virtual     void        toAudioPortConfig(struct audio_port_config *config);
+    void toAudioPortConfig(struct audio_port_config* config) final;
 
                 // Return the asynchronous signal wait time.
-    virtual     int64_t     computeWaitTimeNs_l() const { return INT64_MAX; }
+    int64_t computeWaitTimeNs_l() const override { return INT64_MAX; }
                 // returns true if the track is allowed to be added to the thread.
-    virtual     bool        isTrackAllowed_l(
+    bool isTrackAllowed_l(
                                     audio_channel_mask_t channelMask __unused,
                                     audio_format_t format __unused,
                                     audio_session_t sessionId __unused,
-                                    uid_t uid) const {
+                                    uid_t uid) const override {
                                 return trackCountForUid_l(uid) < PlaybackThread::kMaxTracksPerUid
                                        && mTracks.size() < PlaybackThread::kMaxTracks;
                             }
 
-                bool        isTimestampCorrectionEnabled() const override {
+    bool isTimestampCorrectionEnabled() const final {
                                 return audio_is_output_devices(mTimestampCorrectedDevice)
                                         && outDeviceTypes().count(mTimestampCorrectedDevice) != 0;
                             }
 
-    virtual     bool        isStreamInitialized() {
+    bool isStreamInitialized() const final {
                                 return !(mOutput == nullptr || mOutput->stream == nullptr);
                             }
 
-                audio_channel_mask_t hapticChannelMask() const override {
+    audio_channel_mask_t hapticChannelMask() const final {
                                          return mHapticChannelMask;
                                      }
-                bool supportsHapticPlayback() const {
+
+    uint32_t hapticChannelCount() const final {
+        return mHapticChannelCount;
+    }
+
+    bool supportsHapticPlayback() const final {
                     return (mHapticChannelMask & AUDIO_CHANNEL_HAPTIC_ALL) != AUDIO_CHANNEL_NONE;
                 }
 
-                void setDownStreamPatch(const struct audio_patch *patch) {
+    void setDownStreamPatch(const struct audio_patch* patch) final {
                     Mutex::Autolock _l(mLock);
                     mDownStreamPatch = *patch;
                 }
 
-                PlaybackThread::Track* getTrackById_l(audio_port_handle_t trackId);
+    IAfTrack* getTrackById_l(audio_port_handle_t trackId) final;
 
-                bool hasMixer() const {
+    bool hasMixer() const final {
                     return mType == MIXER || mType == DUPLICATING || mType == SPATIALIZER;
                 }
 
-    virtual     status_t setRequestedLatencyMode(
-            audio_latency_mode_t mode __unused) { return INVALID_OPERATION; }
+    status_t setRequestedLatencyMode(
+            audio_latency_mode_t /* mode */) override { return INVALID_OPERATION; }
 
-    virtual     status_t getSupportedLatencyModes(
-                        std::vector<audio_latency_mode_t>* modes __unused) {
+    status_t getSupportedLatencyModes(
+            std::vector<audio_latency_mode_t>* /* modes */) override {
                     return INVALID_OPERATION;
                 }
 
-    virtual     status_t setBluetoothVariableLatencyEnabled(bool enabled __unused) {
+    status_t setBluetoothVariableLatencyEnabled(bool /* enabled */) override{
                     return INVALID_OPERATION;
                 }
 
-                void startMelComputation_l(const sp<audio_utils::MelProcessor>& processor) override;
-                void stopMelComputation_l() override;
+    void startMelComputation_l(const sp<audio_utils::MelProcessor>& processor) override;
+    void stopMelComputation_l() override;
 
-                void setStandby() {
+    void setStandby() final {
                     Mutex::Autolock _l(mLock);
                     setStandby_l();
                 }
 
-                void setStandby_l() {
+    void setStandby_l() final {
                     mStandby = true;
                     mHalStarted = false;
                     mKernelPositionOnStandby =
                         mTimestamp.mPosition[ExtendedTimestamp::LOCATION_KERNEL];
                 }
 
-                bool waitForHalStart() {
+    bool waitForHalStart() final {
                     Mutex::Autolock _l(mLock);
                     static const nsecs_t kWaitHalTimeoutNs = seconds(2);
                     nsecs_t endWaitTimetNs = systemTime() + kWaitHalTimeoutNs;
@@ -1244,7 +1191,6 @@
 
     audio_channel_mask_t            mMixerChannelMask = AUDIO_CHANNEL_NONE;
 
-private:
     // mMasterMute is in both PlaybackThread and in AudioFlinger.  When a
     // PlaybackThread needs to find out if master-muted, it checks it's local
     // copy rather than the one in AudioFlinger.  This optimization saves a lock.
@@ -1258,8 +1204,7 @@
                             : mTimestampVerifier.DISCONTINUITY_MODE_CONTINUOUS;
                 }
 
-protected:
-    ActiveTracks<Track>     mActiveTracks;
+    ActiveTracks<IAfTrack> mActiveTracks;
 
     // Time to sleep between cycles when:
     virtual uint32_t        activeSleepTimeUs() const;      // mixer state MIXER_TRACKS_ENABLED
@@ -1269,7 +1214,7 @@
     // No sleep in standby mode; waits on a condition
 
     // Code snippets that are temporarily lifted up out of threadLoop() until the merge
-                void        checkSilentMode_l();
+    virtual void checkSilentMode_l() final;  // consider unification with MMapThread
 
     // Non-trivial for DUPLICATING only
     virtual     void        saveOutputTracks() { }
@@ -1287,26 +1232,23 @@
                                    audio_patch_handle_t *handle);
     virtual     status_t    releaseAudioPatch_l(const audio_patch_handle_t handle);
 
-                bool        usesHwAvSync() const { return (mType == DIRECT) && (mOutput != NULL)
+    bool usesHwAvSync() const final { return mType == DIRECT && mOutput != nullptr
                                     && mHwSupportsPause
                                     && (mOutput->flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC); }
 
                 uint32_t    trackCountForUid_l(uid_t uid) const;
 
                 void        invalidateTracksForAudioSession_l(
-                                    audio_session_t sessionId) const override {
+    audio_session_t sessionId) const override {
                                 ThreadBase::invalidateTracksForAudioSession_l(sessionId, mTracks);
                             }
 
-private:
-
-    friend class AudioFlinger;      // for numerous
-
     DISALLOW_COPY_AND_ASSIGN(PlaybackThread);
 
-    status_t    addTrack_l(const sp<Track>& track);
-    bool        destroyTrack_l(const sp<Track>& track);
-    void        removeTrack_l(const sp<Track>& track);
+    status_t addTrack_l(const sp<IAfTrack>& track) final;
+    bool destroyTrack_l(const sp<IAfTrack>& track) final;
+
+    void        removeTrack_l(const sp<IAfTrack>& track);
 
     void        readOutputParameters_l();
     MetadataUpdate          updateMetadata_l() final;
@@ -1364,9 +1306,10 @@
         SortedVector<sp<T>> mTracks; // wrapped SortedVector.
     };
 
-    Tracks<Track>                   mTracks;
+    Tracks<IAfTrack>                   mTracks;
 
     stream_type_t                   mStreamTypes[AUDIO_STREAM_CNT];
+
     AudioStreamOut                  *mOutput;
 
     float                           mMasterVolume;
@@ -1421,19 +1364,20 @@
     // Bit 0 is reset by the async callback thread calling resetDraining(). Out of sequence
     // callbacks are ignored.
     uint32_t                        mDrainSequence;
+
     sp<AsyncCallbackThread>         mCallbackThread;
 
     Mutex                                    mAudioTrackCbLock;
     // Record of IAudioTrackCallback
-    std::map<sp<Track>, sp<media::IAudioTrackCallback>> mAudioTrackCallbacks;
+    std::map<sp<IAfTrack>, sp<media::IAudioTrackCallback>> mAudioTrackCallbacks;
 
-private:
     // The HAL output sink is treated as non-blocking, but current implementation is blocking
     sp<NBAIO_Sink>          mOutputSink;
     // If a fast mixer is present, the blocking pipe sink, otherwise clear
     sp<NBAIO_Sink>          mPipeSink;
     // The current sink for the normal mixer to write it's (sub)mix, mOutputSink or mPipeSink
     sp<NBAIO_Sink>          mNormalSink;
+
     uint32_t                mScreenState;   // cached copy of gScreenState
     // TODO: add comment and adjust size as needed
     static const size_t     kFastMixerLogSize = 8 * 1024;
@@ -1451,14 +1395,14 @@
     int64_t                  mKernelPositionOnStandby = 0;
 
 public:
-    virtual     bool        hasFastMixer() const = 0;
-    virtual     FastTrackUnderruns getFastTrackUnderruns(size_t fastIndex __unused) const
-                                { FastTrackUnderruns dummy; return dummy; }
-                const std::atomic<int64_t>& framesWritten() const { return mFramesWritten; }
+    FastTrackUnderruns getFastTrackUnderruns(size_t /* fastIndex */) const override
+        { return {}; }
+    const std::atomic<int64_t>& framesWritten() const final { return mFramesWritten; }
 
 protected:
                 // accessed by both binder threads and within threadLoop(), lock on mutex needed
-                unsigned    mFastTrackAvailMask;    // bit i set if fast track [i] is available
+     uint32_t& fastTrackAvailMask_l() final { return mFastTrackAvailMask; }
+     uint32_t mFastTrackAvailMask;  // bit i set if fast track [i] is available
                 bool        mHwSupportsPause;
                 bool        mHwPaused;
                 bool        mFlushPending;
@@ -1509,36 +1453,35 @@
 class MixerThread : public PlaybackThread,
                     public StreamOutHalInterfaceLatencyModeCallback  {
 public:
-    MixerThread(const sp<AudioFlinger>& audioFlinger,
+    MixerThread(const sp<IAfThreadCallback>& afThreadCallback,
                 AudioStreamOut* output,
                 audio_io_handle_t id,
                 bool systemReady,
                 type_t type = MIXER,
                 audio_config_base_t *mixerConfig = nullptr);
-    virtual             ~MixerThread();
+    ~MixerThread() override;
 
     // RefBase
-    virtual     void        onFirstRef();
+    void onFirstRef() override;
 
                 // StreamOutHalInterfaceLatencyModeCallback
                 void        onRecommendedLatencyModeChanged(
-                                    std::vector<audio_latency_mode_t> modes) override;
+            std::vector<audio_latency_mode_t> modes) final;
 
     // Thread virtuals
 
-    virtual     bool        checkForNewParameter_l(const String8& keyValuePair,
-                                                   status_t& status);
+    bool checkForNewParameter_l(const String8& keyValuePair, status_t& status) final;
 
-    virtual     bool        isTrackAllowed_l(
+    bool isTrackAllowed_l(
                                     audio_channel_mask_t channelMask, audio_format_t format,
-                                    audio_session_t sessionId, uid_t uid) const override;
+                                    audio_session_t sessionId, uid_t uid) const final;
 protected:
-    virtual     mixer_state prepareTracks_l(Vector< sp<Track> > *tracksToRemove);
-    virtual     uint32_t    idleSleepTimeUs() const;
-    virtual     uint32_t    suspendSleepTimeUs() const;
-    virtual     void        cacheParameters_l();
+    mixer_state prepareTracks_l(Vector<sp<IAfTrack>>* tracksToRemove) override;
+    uint32_t idleSleepTimeUs() const final;
+    uint32_t suspendSleepTimeUs() const final;
+    void cacheParameters_l() override;
 
-    virtual void acquireWakeLock_l() {
+    void acquireWakeLock_l() final {
         PlaybackThread::acquireWakeLock_l();
         if (hasFastMixer()) {
             mFastMixer->setBoottimeOffset(
@@ -1549,15 +1492,15 @@
                 void        dumpInternals_l(int fd, const Vector<String16>& args) override;
 
     // threadLoop snippets
-    virtual     ssize_t     threadLoop_write();
-    virtual     void        threadLoop_standby();
-    virtual     void        threadLoop_mix();
-    virtual     void        threadLoop_sleepTime();
-    virtual     uint32_t    correctLatency_l(uint32_t latency) const;
+    ssize_t threadLoop_write() override;
+    void threadLoop_standby() override;
+    void threadLoop_mix() override;
+    void threadLoop_sleepTime() override;
+    uint32_t correctLatency_l(uint32_t latency) const final;
 
-    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);
+    status_t createAudioPatch_l(
+            const struct audio_patch* patch, audio_patch_handle_t* handle) final;
+    status_t releaseAudioPatch_l(const audio_patch_handle_t handle) final;
 
                 AudioMixer* mAudioMixer;    // normal mixer
 
@@ -1633,17 +1576,21 @@
                 void       setHalLatencyMode_l() override;
 };
 
-class DirectOutputThread : public PlaybackThread {
+class DirectOutputThread : public PlaybackThread, public virtual IAfDirectOutputThread {
 public:
 
-    DirectOutputThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output,
+    sp<IAfDirectOutputThread> asIAfDirectOutputThread() final {
+        return sp<IAfDirectOutputThread>::fromExisting(this);
+    }
+
+    DirectOutputThread(const sp<IAfThreadCallback>& afThreadCallback, AudioStreamOut* output,
                        audio_io_handle_t id, bool systemReady,
                        const audio_offload_info_t& offloadInfo)
-        : DirectOutputThread(audioFlinger, output, id, DIRECT, systemReady, offloadInfo) { }
+        : DirectOutputThread(afThreadCallback, output, id, DIRECT, systemReady, offloadInfo) { }
 
     virtual                 ~DirectOutputThread();
 
-                status_t    selectPresentation(int presentationId, int programId);
+    status_t selectPresentation(int presentationId, int programId) final;
 
     // Thread virtuals
 
@@ -1663,7 +1610,7 @@
                 void        dumpInternals_l(int fd, const Vector<String16>& args) override;
 
     // threadLoop snippets
-    virtual     mixer_state prepareTracks_l(Vector< sp<Track> > *tracksToRemove);
+    virtual     mixer_state prepareTracks_l(Vector<sp<IAfTrack>>* tracksToRemove);
     virtual     void        threadLoop_mix();
     virtual     void        threadLoop_sleepTime();
     virtual     void        threadLoop_exit();
@@ -1676,16 +1623,16 @@
     audioflinger::MonotonicFrameCounter mMonotonicFrameCounter;  // for VolumeShaper
     bool mVolumeShaperActive = false;
 
-    DirectOutputThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output,
+    DirectOutputThread(const sp<IAfThreadCallback>& afThreadCallback, AudioStreamOut* output,
                        audio_io_handle_t id, ThreadBase::type_t type, bool systemReady,
                        const audio_offload_info_t& offloadInfo);
-    void processVolume_l(Track *track, bool lastTrack);
+    void processVolume_l(IAfTrack *track, bool lastTrack);
     bool isTunerStream() const { return (mOffloadInfo.content_id > 0); }
 
     // prepareTracks_l() tells threadLoop_mix() the name of the single active track
-    sp<Track>               mActiveTrack;
+    sp<IAfTrack>               mActiveTrack;
 
-    wp<Track>               mPreviousTrack;         // used to detect track switch
+    wp<IAfTrack>               mPreviousTrack;         // used to detect track switch
 
     // This must be initialized for initial condition of mMasterBalance = 0 (disabled).
     float                   mMasterBalanceLeft = 1.f;
@@ -1717,7 +1664,7 @@
 class OffloadThread : public DirectOutputThread {
 public:
 
-    OffloadThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output,
+    OffloadThread(const sp<IAfThreadCallback>& afThreadCallback, AudioStreamOut* output,
                   audio_io_handle_t id, bool systemReady,
                   const audio_offload_info_t& offloadInfo);
     virtual                 ~OffloadThread() {};
@@ -1725,7 +1672,7 @@
 
 protected:
     // threadLoop snippets
-    virtual     mixer_state prepareTracks_l(Vector< sp<Track> > *tracksToRemove);
+    virtual     mixer_state prepareTracks_l(Vector<sp<IAfTrack>>* tracksToRemove);
     virtual     void        threadLoop_exit();
 
     virtual     bool        waitingAsyncCallback();
@@ -1743,11 +1690,8 @@
 
 class AsyncCallbackThread : public Thread {
 public:
-
     explicit AsyncCallbackThread(const wp<PlaybackThread>& playbackThread);
 
-    virtual             ~AsyncCallbackThread();
-
     // Thread virtuals
     virtual bool        threadLoop();
 
@@ -1776,16 +1720,21 @@
     bool                       mAsyncError;
 };
 
-class DuplicatingThread : public MixerThread {
+class DuplicatingThread : public MixerThread, public IAfDuplicatingThread {
 public:
-    DuplicatingThread(const sp<AudioFlinger>& audioFlinger, MixerThread* mainThread,
+    DuplicatingThread(const sp<IAfThreadCallback>& afThreadCallback,
+            IAfPlaybackThread* mainThread,
                       audio_io_handle_t id, bool systemReady);
-    virtual                 ~DuplicatingThread();
+    ~DuplicatingThread() override;
+
+    sp<IAfDuplicatingThread> asIAfDuplicatingThread() final {
+        return sp<IAfDuplicatingThread>::fromExisting(this);
+    }
 
     // Thread virtuals
-                void        addOutputTrack(MixerThread* thread);
-                void        removeOutputTrack(MixerThread* thread);
-                uint32_t    waitTimeMs() const { return mWaitTimeMs; }
+    void addOutputTrack(IAfPlaybackThread* thread) final;
+    void removeOutputTrack(IAfPlaybackThread* thread) final;
+    uint32_t waitTimeMs() const final { return mWaitTimeMs; }
 
                 void        sendMetadataToBackend_l(
                         const StreamOutHalInterface::SourceMetadata& metadata) override;
@@ -1812,8 +1761,8 @@
 private:
 
                 uint32_t    mWaitTimeMs;
-    SortedVector < sp<OutputTrack> >  outputTracks;
-    SortedVector < sp<OutputTrack> >  mOutputTracks;
+    SortedVector <sp<IAfOutputTrack>>  outputTracks;
+    SortedVector <sp<IAfOutputTrack>>  mOutputTracks;
 public:
     virtual     bool        hasFastMixer() const { return false; }
                 status_t    threadloop_getHalTimestamp_l(
@@ -1836,23 +1785,22 @@
 
 class SpatializerThread : public MixerThread {
 public:
-    SpatializerThread(const sp<AudioFlinger>& audioFlinger,
+    SpatializerThread(const sp<IAfThreadCallback>& afThreadCallback,
                            AudioStreamOut* output,
                            audio_io_handle_t id,
                            bool systemReady,
                            audio_config_base_t *mixerConfig);
-            ~SpatializerThread() override {}
 
-            bool hasFastMixer() const override { return false; }
+    bool hasFastMixer() const final { return false; }
 
             // RefBase
-            virtual void        onFirstRef();
+    void onFirstRef() final;
 
-            status_t setRequestedLatencyMode(audio_latency_mode_t mode) override;
+    status_t setRequestedLatencyMode(audio_latency_mode_t mode) final;
 
 protected:
-            void checkOutputStageEffects() override;
-            void setHalLatencyMode_l() override;
+    void checkOutputStageEffects() final;
+    void setHalLatencyMode_l() final;
 
 private:
             // Do not request a specific mode by default
@@ -1862,83 +1810,39 @@
 };
 
 // record thread
-class RecordThread : public ThreadBase
+class RecordThread : public IAfRecordThread, public ThreadBase
 {
+    friend class ResamplerBufferProvider;
 public:
+    sp<IAfRecordThread> asIAfRecordThread() final {
+        return sp<IAfRecordThread>::fromExisting(this);
+    }
 
-    class RecordTrack;
-
-    /* The ResamplerBufferProvider is used to retrieve recorded input data from the
-     * RecordThread.  It maintains local state on the relative position of the read
-     * position of the RecordTrack compared with the RecordThread.
-     */
-    class ResamplerBufferProvider : public AudioBufferProvider
-    {
-    public:
-        explicit ResamplerBufferProvider(RecordTrack* recordTrack) :
-            mRecordTrack(recordTrack),
-            mRsmpInUnrel(0), mRsmpInFront(0) { }
-        virtual ~ResamplerBufferProvider() { }
-
-        // called to set the ResamplerBufferProvider to head of the RecordThread data buffer,
-        // skipping any previous data read from the hal.
-        virtual void reset();
-
-        /* Synchronizes RecordTrack position with the RecordThread.
-         * Calculates available frames and handle overruns if the RecordThread
-         * has advanced faster than the ResamplerBufferProvider has retrieved data.
-         * TODO: why not do this for every getNextBuffer?
-         *
-         * Parameters
-         * framesAvailable:  pointer to optional output size_t to store record track
-         *                   frames available.
-         *      hasOverrun:  pointer to optional boolean, returns true if track has overrun.
-         */
-
-        virtual void sync(size_t *framesAvailable = NULL, bool *hasOverrun = NULL);
-
-        // AudioBufferProvider interface
-        virtual status_t    getNextBuffer(AudioBufferProvider::Buffer* buffer);
-        virtual void        releaseBuffer(AudioBufferProvider::Buffer* buffer);
-
-                int32_t     getFront() const { return mRsmpInFront; }
-                void        setFront(int32_t front) { mRsmpInFront = front; }
-    private:
-        RecordTrack * const mRecordTrack;
-        size_t              mRsmpInUnrel;   // unreleased frames remaining from
-                                            // most recent getNextBuffer
-                                            // for debug only
-        int32_t             mRsmpInFront;   // next available frame
-                                            // rolling counter that is never cleared
-    };
-
-#include "RecordTracks.h"
-
-            RecordThread(const sp<AudioFlinger>& audioFlinger,
+            RecordThread(const sp<IAfThreadCallback>& afThreadCallback,
                     AudioStreamIn *input,
                     audio_io_handle_t id,
                     bool systemReady
                     );
-            virtual     ~RecordThread();
+    ~RecordThread() override;
 
     // no addTrack_l ?
-    void        destroyTrack_l(const sp<RecordTrack>& track);
-    void        removeTrack_l(const sp<RecordTrack>& track);
+    void destroyTrack_l(const sp<IAfRecordTrack>& track) final;
+    void removeTrack_l(const sp<IAfRecordTrack>& track) final;
 
     // Thread virtuals
-    virtual bool        threadLoop();
-    virtual void        preExit();
+    bool threadLoop() final;
+    void preExit() final;
 
     // RefBase
-    virtual void        onFirstRef();
+    void onFirstRef() final;
 
-    virtual status_t    initCheck() const { return (mInput == NULL) ? NO_INIT : NO_ERROR; }
+    status_t initCheck() const final { return mInput == nullptr ? NO_INIT : NO_ERROR; }
 
-    virtual sp<MemoryDealer>    readOnlyHeap() const { return mReadOnlyHeap; }
+    sp<MemoryDealer> readOnlyHeap() const final { return mReadOnlyHeap; }
 
-    virtual sp<IMemory> pipeMemory() const { return mPipeMemory; }
+    sp<IMemory> pipeMemory() const final { return mPipeMemory; }
 
-            sp<AudioFlinger::RecordThread::RecordTrack>  createRecordTrack_l(
+    sp<IAfRecordTrack> createRecordTrack_l(
                     const sp<Client>& client,
                     const audio_attributes_t& attr,
                     uint32_t *pSampleRate,
@@ -1953,17 +1857,19 @@
                     pid_t tid,
                     status_t *status /*non-NULL*/,
                     audio_port_handle_t portId,
-                    int32_t maxSharedAudioHistoryMs);
+                    int32_t maxSharedAudioHistoryMs) final;
 
-            status_t    start(RecordTrack* recordTrack,
+            status_t start(IAfRecordTrack* recordTrack,
                               AudioSystem::sync_event_t event,
-                              audio_session_t triggerSession);
+                              audio_session_t triggerSession) final;
 
             // ask the thread to stop the specified track, and
             // return true if the caller should then do it's part of the stopping process
-            bool        stop(RecordTrack* recordTrack);
+    bool stop(IAfRecordTrack* recordTrack) final;
+    AudioStreamIn* getInput() const final { return mInput; }
+    AudioStreamIn* clearInput() final;
 
-            AudioStreamIn* clearInput();
+            // TODO(b/291317898) Unify with IAfThreadBase
             virtual sp<StreamHalInterface> stream() const;
 
 
@@ -1971,19 +1877,19 @@
                                                status_t& status);
     virtual void        cacheParameters_l() {}
     virtual String8     getParameters(const String8& keys);
-    virtual void        ioConfigChanged(audio_io_config_event_t event, pid_t pid = 0,
-                                        audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE);
+    void ioConfigChanged(audio_io_config_event_t event, pid_t pid = 0,
+            audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE) final;
     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        resizeInputBuffer_l(int32_t maxSharedAudioHistoryMs) override;
 
-            void        addPatchTrack(const sp<PatchRecord>& record);
-            void        deletePatchTrack(const sp<PatchRecord>& record);
+    void addPatchTrack(const sp<IAfPatchRecord>& record) final;
+    void deletePatchTrack(const sp<IAfPatchRecord>& record) final;
 
             void        readInputParameters_l();
-    virtual uint32_t    getInputFramesLost();
+    uint32_t getInputFramesLost() const final;
 
     virtual status_t addEffectChain_l(const sp<IAfEffectChain>& chain);
     virtual size_t removeEffectChain_l(const sp<IAfEffectChain>& chain);
@@ -2002,7 +1908,7 @@
     static void syncStartEventCallback(const wp<audioflinger::SyncEvent>& event);
 
     virtual size_t      frameCount() const { return mFrameCount; }
-            bool        hasFastCapture() const { return mFastCapture != 0; }
+    bool hasFastCapture() const final { return mFastCapture != 0; }
     virtual void        toAudioPortConfig(struct audio_port_config *config);
 
     virtual status_t    checkEffectCompatibility_l(const effect_descriptor_t *desc,
@@ -2013,20 +1919,20 @@
                             mActiveTracks.updatePowerState(this, true /* force */);
                         }
 
-            void        checkBtNrec();
+    void checkBtNrec() final;
 
             // Sets the UID records silence
-            void        setRecordSilenced(audio_port_handle_t portId, bool silenced);
+    void setRecordSilenced(audio_port_handle_t portId, bool silenced) final;
 
-            status_t    getActiveMicrophones(
-                    std::vector<media::MicrophoneInfoFw>* activeMicrophones);
-
-            status_t    setPreferredMicrophoneDirection(audio_microphone_direction_t direction);
-            status_t    setPreferredMicrophoneFieldDimension(float zoom);
+    status_t getActiveMicrophones(
+            std::vector<media::MicrophoneInfoFw>* activeMicrophones) const final;
+    status_t setPreferredMicrophoneDirection(audio_microphone_direction_t direction) final;
+    status_t setPreferredMicrophoneFieldDimension(float zoom) final;
 
             MetadataUpdate        updateMetadata_l() override;
 
-            bool        fastTrackAvailable() const { return mFastTrackAvail; }
+    bool fastTrackAvailable() const final { return mFastTrackAvail; }
+    void setFastTrackAvailable(bool available) final { mFastTrackAvail = available; }
 
             bool        isTimestampCorrectionEnabled() const override {
                             // checks popcount for exactly one device.
@@ -2036,15 +1942,15 @@
                                     && inDeviceType() == mTimestampCorrectedDevice;
                         }
 
-            status_t    shareAudioHistory(const std::string& sharedAudioPackageName,
+    status_t shareAudioHistory(const std::string& sharedAudioPackageName,
                                           audio_session_t sharedSessionId = AUDIO_SESSION_NONE,
-                                          int64_t sharedAudioStartMs = -1);
+            int64_t sharedAudioStartMs = -1) final;
             status_t    shareAudioHistory_l(const std::string& sharedAudioPackageName,
                                           audio_session_t sharedSessionId = AUDIO_SESSION_NONE,
                                           int64_t sharedAudioStartMs = -1);
-            void        resetAudioHistory_l();
+    void resetAudioHistory_l() final;
 
-    virtual bool        isStreamInitialized() {
+    bool isStreamInitialized() const final {
                             return !(mInput == nullptr || mInput->stream == nullptr);
                         }
 
@@ -2066,10 +1972,10 @@
 
             AudioStreamIn                       *mInput;
             Source                              *mSource;
-            SortedVector < sp<RecordTrack> >    mTracks;
+            SortedVector <sp<IAfRecordTrack>>    mTracks;
             // mActiveTracks has dual roles:  it indicates the current active track(s), and
             // is used together with mStartStopCond to indicate start()/stop() progress
-            ActiveTracks<RecordTrack>           mActiveTracks;
+            ActiveTracks<IAfRecordTrack>           mActiveTracks;
 
             Condition                           mStartStopCond;
 
@@ -2136,90 +2042,85 @@
             audio_session_t                     mSharedAudioSessionId = AUDIO_SESSION_NONE;
 };
 
-class MmapThread : public ThreadBase
+class MmapThread : public ThreadBase, public virtual IAfMmapThread
 {
  public:
-
-#include "MmapTracks.h"
-
-    MmapThread(const sp<AudioFlinger>& audioFlinger, audio_io_handle_t id,
+    MmapThread(const sp<IAfThreadCallback>& afThreadCallback, audio_io_handle_t id,
                AudioHwDevice *hwDev, const sp<StreamHalInterface>& stream, bool systemReady,
                bool isOut);
-    virtual     ~MmapThread();
 
-    virtual     void        configure(const audio_attributes_t *attr,
+    void configure(const audio_attributes_t* attr,
                                       audio_stream_type_t streamType,
                                       audio_session_t sessionId,
                                       const sp<MmapStreamCallback>& callback,
                                       audio_port_handle_t deviceId,
-                                      audio_port_handle_t portId);
+                                      audio_port_handle_t portId) override;
 
-                void        disconnect();
+    void disconnect() final;
 
-    // MmapStreamInterface
-    status_t createMmapBuffer(int32_t minSizeFrames,
-                                      struct audio_mmap_buffer_info *info);
-    status_t getMmapPosition(struct audio_mmap_position *position);
+    // MmapStreamInterface for adapter.
+    status_t createMmapBuffer(int32_t minSizeFrames, struct audio_mmap_buffer_info* info) final;
+    status_t getMmapPosition(struct audio_mmap_position* position) const override;
     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();
-    virtual status_t getExternalPosition(uint64_t *position, int64_t *timeNaos) = 0;
-    virtual status_t reportData(const void* buffer, size_t frameCount);
+            audio_port_handle_t* handle) final;
+    status_t stop(audio_port_handle_t handle) final;
+    status_t standby() final;
+    status_t getExternalPosition(uint64_t* position, int64_t* timeNanos) const = 0;
+    status_t reportData(const void* buffer, size_t frameCount) override;
 
     // RefBase
-    virtual     void        onFirstRef();
+    void onFirstRef() final;
 
     // Thread virtuals
-    virtual     bool        threadLoop();
+    bool threadLoop() final;
 
-    virtual     void        threadLoop_exit();
-    virtual     void        threadLoop_standby();
-    virtual     bool        shouldStandby_l() { return false; }
-    virtual     status_t    exitStandby_l() REQUIRES(mLock);
+    // Not in ThreadBase
+    virtual void threadLoop_exit() final;
+    virtual void threadLoop_standby() final;
+    virtual bool shouldStandby_l() final { return false; }
+    virtual status_t exitStandby_l() REQUIRES(mLock);
 
-    virtual     status_t    initCheck() const { return (mHalStream == 0) ? NO_INIT : NO_ERROR; }
-    virtual     size_t      frameCount() const { return mFrameCount; }
-    virtual     bool        checkForNewParameter_l(const String8& keyValuePair,
-                                                    status_t& status);
-    virtual     String8     getParameters(const String8& keys);
-    virtual     void        ioConfigChanged(audio_io_config_event_t event, pid_t pid = 0,
-                                            audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE);
+    status_t initCheck() const final { return mHalStream == nullptr ? NO_INIT : NO_ERROR; }
+    size_t frameCount() const final { return mFrameCount; }
+    bool checkForNewParameter_l(const String8& keyValuePair, status_t& status) final;
+    String8 getParameters(const String8& keys) final;
+    void ioConfigChanged(audio_io_config_event_t event, pid_t pid = 0,
+            audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE) final;
                 void        readHalParameters_l();
-    virtual     void        cacheParameters_l() {}
-    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);
-    virtual     void        toAudioPortConfig(struct audio_port_config *config);
+    void cacheParameters_l() final {}
+    status_t createAudioPatch_l(
+            const struct audio_patch* patch, audio_patch_handle_t* handle) final;
+    status_t releaseAudioPatch_l(const audio_patch_handle_t handle) final;
+    void toAudioPortConfig(struct audio_port_config* config) override;
 
-    virtual     sp<StreamHalInterface> stream() const { return mHalStream; }
-    virtual     status_t    addEffectChain_l(const sp<IAfEffectChain>& chain);
-    virtual     size_t      removeEffectChain_l(const sp<IAfEffectChain>& chain);
-    virtual     status_t    checkEffectCompatibility_l(const effect_descriptor_t *desc,
-                                                               audio_session_t sessionId);
+    sp<StreamHalInterface> stream() const final { return mHalStream; }
+    status_t addEffectChain_l(const sp<IAfEffectChain>& chain) final;
+    size_t removeEffectChain_l(const sp<IAfEffectChain>& chain) final;
+    status_t checkEffectCompatibility_l(
+            const effect_descriptor_t *desc, audio_session_t sessionId) final;
 
-                uint32_t    hasAudioSession_l(audio_session_t sessionId) const override {
+    uint32_t hasAudioSession_l(audio_session_t sessionId) const override {
                                 // Note: using mActiveTracks as no mTracks here.
                                 return ThreadBase::hasAudioSession_l(sessionId, mActiveTracks);
                             }
-    virtual     status_t    setSyncEvent(const sp<audioflinger::SyncEvent>& event);
-    virtual     bool        isValidSyncEvent(const sp<audioflinger::SyncEvent>& event) const;
+    status_t setSyncEvent(const sp<audioflinger::SyncEvent>& event) final;
+    bool isValidSyncEvent(const sp<audioflinger::SyncEvent>& event) const final;
 
-    virtual     void        checkSilentMode_l() {}
-    virtual     void        processVolume_l() {}
+    virtual void checkSilentMode_l() {} // cannot be const (RecordThread)
+    virtual void processVolume_l() {}
                 void        checkInvalidTracks_l();
 
-    virtual     audio_stream_type_t streamType() { return AUDIO_STREAM_DEFAULT; }
-
-    virtual     void        invalidateTracks(audio_stream_type_t streamType __unused) {}
-    virtual     void        invalidateTracks(std::set<audio_port_handle_t>& portIds __unused) {}
+    // Not in ThreadBase
+    virtual audio_stream_type_t streamType() const { return AUDIO_STREAM_DEFAULT; }
+    virtual void invalidateTracks(audio_stream_type_t /* streamType */) {}
+    void invalidateTracks(std::set<audio_port_handle_t>& /* portIds */) override {}
 
                 // Sets the UID records silence
-    virtual     void        setRecordSilenced(audio_port_handle_t portId __unused,
-                                              bool silenced __unused) {}
+    void setRecordSilenced(
+            audio_port_handle_t /* portId */, bool /* silenced */) override {}
 
-    virtual     bool        isStreamInitialized() { return false; }
+    bool isStreamInitialized() const override { return false; }
 
                 void        setClientSilencedState_l(audio_port_handle_t portId, bool silenced) {
                                 mClientSilencedStates[portId] = silenced;
@@ -2242,8 +2143,8 @@
                             }
 
  protected:
-                void        dumpInternals_l(int fd, const Vector<String16>& args) override;
-                void        dumpTracks_l(int fd, const Vector<String16>& args) override;
+    void dumpInternals_l(int fd, const Vector<String16>& args) override;
+    void dumpTracks_l(int fd, const Vector<String16>& args) final;
 
                 /**
                  * @brief mDeviceId  current device port unique identifier
@@ -2258,7 +2159,7 @@
                 sp<StreamHalInterface>  mHalStream;
                 sp<DeviceHalInterface>  mHalDevice;
                 AudioHwDevice* const    mAudioHwDev;
-                ActiveTracks<MmapTrack> mActiveTracks;
+                ActiveTracks<IAfMmapTrack> mActiveTracks;
                 float                   mHalVolFloat;
                 std::map<audio_port_handle_t, bool> mClientSilencedStates;
 
@@ -2266,89 +2167,98 @@
      static     constexpr int32_t       kMaxNoCallbackWarnings = 5;
 };
 
-class MmapPlaybackThread : public MmapThread, public VolumeInterface
-{
-
+class MmapPlaybackThread : public MmapThread, public IAfMmapPlaybackThread,
+        public virtual VolumeInterface {
 public:
-    MmapPlaybackThread(const sp<AudioFlinger>& audioFlinger, audio_io_handle_t id,
+    MmapPlaybackThread(const sp<IAfThreadCallback>& afThreadCallback, audio_io_handle_t id,
                        AudioHwDevice *hwDev, AudioStreamOut *output, bool systemReady);
-    virtual     ~MmapPlaybackThread() {}
 
-    virtual     void        configure(const audio_attributes_t *attr,
+    sp<IAfMmapPlaybackThread> asIAfMmapPlaybackThread() final {
+        return sp<IAfMmapPlaybackThread>::fromExisting(this);
+    }
+
+    void configure(const audio_attributes_t* attr,
                                       audio_stream_type_t streamType,
                                       audio_session_t sessionId,
                                       const sp<MmapStreamCallback>& callback,
                                       audio_port_handle_t deviceId,
-                                      audio_port_handle_t portId);
+                                      audio_port_handle_t portId) final;
 
-                AudioStreamOut* clearOutput();
+    AudioStreamOut* clearOutput() final;
 
                 // VolumeInterface
-    virtual     void        setMasterVolume(float value);
-    virtual     void        setMasterMute(bool muted);
-    virtual     void        setStreamVolume(audio_stream_type_t stream, float value);
-    virtual     void        setStreamMute(audio_stream_type_t stream, bool muted);
-    virtual     float       streamVolume(audio_stream_type_t stream) const;
+    void setMasterVolume(float value) final;
+    void setMasterBalance(float /* value */) final {}  // Needs implementation?
+    void setMasterMute(bool muted) final;
+    void setStreamVolume(audio_stream_type_t stream, float value) final;
+    void setStreamMute(audio_stream_type_t stream, bool muted) final;
+    float streamVolume(audio_stream_type_t stream) const final;
 
                 void        setMasterMute_l(bool muted) { mMasterMute = muted; }
 
-    virtual     void        invalidateTracks(audio_stream_type_t streamType);
-                void        invalidateTracks(std::set<audio_port_handle_t>& portIds) override;
+    void invalidateTracks(audio_stream_type_t streamType) final;
+    void invalidateTracks(std::set<audio_port_handle_t>& portIds) final;
 
-    virtual     audio_stream_type_t streamType() { return mStreamType; }
-    virtual     void        checkSilentMode_l();
-                void        processVolume_l() override;
+    audio_stream_type_t streamType() const final { return mStreamType; }
+    void checkSilentMode_l() final;
+    void processVolume_l() final;
 
-                MetadataUpdate        updateMetadata_l() override;
+    MetadataUpdate updateMetadata_l() final;
 
-    virtual     void        toAudioPortConfig(struct audio_port_config *config);
+    void toAudioPortConfig(struct audio_port_config* config) final;
 
-                status_t    getExternalPosition(uint64_t *position, int64_t *timeNanos) override;
+    status_t getExternalPosition(uint64_t* position, int64_t* timeNanos) const final;
 
-    virtual     bool        isStreamInitialized() {
+    bool isStreamInitialized() const final {
                                 return !(mOutput == nullptr || mOutput->stream == nullptr);
                             }
 
-                status_t    reportData(const void* buffer, size_t frameCount) override;
+    status_t reportData(const void* buffer, size_t frameCount) final;
 
-                void startMelComputation_l(const sp<audio_utils::MelProcessor>& processor) override;
-                void stopMelComputation_l() override;
+    void startMelComputation_l(const sp<audio_utils::MelProcessor>& processor) final;
+    void stopMelComputation_l() final;
 
 protected:
-                void        dumpInternals_l(int fd, const Vector<String16>& args) override;
+    void dumpInternals_l(int fd, const Vector<String16>& args) final;
+                float       streamVolume_l() const {
+                    return mStreamTypes[mStreamType].volume;
+                }
+                bool     streamMuted_l() const {
+                    return mStreamTypes[mStreamType].mute;
+                }
 
+                stream_type_t               mStreamTypes[AUDIO_STREAM_CNT];
                 audio_stream_type_t         mStreamType;
                 float                       mMasterVolume;
-                float                       mStreamVolume;
                 bool                        mMasterMute;
-                bool                        mStreamMute;
                 AudioStreamOut*             mOutput;
 
                 mediautils::atomic_sp<audio_utils::MelProcessor> mMelProcessor;
 };
 
-class MmapCaptureThread : public MmapThread
+class MmapCaptureThread : public MmapThread, public IAfMmapCaptureThread
 {
-
 public:
-    MmapCaptureThread(const sp<AudioFlinger>& audioFlinger, audio_io_handle_t id,
+    MmapCaptureThread(const sp<IAfThreadCallback>& afThreadCallback, audio_io_handle_t id,
                       AudioHwDevice *hwDev, AudioStreamIn *input, bool systemReady);
-    virtual     ~MmapCaptureThread() {}
 
-                AudioStreamIn* clearInput();
+    sp<IAfMmapCaptureThread> asIAfMmapCaptureThread() final {
+        return sp<IAfMmapCaptureThread>::fromExisting(this);
+    }
 
-                status_t       exitStandby_l() REQUIRES(mLock) override;
+    AudioStreamIn* clearInput() final;
 
-                MetadataUpdate           updateMetadata_l() override;
-                void           processVolume_l() override;
-                void           setRecordSilenced(audio_port_handle_t portId,
-                                                 bool silenced) override;
+    status_t exitStandby_l() REQUIRES(mLock) final;
 
-    virtual     void           toAudioPortConfig(struct audio_port_config *config);
+    MetadataUpdate updateMetadata_l() final;
+    void processVolume_l() final;
+    void setRecordSilenced(audio_port_handle_t portId, bool silenced) final;
 
-                status_t       getExternalPosition(uint64_t *position, int64_t *timeNanos) override;
+    void toAudioPortConfig(struct audio_port_config* config) final;
 
-    virtual     bool           isStreamInitialized() {
+    status_t getExternalPosition(uint64_t* position, int64_t* timeNanos) const final;
+
+    bool isStreamInitialized() const final {
                                    return !(mInput == nullptr || mInput->stream == nullptr);
                                }
 
@@ -2359,12 +2269,12 @@
 
 class BitPerfectThread : public MixerThread {
 public:
-    BitPerfectThread(const sp<AudioFlinger>& audioflinger, AudioStreamOut *output,
+    BitPerfectThread(const sp<IAfThreadCallback>& afThreadCallback, AudioStreamOut *output,
                      audio_io_handle_t id, bool systemReady);
 
 protected:
-    mixer_state prepareTracks_l(Vector<sp<Track>> *tracksToRemove) override;
-    void threadLoop_mix() override;
+    mixer_state prepareTracks_l(Vector<sp<IAfTrack>>* tracksToRemove) final;
+    void threadLoop_mix() final;
 
 private:
     bool mIsBitPerfect;
@@ -2372,4 +2282,4 @@
     float mVolumeRight = 0.f;
 };
 
-private:
+} // namespace android
diff --git a/services/audioflinger/TrackBase.h b/services/audioflinger/TrackBase.h
index dec49ba..5708c61 100644
--- a/services/audioflinger/TrackBase.h
+++ b/services/audioflinger/TrackBase.h
@@ -15,46 +15,26 @@
 ** limitations under the License.
 */
 
-#ifndef INCLUDING_FROM_AUDIOFLINGER_H
-    #error This header file should only be included from AudioFlinger.h
-#endif
+#pragma once
+
+#include "Configuration.h"  // TEE_SINK
+#include "IAfTrack.h"
+
+#include <afutils/NBAIO_Tee.h>
+#include <android-base/macros.h>  // DISALLOW_COPY_AND_ASSIGN
+#include <datapath/TrackMetrics.h>
+#include <mediautils/BatteryNotifier.h>
+
+#include <atomic>    // avoid transitive dependency
+#include <list>      // avoid transitive dependency
+#include <optional>  // avoid transitive dependency
+
+namespace android {
 
 // base for record and playback
-class TrackBase : public ExtendedAudioBufferProvider, public RefBase {
-
+class TrackBase : public ExtendedAudioBufferProvider, public virtual IAfTrackBase {
 public:
-    enum track_state : int32_t {
-        IDLE,
-        FLUSHED,        // for PlaybackTracks only
-        STOPPED,
-        // next 2 states are currently used for fast tracks
-        // and offloaded tracks only
-        STOPPING_1,     // waiting for first underrun
-        STOPPING_2,     // waiting for presentation complete
-        RESUMING,       // for PlaybackTracks only
-        ACTIVE,
-        PAUSING,
-        PAUSED,
-        STARTING_1,     // for RecordTrack only
-        STARTING_2,     // for RecordTrack only
-    };
-
-    // where to allocate the data buffer
-    enum alloc_type {
-        ALLOC_CBLK,     // allocate immediately after control block
-        ALLOC_READONLY, // allocate from a separate read-only heap per thread
-        ALLOC_PIPE,     // do not allocate; use the pipe buffer
-        ALLOC_LOCAL,    // allocate a local buffer
-        ALLOC_NONE,     // do not allocate:use the buffer passed to TrackBase constructor
-    };
-
-    enum track_type {
-        TYPE_DEFAULT,
-        TYPE_OUTPUT,
-        TYPE_PATCH,
-    };
-
-                        TrackBase(ThreadBase *thread,
+    TrackBase(IAfThreadBase* thread,
                                 const sp<Client>& client,
                                 const audio_attributes_t& mAttr,
                                 uint32_t sampleRate,
@@ -71,87 +51,79 @@
                                 track_type type = TYPE_DEFAULT,
                                 audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE,
                                 std::string metricsId = {});
-    virtual             ~TrackBase();
-    virtual status_t    initCheck() const;
+    ~TrackBase() override;
+    status_t initCheck() const override;
+    sp<IMemory> getCblk() const final { return mCblkMemory; }
+    audio_track_cblk_t* cblk() const final { return mCblk; }
+    audio_session_t sessionId() const final { return mSessionId; }
+    uid_t uid() const final { return mUid; }
+    pid_t creatorPid() const final { return mCreatorPid; }
+    audio_port_handle_t portId() const final { return mPortId; }
+    status_t setSyncEvent(const sp<audioflinger::SyncEvent>& event) override;
+    track_state state() const final { return mState; }
+    void setState(track_state state) final { mState = state; }
+    sp<IMemory> getBuffers() const final { return mBufferMemory; }
+    void* buffer() const final { return mBuffer; }
+    size_t bufferSize() const final { return mBufferSize; }
 
-    virtual status_t    start(AudioSystem::sync_event_t event,
-                             audio_session_t triggerSession) = 0;
-    virtual void        stop() = 0;
-            sp<IMemory> getCblk() const { return mCblkMemory; }
-            audio_track_cblk_t* cblk() const { return mCblk; }
-            audio_session_t sessionId() const { return mSessionId; }
-            uid_t       uid() const { return mUid; }
-            pid_t       creatorPid() const { return mCreatorPid; }
-
-            audio_port_handle_t portId() const { return mPortId; }
-    virtual status_t    setSyncEvent(const sp<audioflinger::SyncEvent>& event);
-
-            sp<IMemory> getBuffers() const { return mBufferMemory; }
-            void*       buffer() const { return mBuffer; }
-            size_t      bufferSize() const { return mBufferSize; }
-    virtual bool        isFastTrack() const = 0;
-    virtual bool        isDirect() const = 0;
-            bool        isOutputTrack() const { return (mType == TYPE_OUTPUT); }
-            bool        isPatchTrack() const { return (mType == TYPE_PATCH); }
-            bool        isExternalTrack() const { return !isOutputTrack() && !isPatchTrack(); }
-
-    virtual void        invalidate() {
+    bool isOutputTrack() const final { return (mType == TYPE_OUTPUT); }
+    bool isPatchTrack() const final { return (mType == TYPE_PATCH); }
+    bool isExternalTrack() const final { return !isOutputTrack() && !isPatchTrack(); }
+    void invalidate() override {
                             if (mIsInvalid) return;
                             mTrackMetrics.logInvalidate();
                             mIsInvalid = true;
                         }
-            bool        isInvalid() const { return mIsInvalid; }
+    bool isInvalid() const final { return mIsInvalid; }
+    void terminate() final { mTerminated = true; }
+    bool isTerminated() const final { return mTerminated; }
+    audio_attributes_t attributes() const final { return mAttr; }
+    bool isSpatialized() const override { return false; }
+    bool isBitPerfect() const override { return false; }
 
-            void        terminate() { mTerminated = true; }
-            bool        isTerminated() const { return mTerminated; }
+    wp<IAfThreadBase> thread() const final { return mThread; }
 
-    audio_attributes_t  attributes() const { return mAttr; }
-
-    virtual bool        isSpatialized() const { return false; }
-
-    virtual bool        isBitPerfect() const { return false; }
+    const sp<ServerProxy>& serverProxy() const final { return mServerProxy; }
 
 #ifdef TEE_SINK
-           void         dumpTee(int fd, const std::string &reason) const {
-                                mTee.dump(fd, reason);
-                        }
+    void dumpTee(int fd, const std::string &reason) const final {
+        mTee.dump(fd, reason);
+    }
 #endif
-
-            /** returns the buffer contents size converted to time in milliseconds
-             * for PCM Playback or Record streaming tracks. The return value is zero for
-             * PCM static tracks and not defined for non-PCM tracks.
-             *
-             * This may be called without the thread lock.
-             */
-    virtual double      bufferLatencyMs() const {
+    /** returns the buffer contents size converted to time in milliseconds
+     * for PCM Playback or Record streaming tracks. The return value is zero for
+     * PCM static tracks and not defined for non-PCM tracks.
+     *
+     * This may be called without the thread lock.
+     */
+    double bufferLatencyMs() const override {
                             return mServerProxy->framesReadySafe() * 1000. / sampleRate();
                         }
 
-            /** returns whether the track supports server latency computation.
-             * This is set in the constructor and constant throughout the track lifetime.
-             */
+    /** returns whether the track supports server latency computation.
+     * This is set in the constructor and constant throughout the track lifetime.
+     */
+    bool isServerLatencySupported() const final { return mServerLatencySupported; }
 
-            bool        isServerLatencySupported() const { return mServerLatencySupported; }
-
-            /** computes the server latency for PCM Playback or Record track
-             * to the device sink/source.  This is the time for the next frame in the track buffer
-             * written or read from the server thread to the device source or sink.
-             *
-             * This may be called without the thread lock, but latencyMs and fromTrack
-             * may be not be synchronized. For example PatchPanel may not obtain the
-             * thread lock before calling.
-             *
-             * \param latencyMs on success is set to the latency in milliseconds of the
-             *        next frame written/read by the server thread to/from the track buffer
-             *        from the device source/sink.
-             * \param fromTrack on success is set to true if latency was computed directly
-             *        from the track timestamp; otherwise set to false if latency was
-             *        estimated from the server timestamp.
-             *        fromTrack may be nullptr or omitted if not required.
-             *
-             * \returns OK or INVALID_OPERATION on failure.
-             */
-            status_t    getServerLatencyMs(double *latencyMs, bool *fromTrack = nullptr) const {
+    /** computes the server latency for PCM Playback or Record track
+     * to the device sink/source.  This is the time for the next frame in the track buffer
+     * written or read from the server thread to the device source or sink.
+     *
+     * This may be called without the thread lock, but latencyMs and fromTrack
+     * may be not be synchronized. For example PatchPanel may not obtain the
+     * thread lock before calling.
+     *
+     * \param latencyMs on success is set to the latency in milliseconds of the
+     *        next frame written/read by the server thread to/from the track buffer
+     *        from the device source/sink.
+     * \param fromTrack on success is set to true if latency was computed directly
+     *        from the track timestamp; otherwise set to false if latency was
+     *        estimated from the server timestamp.
+     *        fromTrack may be nullptr or omitted if not required.
+     *
+     * \returns OK or INVALID_OPERATION on failure.
+     */
+    status_t getServerLatencyMs(double* latencyMs, bool* fromTrack = nullptr) const final {
                             if (!isServerLatencySupported()) {
                                 return INVALID_OPERATION;
                             }
@@ -170,25 +142,25 @@
                             return OK;
                         }
 
-            /** computes the total client latency for PCM Playback or Record tracks
-             * for the next client app access to the device sink/source; i.e. the
-             * server latency plus the buffer latency.
-             *
-             * This may be called without the thread lock, but latencyMs and fromTrack
-             * may be not be synchronized. For example PatchPanel may not obtain the
-             * thread lock before calling.
-             *
-             * \param latencyMs on success is set to the latency in milliseconds of the
-             *        next frame written/read by the client app to/from the track buffer
-             *        from the device sink/source.
-             * \param fromTrack on success is set to true if latency was computed directly
-             *        from the track timestamp; otherwise set to false if latency was
-             *        estimated from the server timestamp.
-             *        fromTrack may be nullptr or omitted if not required.
-             *
-             * \returns OK or INVALID_OPERATION on failure.
-             */
-            status_t    getTrackLatencyMs(double *latencyMs, bool *fromTrack = nullptr) const {
+    /** computes the total client latency for PCM Playback or Record tracks
+     * for the next client app access to the device sink/source; i.e. the
+     * server latency plus the buffer latency.
+     *
+     * This may be called without the thread lock, but latencyMs and fromTrack
+     * may be not be synchronized. For example PatchPanel may not obtain the
+     * thread lock before calling.
+     *
+     * \param latencyMs on success is set to the latency in milliseconds of the
+     *        next frame written/read by the client app to/from the track buffer
+     *        from the device sink/source.
+     * \param fromTrack on success is set to true if latency was computed directly
+     *        from the track timestamp; otherwise set to false if latency was
+     *        estimated from the server timestamp.
+     *        fromTrack may be nullptr or omitted if not required.
+     *
+     * \returns OK or INVALID_OPERATION on failure.
+     */
+    status_t getTrackLatencyMs(double* latencyMs, bool* fromTrack = nullptr) const {
                             double serverLatencyMs;
                             status_t status = getServerLatencyMs(&serverLatencyMs, fromTrack);
                             if (status == OK) {
@@ -197,21 +169,15 @@
                             return status;
                         }
 
-           // TODO: Consider making this external.
-           struct FrameTime {
-               int64_t frames;
-               int64_t timeNs;
-           };
-
-           // KernelFrameTime is updated per "mix" period even for non-pcm tracks.
-           void         getKernelFrameTime(FrameTime *ft) const {
+    // KernelFrameTime is updated per "mix" period even for non-pcm tracks.
+    void getKernelFrameTime(FrameTime* ft) const final {
                            *ft = mKernelFrameTime.load();
                         }
 
-           audio_format_t format() const { return mFormat; }
-           int id() const { return mId; }
+    audio_format_t format() const final { return mFormat; }
+    int id() const final { return mId; }
 
-    const char *getTrackStateAsString() const {
+    const char* getTrackStateAsString() const final {
         if (isTerminated()) {
             return "TERMINATED";
         }
@@ -245,19 +211,19 @@
 
     // 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) {
+    void logBeginInterval(const std::string& devices) final {
         mTrackMetrics.logBeginInterval(devices);
     }
 
     // Called by the PlaybackThread to indicate the track is no longer active.
-    void logEndInterval() {
+    void logEndInterval() final {
         mTrackMetrics.logEndInterval();
     }
 
     // Called to tally underrun frames in playback.
-    virtual void tallyUnderrunFrames(size_t /* frames */) {}
+    void tallyUnderrunFrames(size_t /* frames */) override {}
 
-    audio_channel_mask_t channelMask() const { return mChannelMask; }
+    audio_channel_mask_t channelMask() const final { return mChannelMask; }
 
     /** @return true if the track has changed (metadata or volume) since
      *          the last time this function was called,
@@ -265,16 +231,16 @@
      *          false otherwise.
      *  Thread safe.
      */
-    bool readAndClearHasChanged() { return !mChangeNotified.test_and_set(); }
+    bool readAndClearHasChanged() final { return !mChangeNotified.test_and_set(); }
 
     /** Set that a metadata has changed and needs to be notified to backend. Thread safe. */
-    void setMetadataHasChanged() { mChangeNotified.clear(); }
+    void setMetadataHasChanged() final { mChangeNotified.clear(); }
 
     /**
      * Called when a track moves to active state to record its contribution to battery usage.
      * Track state transitions should eventually be handled within the track class.
      */
-    void beginBatteryAttribution() {
+    void beginBatteryAttribution() final {
         mBatteryStatsHolder.emplace(uid());
     }
 
@@ -282,11 +248,10 @@
      * Called when a track moves out of the active state to record its contribution
      * to battery usage.
      */
-    void endBatteryAttribution() {
+    void endBatteryAttribution() final {
         mBatteryStatsHolder.reset();
     }
 
-
 protected:
     DISALLOW_COPY_AND_ASSIGN(TrackBase);
 
@@ -302,31 +267,31 @@
     }
 
     // AudioBufferProvider interface
-    virtual status_t getNextBuffer(AudioBufferProvider::Buffer* buffer) = 0;
-    virtual void releaseBuffer(AudioBufferProvider::Buffer* buffer);
+    // status_t getNextBuffer(AudioBufferProvider::Buffer* buffer) override;
+    void releaseBuffer(AudioBufferProvider::Buffer* buffer) override;
 
     // ExtendedAudioBufferProvider interface is only needed for Track,
     // but putting it in TrackBase avoids the complexity of virtual inheritance
-    virtual size_t  framesReady() const { return SIZE_MAX; }
+    size_t framesReady() const override { return SIZE_MAX; } // MmapTrack doesn't implement.
 
     uint32_t channelCount() const { return mChannelCount; }
 
-    size_t frameSize() const { return mFrameSize; }
+    size_t frameSize() const final { return mFrameSize; }
 
-    virtual uint32_t sampleRate() const { return mSampleRate; }
+    uint32_t sampleRate() const override { return mSampleRate; }
 
-    bool isStopped() const {
+    bool isStopped() const final {
         return (mState == STOPPED || mState == FLUSHED);
     }
 
     // for fast tracks and offloaded tracks only
-    bool isStopping() const {
+    bool isStopping() const final {
         return mState == STOPPING_1 || mState == STOPPING_2;
     }
-    bool isStopping_1() const {
+    bool isStopping_1() const final {
         return mState == STOPPING_1;
     }
-    bool isStopping_2() const {
+    bool isStopping_2() const final {
         return mState == STOPPING_2;
     }
 
@@ -368,7 +333,7 @@
                                     // true for Track, false for RecordTrack,
                                     // this could be a track type if needed later
 
-    const wp<ThreadBase> mThread;
+    const wp<IAfThreadBase> mThread;
     const alloc_type     mAllocType;
     /*const*/ sp<Client> mClient;   // see explanation at ~TrackBase() why not const
     sp<IMemory>         mCblkMemory;
@@ -434,37 +399,28 @@
     std::optional<mediautils::BatteryStatsAudioHandle> mBatteryStatsHolder;
 };
 
-// PatchProxyBufferProvider interface is implemented by PatchTrack and PatchRecord.
-// it provides buffer access methods that map those of a ClientProxy (see AudioTrackShared.h)
-class PatchProxyBufferProvider
+class PatchTrackBase : public PatchProxyBufferProvider, public virtual IAfPatchTrackBase
 {
 public:
-
-    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;
-};
-
-class PatchTrackBase : public PatchProxyBufferProvider
-{
-public:
-    using Timeout = std::optional<std::chrono::nanoseconds>;
-                        PatchTrackBase(const sp<ClientProxy>& proxy, const ThreadBase& thread,
+                        PatchTrackBase(const sp<ClientProxy>& proxy,
+                                       IAfThreadBase* thread,
                                        const Timeout& timeout);
-            void        setPeerTimeout(std::chrono::nanoseconds timeout);
-            template <typename T>
-            void        setPeerProxy(const sp<T> &proxy, bool holdReference) {
-                            mPeerReferenceHold = holdReference ? proxy : nullptr;
-                            mPeerProxy = proxy.get();
-                        }
-            void        clearPeerProxy() {
+            void setPeerTimeout(std::chrono::nanoseconds timeout) final;
+            void setPeerProxy(const sp<IAfPatchTrackBase>& proxy, bool holdReference) final {
+                if (proxy) {
+                    mPeerReferenceHold = holdReference ? proxy : nullptr;
+                    mPeerProxy = proxy->asPatchProxyBufferProvider();
+                } else {
+                    clearPeerProxy();
+                }
+            }
+            void clearPeerProxy() final {
                             mPeerReferenceHold.clear();
                             mPeerProxy = nullptr;
                         }
 
+            PatchProxyBufferProvider* asPatchProxyBufferProvider() final { return this; }
+
             bool        producesBufferOnDemand() const override { return false; }
 
 protected:
@@ -472,5 +428,6 @@
     sp<RefBase>                 mPeerReferenceHold;   // keeps mPeerProxy alive during access.
     PatchProxyBufferProvider*   mPeerProxy = nullptr;
     struct timespec             mPeerTimeout{};
-
 };
+
+} // namespace android
diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp
index 6350a57..1a00681 100644
--- a/services/audioflinger/Tracks.cpp
+++ b/services/audioflinger/Tracks.cpp
@@ -15,28 +15,33 @@
 ** limitations under the License.
 */
 
-
 #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 "MmapTracks.h"
+#include "PlaybackTracks.h"
+#include "RecordTracks.h"
+
+#include "Client.h"
+#include "IAfEffect.h"
+#include "IAfThread.h"
+#include "ResamplerBufferProvider.h"
+
+#include <audio_utils/minifloat.h>
+#include <media/AudioValidator.h>
+#include <media/RecordBufferConverter.h>
+#include <media/nbaio/Pipe.h>
+#include <media/nbaio/PipeReader.h>
+#include <mediautils/ServiceUtilities.h>
+#include <mediautils/SharedMemoryAllocator.h>
+#include <private/media/AudioTrackShared.h>
 #include <utils/Log.h>
 #include <utils/Trace.h>
 
-#include <private/media/AudioTrackShared.h>
-
-#include "AudioFlinger.h"
-
-#include <media/nbaio/Pipe.h>
-#include <media/nbaio/PipeReader.h>
-#include <media/AudioValidator.h>
-#include <media/RecordBufferConverter.h>
-#include <mediautils/ServiceUtilities.h>
-#include <audio_utils/minifloat.h>
+#include <linux/futex.h>
+#include <math.h>
+#include <sys/syscall.h>
 
 // ----------------------------------------------------------------------------
 
@@ -76,8 +81,8 @@
 static volatile int32_t nextTrackId = 55;
 
 // TrackBase constructor must be called with AudioFlinger::mLock held
-AudioFlinger::ThreadBase::TrackBase::TrackBase(
-            ThreadBase *thread,
+TrackBase::TrackBase(
+        IAfThreadBase *thread,
             const sp<Client>& client,
             const audio_attributes_t& attr,
             uint32_t sampleRate,
@@ -94,7 +99,7 @@
             track_type type,
             audio_port_handle_t portId,
             std::string metricsId)
-    :   RefBase(),
+    :
         mThread(thread),
         mAllocType(alloc),
         mClient(client),
@@ -253,7 +258,7 @@
    return attributionSource;
 }
 
-status_t AudioFlinger::ThreadBase::TrackBase::initCheck() const
+status_t TrackBase::initCheck() const
 {
     status_t status;
     if (mType == TYPE_OUTPUT || mType == TYPE_PATCH) {
@@ -264,7 +269,7 @@
     return status;
 }
 
-AudioFlinger::ThreadBase::TrackBase::~TrackBase()
+TrackBase::~TrackBase()
 {
     // delete the proxy before deleting the shared memory it refers to, to avoid dangling reference
     mServerProxy.clear();
@@ -272,7 +277,7 @@
     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
-        Mutex::Autolock _l(mClient->audioFlinger()->mClientLock);
+        Mutex::Autolock _l(mClient->afClientCallback()->clientMutex());
         // If the client's reference count drops to zero, the associated destructor
         // must run with AudioFlinger lock held. Thus the explicit clear() rather than
         // relying on the automatic clear() at end of scope.
@@ -289,7 +294,7 @@
 // AudioBufferProvider interface
 // getNextBuffer() = 0;
 // This implementation of releaseBuffer() is used by Track and RecordTrack
-void AudioFlinger::ThreadBase::TrackBase::releaseBuffer(AudioBufferProvider::Buffer* buffer)
+void TrackBase::releaseBuffer(AudioBufferProvider::Buffer* buffer)
 {
 #ifdef TEE_SINK
     mTee.write(buffer->raw, buffer->frameCount);
@@ -303,29 +308,28 @@
     mServerProxy->releaseBuffer(&buf);
 }
 
-status_t AudioFlinger::ThreadBase::TrackBase::setSyncEvent(
+status_t TrackBase::setSyncEvent(
         const sp<audioflinger::SyncEvent>& event)
 {
     mSyncEvents.emplace_back(event);
     return NO_ERROR;
 }
 
-AudioFlinger::ThreadBase::PatchTrackBase::PatchTrackBase(const sp<ClientProxy>& proxy,
-                                                         const ThreadBase& thread,
-                                                         const Timeout& timeout)
+PatchTrackBase::PatchTrackBase(const sp<ClientProxy>& proxy,
+        IAfThreadBase* thread, const Timeout& timeout)
     : mProxy(proxy)
 {
     if (timeout) {
         setPeerTimeout(*timeout);
     } else {
         // Double buffer mixer
-        uint64_t mixBufferNs = ((uint64_t)2 * thread.frameCount() * 1000000000) /
-                                              thread.sampleRate();
+        uint64_t mixBufferNs = ((uint64_t)2 * thread->frameCount() * 1000000000) /
+                                              thread->sampleRate();
         setPeerTimeout(std::chrono::nanoseconds{mixBufferNs});
     }
 }
 
-void AudioFlinger::ThreadBase::PatchTrackBase::setPeerTimeout(std::chrono::nanoseconds timeout) {
+void PatchTrackBase::setPeerTimeout(std::chrono::nanoseconds timeout) {
     mPeerTimeout.tv_sec = timeout.count() / std::nano::den;
     mPeerTimeout.tv_nsec = timeout.count() % std::nano::den;
 }
@@ -339,7 +343,7 @@
 
 class TrackHandle : public android::media::BnAudioTrack {
 public:
-    explicit TrackHandle(const sp<AudioFlinger::PlaybackThread::Track>& track);
+    explicit TrackHandle(const sp<IAfTrack>& track);
     ~TrackHandle() override;
 
     binder::Status getCblk(std::optional<media::SharedFileRegion>* _aidl_return) final;
@@ -373,20 +377,18 @@
             const media::audio::common::AudioPlaybackRate& playbackRate) final;
 
 private:
-    const sp<AudioFlinger::PlaybackThread::Track> mTrack;
+    const sp<IAfTrack> mTrack;
 };
 
 /* static */
-sp<media::IAudioTrack> AudioFlinger::PlaybackThread::Track::createIAudioTrackAdapter(
-        const sp<Track>& track) {
+sp<media::IAudioTrack> IAfTrack::createIAudioTrackAdapter(const sp<IAfTrack>& track) {
     return sp<TrackHandle>::make(track);
 }
 
-TrackHandle::TrackHandle(const sp<AudioFlinger::PlaybackThread::Track>& track)
+TrackHandle::TrackHandle(const sp<IAfTrack>& track)
     : BnAudioTrack(),
       mTrack(track)
 {
-    // TODO(b/288339104) binder thread priority change not needed.
     setMinSchedulerPolicy(SCHED_NORMAL, ANDROID_PRIORITY_AUDIO);
 }
 
@@ -556,9 +558,8 @@
 // -------------------------------
 
 // static
-sp<AudioFlinger::PlaybackThread::OpPlayAudioMonitor>
-AudioFlinger::PlaybackThread::OpPlayAudioMonitor::createIfNeeded(
-            AudioFlinger::ThreadBase* thread,
+sp<OpPlayAudioMonitor> OpPlayAudioMonitor::createIfNeeded(
+            IAfThreadBase* thread,
             const AttributionSourceState& attributionSource, const audio_attributes_t& attr, int id,
             audio_stream_type_t streamType)
 {
@@ -588,11 +589,10 @@
     return sp<OpPlayAudioMonitor>::make(thread, attributionSource, attr.usage, id, uid);
 }
 
-AudioFlinger::PlaybackThread::OpPlayAudioMonitor::OpPlayAudioMonitor(
-        AudioFlinger::ThreadBase* thread,
-        const AttributionSourceState& attributionSource,
-        audio_usage_t usage, int id, uid_t uid)
-    : mThread(wp<AudioFlinger::ThreadBase>::fromExisting(thread)),
+OpPlayAudioMonitor::OpPlayAudioMonitor(IAfThreadBase* thread,
+                                       const AttributionSourceState& attributionSource,
+                                       audio_usage_t usage, int id, uid_t uid)
+    : mThread(wp<IAfThreadBase>::fromExisting(thread)),
       mHasOpPlayAudio(true),
       mAttributionSource(attributionSource),
       mUsage((int32_t)usage),
@@ -601,7 +601,7 @@
       mPackageName(VALUE_OR_FATAL(aidl2legacy_string_view_String16(
                   attributionSource.packageName.value_or("")))) {}
 
-AudioFlinger::PlaybackThread::OpPlayAudioMonitor::~OpPlayAudioMonitor()
+OpPlayAudioMonitor::~OpPlayAudioMonitor()
 {
     if (mOpCallback != 0) {
         mAppOpsManager.stopWatchingMode(mOpCallback);
@@ -609,7 +609,7 @@
     mOpCallback.clear();
 }
 
-void AudioFlinger::PlaybackThread::OpPlayAudioMonitor::onFirstRef()
+void OpPlayAudioMonitor::onFirstRef()
 {
     checkPlayAudioForUsage();
     if (mAttributionSource.packageName.has_value()) {
@@ -619,14 +619,14 @@
     }
 }
 
-bool AudioFlinger::PlaybackThread::OpPlayAudioMonitor::hasOpPlayAudio() const {
+bool OpPlayAudioMonitor::hasOpPlayAudio() const {
     return mHasOpPlayAudio.load();
 }
 
 // Note this method is never called (and never to be) for audio server / patch record track
 // - not called from constructor due to check on UID,
 // - not called from PlayAudioOpCallback because the callback is not installed in this case
-void AudioFlinger::PlaybackThread::OpPlayAudioMonitor::checkPlayAudioForUsage()
+void OpPlayAudioMonitor::checkPlayAudioForUsage()
 {
     const bool hasAppOps = mAttributionSource.packageName.has_value()
         && mAppOpsManager.checkAudioOpNoThrow(
@@ -637,19 +637,19 @@
     if (mHasOpPlayAudio.compare_exchange_strong(shouldChange, hasAppOps)) {
         ALOGD("OpPlayAudio: track:%d usage:%d %smuted", mId, mUsage, hasAppOps ? "not " : "");
         auto thread = mThread.promote();
-        if (thread != nullptr && thread->type() == AudioFlinger::ThreadBase::OFFLOAD) {
+        if (thread != nullptr && thread->type() == IAfThreadBase::OFFLOAD) {
             // Wake up Thread if offloaded, otherwise it may be several seconds for update.
-            Mutex::Autolock _l(thread->mLock);
+            Mutex::Autolock _l(thread->mutex());
             thread->broadcast_l();
         }
     }
 }
 
-AudioFlinger::PlaybackThread::OpPlayAudioMonitor::PlayAudioOpCallback::PlayAudioOpCallback(
+OpPlayAudioMonitor::PlayAudioOpCallback::PlayAudioOpCallback(
         const wp<OpPlayAudioMonitor>& monitor) : mMonitor(monitor)
 { }
 
-void AudioFlinger::PlaybackThread::OpPlayAudioMonitor::PlayAudioOpCallback::opChanged(int32_t op,
+void OpPlayAudioMonitor::PlayAudioOpCallback::opChanged(int32_t op,
             const String16& packageName) {
     // we only have uid, so we need to check all package names anyway
     UNUSED(packageName);
@@ -663,7 +663,7 @@
 }
 
 // static
-void AudioFlinger::PlaybackThread::OpPlayAudioMonitor::getPackagesForUid(
+void OpPlayAudioMonitor::getPackagesForUid(
     uid_t uid, Vector<String16>& packages)
 {
     PermissionController permissionController;
@@ -674,9 +674,57 @@
 #undef LOG_TAG
 #define LOG_TAG "AF::Track"
 
+/* static */
+sp<IAfTrack> IAfTrack::create(
+        IAfPlaybackThread* thread,
+        const sp<Client>& client,
+        audio_stream_type_t streamType,
+        const audio_attributes_t& attr,
+        uint32_t sampleRate,
+        audio_format_t format,
+        audio_channel_mask_t channelMask,
+        size_t frameCount,
+        void *buffer,
+        size_t bufferSize,
+        const sp<IMemory>& sharedBuffer,
+        audio_session_t sessionId,
+        pid_t creatorPid,
+        const AttributionSourceState& attributionSource,
+        audio_output_flags_t flags,
+        track_type type,
+        audio_port_handle_t portId,
+        /** default behaviour is to start when there are as many frames
+          * ready as possible (aka. Buffer is full). */
+        size_t frameCountToBeReady,
+        float speed,
+        bool isSpatialized,
+        bool isBitPerfect) {
+    return sp<Track>::make(thread,
+            client,
+            streamType,
+            attr,
+            sampleRate,
+            format,
+            channelMask,
+            frameCount,
+            buffer,
+            bufferSize,
+            sharedBuffer,
+            sessionId,
+            creatorPid,
+            attributionSource,
+            flags,
+            type,
+            portId,
+            frameCountToBeReady,
+            speed,
+            isSpatialized,
+            isBitPerfect);
+}
+
 // Track constructor must be called with AudioFlinger::mLock and ThreadBase::mLock held
-AudioFlinger::PlaybackThread::Track::Track(
-            PlaybackThread *thread,
+Track::Track(
+        IAfPlaybackThread* thread,
             const sp<Client>& client,
             audio_stream_type_t streamType,
             const audio_attributes_t& attr,
@@ -710,7 +758,7 @@
                   type,
                   portId,
                   std::string(AMEDIAMETRICS_KEY_PREFIX_AUDIO_TRACK) + std::to_string(portId)),
-    mFillingUpStatus(FS_INVALID),
+    mFillingStatus(FS_INVALID),
     // mRetryCount initialized later when needed
     mSharedBuffer(sharedBuffer),
     mStreamType(streamType),
@@ -767,15 +815,15 @@
         // race with setSyncEvent(). However, if we call it, we cannot properly start
         // static fast tracks (SoundPool) immediately after stopping.
         //mAudioTrackServerProxy->framesReadyIsCalledByMultipleThreads();
-        ALOG_ASSERT(thread->mFastTrackAvailMask != 0);
-        int i = __builtin_ctz(thread->mFastTrackAvailMask);
+        ALOG_ASSERT(thread->fastTrackAvailMask_l() != 0);
+        const int i = __builtin_ctz(thread->fastTrackAvailMask_l());
         ALOG_ASSERT(0 < i && i < (int)FastMixerState::sMaxFastTracks);
         // FIXME This is too eager.  We allocate a fast track index before the
         //       fast track becomes active.  Since fast tracks are a scarce resource,
         //       this means we are potentially denying other more important fast tracks from
         //       being created.  It would be better to allocate the index dynamically.
         mFastIndex = i;
-        thread->mFastTrackAvailMask &= ~(1 << i);
+        thread->fastTrackAvailMask_l() &= ~(1 << i);
     }
 
     mServerLatencySupported = checkServerLatencySupported(format, flags);
@@ -800,7 +848,7 @@
     mTrackMetrics.logConstructor(creatorPid, uid, id(), traits, streamType);
 }
 
-AudioFlinger::PlaybackThread::Track::~Track()
+Track::~Track()
 {
     ALOGV("%s(%d)", __func__, mId);
 
@@ -813,7 +861,7 @@
     }
 }
 
-status_t AudioFlinger::PlaybackThread::Track::initCheck() const
+status_t Track::initCheck() const
 {
     status_t status = TrackBase::initCheck();
     if (status == NO_ERROR && mCblk == nullptr) {
@@ -822,7 +870,7 @@
     return status;
 }
 
-void AudioFlinger::PlaybackThread::Track::destroy()
+void Track::destroy()
 {
     // NOTE: destroyTrack_l() can remove a strong reference to this Track
     // by removing it from mTracks vector, so there is a risk that this Tracks's
@@ -835,10 +883,10 @@
     sp<Track> keep(this);
     { // scope for mLock
         bool wasActive = false;
-        sp<ThreadBase> thread = mThread.promote();
+        const sp<IAfThreadBase> thread = mThread.promote();
         if (thread != 0) {
-            Mutex::Autolock _l(thread->mLock);
-            PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
+            Mutex::Autolock _l(thread->mutex());
+            auto* const playbackThread = thread->asIAfPlaybackThread().get();
             wasActive = playbackThread->destroyTrack_l(this);
             forEachTeePatchTrack_l([](const auto& patchTrack) { patchTrack->destroy(); });
         }
@@ -848,7 +896,7 @@
     }
 }
 
-void AudioFlinger::PlaybackThread::Track::appendDumpHeader(String8& result)
+void Track::appendDumpHeader(String8& result) const
 {
     result.appendFormat("Type     Id Active Client Session Port Id S  Flags "
                         "  Format Chn mask  SRate "
@@ -859,7 +907,7 @@
                         isServerLatencySupported() ? "   Latency" : "");
 }
 
-void AudioFlinger::PlaybackThread::Track::appendDump(String8& result, bool active)
+void Track::appendDump(String8& result, bool active) const
 {
     char trackType;
     switch (mType) {
@@ -901,7 +949,7 @@
     }
 
     char fillingStatus;
-    switch (mFillingUpStatus) {
+    switch (mFillingStatus) {
     case FS_INVALID:
         fillingStatus = 'I';
         break;
@@ -987,12 +1035,12 @@
     result.append("\n");
 }
 
-uint32_t AudioFlinger::PlaybackThread::Track::sampleRate() const {
+uint32_t Track::sampleRate() const {
     return mAudioTrackServerProxy->getSampleRate();
 }
 
 // AudioBufferProvider interface
-status_t AudioFlinger::PlaybackThread::Track::getNextBuffer(AudioBufferProvider::Buffer* buffer)
+status_t Track::getNextBuffer(AudioBufferProvider::Buffer* buffer)
 {
     ServerProxy::Buffer buf;
     size_t desiredFrames = buffer->frameCount;
@@ -1010,14 +1058,14 @@
     return status;
 }
 
-void AudioFlinger::PlaybackThread::Track::releaseBuffer(AudioBufferProvider::Buffer* buffer)
+void Track::releaseBuffer(AudioBufferProvider::Buffer* buffer)
 {
     interceptBuffer(*buffer);
     TrackBase::releaseBuffer(buffer);
 }
 
 // TODO: compensate for time shift between HW modules.
-void AudioFlinger::PlaybackThread::Track::interceptBuffer(
+void Track::interceptBuffer(
         const AudioBufferProvider::Buffer& sourceBuffer) {
     auto start = std::chrono::steady_clock::now();
     const size_t frameCount = sourceBuffer.frameCount;
@@ -1027,12 +1075,12 @@
         // does not allow 0 frame size request contrary to getNextBuffer
     }
     for (auto& teePatch : mTeePatches) {
-        RecordThread::PatchRecord* patchRecord = teePatch.patchRecord.get();
+        IAfPatchRecord* patchRecord = teePatch.patchRecord.get();
         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,
+                 "buffer %zu/%zu, dropping %zu frames", __func__, mId, patchRecord->id(),
                  framesWritten, frameCount, framesLeft);
     }
     auto spent = ceil<std::chrono::microseconds>(std::chrono::steady_clock::now() - start);
@@ -1048,7 +1096,7 @@
 // from a different thread than the one calling Proxy->obtainBuffer() and
 // Proxy->releaseBuffer(). Also note there is no mutual exclusion in the
 // AudioTrackServerProxy so be especially careful calling with FastTracks.
-size_t AudioFlinger::PlaybackThread::Track::framesReady() const {
+size_t Track::framesReady() const {
     if (mSharedBuffer != 0 && (isStopped() || isStopping())) {
         // Static tracks return zero frames immediately upon stopping (for FastTracks).
         // The remainder of the buffer is not drained.
@@ -1057,12 +1105,12 @@
     return mAudioTrackServerProxy->framesReady();
 }
 
-int64_t AudioFlinger::PlaybackThread::Track::framesReleased() const
+int64_t Track::framesReleased() const
 {
     return mAudioTrackServerProxy->framesReleased();
 }
 
-void AudioFlinger::PlaybackThread::Track::onTimestamp(const ExtendedTimestamp &timestamp)
+void Track::onTimestamp(const ExtendedTimestamp &timestamp)
 {
     // This call comes from a FastTrack and should be kept lockless.
     // The server side frames are already translated to client frames.
@@ -1079,14 +1127,14 @@
 }
 
 // Don't call for fast tracks; the framesReady() could result in priority inversion
-bool AudioFlinger::PlaybackThread::Track::isReady() const {
-    if (mFillingUpStatus != FS_FILLING || isStopped() || isPausing()) {
+bool Track::isReady() const {
+    if (mFillingStatus != FS_FILLING || isStopped() || isPausing()) {
         return true;
     }
 
     if (isStopping()) {
         if (framesReady() > 0) {
-            mFillingUpStatus = FS_FILLED;
+            mFillingStatus = FS_FILLED;
         }
         return true;
     }
@@ -1100,33 +1148,33 @@
     if (framesReady() >= framesToBeReady || (mCblk->mFlags & CBLK_FORCEREADY)) {
         ALOGV("%s(%d): consider track ready with %zu/%zu, target was %zu)",
               __func__, mId, framesReady(), bufferSizeInFrames, framesToBeReady);
-        mFillingUpStatus = FS_FILLED;
+        mFillingStatus = FS_FILLED;
         android_atomic_and(~CBLK_FORCEREADY, &mCblk->mFlags);
         return true;
     }
     return false;
 }
 
-status_t AudioFlinger::PlaybackThread::Track::start(AudioSystem::sync_event_t event __unused,
+status_t Track::start(AudioSystem::sync_event_t event __unused,
                                                     audio_session_t triggerSession __unused)
 {
     status_t status = NO_ERROR;
     ALOGV("%s(%d): calling pid %d session %d",
             __func__, mId, IPCThreadState::self()->getCallingPid(), mSessionId);
 
-    sp<ThreadBase> thread = mThread.promote();
+    const sp<IAfThreadBase> thread = mThread.promote();
     if (thread != 0) {
         if (isOffloaded()) {
-            Mutex::Autolock _laf(thread->mAudioFlinger->mLock);
-            Mutex::Autolock _lth(thread->mLock);
+            Mutex::Autolock _laf(thread->afThreadCallback()->mutex());
+            Mutex::Autolock _lth(thread->mutex());
             sp<IAfEffectChain> ec = thread->getEffectChain_l(mSessionId);
-            if (thread->mAudioFlinger->isNonOffloadableGlobalEffectEnabled_l() ||
+            if (thread->afThreadCallback()->isNonOffloadableGlobalEffectEnabled_l() ||
                     (ec != 0 && ec->isNonOffloadableEnabled())) {
                 invalidate();
                 return PERMISSION_DENIED;
             }
         }
-        Mutex::Autolock _lth(thread->mLock);
+        Mutex::Autolock _lth(thread->mutex());
         track_state state = mState;
         // here the track could be either new, or restarted
         // in both cases "unstop" the track
@@ -1158,7 +1206,7 @@
                     __func__, mId, (int)mThreadIoHandle);
         }
 
-        PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
+        auto* const playbackThread = thread->asIAfPlaybackThread().get();
 
         // states to reset position info for pcm tracks
         if (audio_is_linear_pcm(mFormat)
@@ -1226,7 +1274,8 @@
     }
     if (status == NO_ERROR) {
         // send format to AudioManager for playback activity monitoring
-        sp<IAudioManager> audioManager = thread->mAudioFlinger->getOrCreateAudioManager();
+        const sp<IAudioManager> audioManager =
+                thread->afThreadCallback()->getOrCreateAudioManager();
         if (audioManager && mPortId != AUDIO_PORT_HANDLE_NONE) {
             std::unique_ptr<os::PersistableBundle> bundle =
                     std::make_unique<os::PersistableBundle>();
@@ -1245,17 +1294,17 @@
     return status;
 }
 
-void AudioFlinger::PlaybackThread::Track::stop()
+void Track::stop()
 {
     ALOGV("%s(%d): calling pid %d", __func__, mId, IPCThreadState::self()->getCallingPid());
-    sp<ThreadBase> thread = mThread.promote();
+    const sp<IAfThreadBase> thread = mThread.promote();
     if (thread != 0) {
-        Mutex::Autolock _l(thread->mLock);
+        Mutex::Autolock _l(thread->mutex());
         track_state state = mState;
         if (state == RESUMING || state == ACTIVE || state == PAUSING || state == PAUSED) {
             // If the track is not active (PAUSED and buffers full), flush buffers
-            PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
-            if (playbackThread->mActiveTracks.indexOf(this) < 0) {
+            auto* const playbackThread = thread->asIAfPlaybackThread().get();
+            if (!playbackThread->isTrackActive(this)) {
                 reset();
                 mState = STOPPED;
             } else if (!isFastTrack() && !isOffloaded() && !isDirect()) {
@@ -1267,7 +1316,7 @@
                 // move to STOPPING_2 when drain completes and then STOPPED
                 mState = STOPPING_1;
                 if (isOffloaded()) {
-                    mRetryCount = PlaybackThread::kMaxTrackStopRetriesOffload;
+                    mRetryCount = IAfPlaybackThread::kMaxTrackStopRetriesOffload;
                 }
             }
             playbackThread->broadcast_l();
@@ -1278,13 +1327,13 @@
     }
 }
 
-void AudioFlinger::PlaybackThread::Track::pause()
+void Track::pause()
 {
     ALOGV("%s(%d): calling pid %d", __func__, mId, IPCThreadState::self()->getCallingPid());
-    sp<ThreadBase> thread = mThread.promote();
+    const sp<IAfThreadBase> thread = mThread.promote();
     if (thread != 0) {
-        Mutex::Autolock _l(thread->mLock);
-        PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
+        Mutex::Autolock _l(thread->mutex());
+        auto* const playbackThread = thread->asIAfPlaybackThread().get();
         switch (mState) {
         case STOPPING_1:
         case STOPPING_2:
@@ -1315,18 +1364,18 @@
     }
 }
 
-void AudioFlinger::PlaybackThread::Track::flush()
+void Track::flush()
 {
     ALOGV("%s(%d)", __func__, mId);
-    sp<ThreadBase> thread = mThread.promote();
+    const sp<IAfThreadBase> thread = mThread.promote();
     if (thread != 0) {
-        Mutex::Autolock _l(thread->mLock);
-        PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
+        Mutex::Autolock _l(thread->mutex());
+        auto* const playbackThread = thread->asIAfPlaybackThread().get();
 
         // Flush the ring buffer now if the track is not active in the PlaybackThread.
         // Otherwise the flush would not be done until the track is resumed.
         // Requires FastTrack removal be BLOCK_UNTIL_ACKED
-        if (playbackThread->mActiveTracks.indexOf(this) < 0) {
+        if (!playbackThread->isTrackActive(this)) {
             (void)mServerProxy->flushBufferIfNeeded();
         }
 
@@ -1365,7 +1414,7 @@
             if (isDirect()) {
                 mFlushHwPending = true;
             }
-            if (playbackThread->mActiveTracks.indexOf(this) < 0) {
+            if (!playbackThread->isTrackActive(this)) {
                 reset();
             }
         }
@@ -1380,7 +1429,7 @@
 }
 
 // must be called with thread lock held
-void AudioFlinger::PlaybackThread::Track::flushAck()
+void Track::flushAck()
 {
     if (!isOffloaded() && !isDirect()) {
         return;
@@ -1393,12 +1442,12 @@
     mFlushHwPending = false;
 }
 
-void AudioFlinger::PlaybackThread::Track::pauseAck()
+void Track::pauseAck()
 {
     mPauseHwPending = false;
 }
 
-void AudioFlinger::PlaybackThread::Track::reset()
+void Track::reset()
 {
     // Do not reset twice to avoid discarding data written just after a flush and before
     // the audioflinger thread detects the track is stopped.
@@ -1406,7 +1455,7 @@
         // Force underrun condition to avoid false underrun callback until first data is
         // written to buffer
         android_atomic_and(~CBLK_FORCEREADY, &mCblk->mFlags);
-        mFillingUpStatus = FS_FILLING;
+        mFillingStatus = FS_FILLING;
         mResetDone = true;
         if (mState == FLUSHED) {
             mState = IDLE;
@@ -1414,34 +1463,35 @@
     }
 }
 
-status_t AudioFlinger::PlaybackThread::Track::setParameters(const String8& keyValuePairs)
+status_t Track::setParameters(const String8& keyValuePairs)
 {
-    sp<ThreadBase> thread = mThread.promote();
+    const sp<IAfThreadBase> thread = mThread.promote();
     if (thread == 0) {
         ALOGE("%s(%d): thread is dead", __func__, mId);
         return FAILED_TRANSACTION;
-    } else if ((thread->type() == ThreadBase::DIRECT) ||
-                    (thread->type() == ThreadBase::OFFLOAD)) {
+    } else if (thread->type() == IAfThreadBase::DIRECT
+            || thread->type() == IAfThreadBase::OFFLOAD) {
         return thread->setParameters(keyValuePairs);
     } else {
         return PERMISSION_DENIED;
     }
 }
 
-status_t AudioFlinger::PlaybackThread::Track::selectPresentation(int presentationId,
+status_t Track::selectPresentation(int presentationId,
         int programId) {
-    sp<ThreadBase> thread = mThread.promote();
+    const sp<IAfThreadBase> thread = mThread.promote();
     if (thread == 0) {
         ALOGE("thread is dead");
         return FAILED_TRANSACTION;
-    } else if ((thread->type() == ThreadBase::DIRECT) || (thread->type() == ThreadBase::OFFLOAD)) {
-        DirectOutputThread *directOutputThread = static_cast<DirectOutputThread*>(thread.get());
+    } else if (thread->type() == IAfThreadBase::DIRECT
+            || thread->type() == IAfThreadBase::OFFLOAD) {
+        auto directOutputThread = thread->asIAfDirectOutputThread().get();
         return directOutputThread->selectPresentation(presentationId, programId);
     }
     return INVALID_OPERATION;
 }
 
-VolumeShaper::Status AudioFlinger::PlaybackThread::Track::applyVolumeShaper(
+VolumeShaper::Status Track::applyVolumeShaper(
         const sp<VolumeShaper::Configuration>& configuration,
         const sp<VolumeShaper::Operation>& operation)
 {
@@ -1449,16 +1499,16 @@
 
     if (isOffloadedOrDirect()) {
         // Signal thread to fetch new volume.
-        sp<ThreadBase> thread = mThread.promote();
+        const sp<IAfThreadBase> thread = mThread.promote();
         if (thread != 0) {
-            Mutex::Autolock _l(thread->mLock);
+            Mutex::Autolock _l(thread->mutex());
             thread->broadcast_l();
         }
     }
     return status;
 }
 
-sp<VolumeShaper::State> AudioFlinger::PlaybackThread::Track::getVolumeShaperState(int id)
+sp<VolumeShaper::State> Track::getVolumeShaperState(int id) const
 {
     // Note: We don't check if Thread exists.
 
@@ -1466,7 +1516,7 @@
     return mVolumeHandler->getVolumeShaperState(id);
 }
 
-void AudioFlinger::PlaybackThread::Track::setFinalVolume(float volumeLeft, float volumeRight)
+void Track::setFinalVolume(float volumeLeft, float volumeRight)
 {
     mFinalVolumeLeft = volumeLeft;
     mFinalVolumeRight = volumeRight;
@@ -1482,7 +1532,7 @@
     }
 }
 
-void AudioFlinger::PlaybackThread::Track::copyMetadataTo(MetadataInserter& backInserter) const
+void Track::copyMetadataTo(MetadataInserter& backInserter) const
 {
     // Do not forward metadata for PatchTrack with unspecified stream type
     if (mStreamType == AUDIO_STREAM_PATCH) {
@@ -1554,7 +1604,7 @@
     *backInserter++ = metadata;
 }
 
-void AudioFlinger::PlaybackThread::Track::updateTeePatches_l() {
+void Track::updateTeePatches_l() {
     if (mTeePatchesToUpdate.has_value()) {
         forEachTeePatchTrack_l([](const auto& patchTrack) { patchTrack->destroy(); });
         mTeePatches = mTeePatchesToUpdate.value();
@@ -1566,14 +1616,14 @@
     }
 }
 
-void AudioFlinger::PlaybackThread::Track::setTeePatchesToUpdate_l(TeePatches teePatchesToUpdate) {
+void Track::setTeePatchesToUpdate_l(TeePatches teePatchesToUpdate) {
     ALOGW_IF(mTeePatchesToUpdate.has_value(),
              "%s, existing tee patches to update will be ignored", __func__);
     mTeePatchesToUpdate = std::move(teePatchesToUpdate);
 }
 
 // must be called with player thread lock held
-void AudioFlinger::PlaybackThread::Track::processMuteEvent_l(const sp<
+void Track::processMuteEvent_l(const sp<
     IAudioManager>& audioManager, mute_state_t muteState)
 {
     if (mMuteState == muteState) {
@@ -1605,31 +1655,32 @@
     }
 }
 
-status_t AudioFlinger::PlaybackThread::Track::getTimestamp(AudioTimestamp& timestamp)
+status_t Track::getTimestamp(AudioTimestamp& timestamp)
 {
     if (!isOffloaded() && !isDirect()) {
         return INVALID_OPERATION; // normal tracks handled through SSQ
     }
-    sp<ThreadBase> thread = mThread.promote();
+    const sp<IAfThreadBase> thread = mThread.promote();
     if (thread == 0) {
         return INVALID_OPERATION;
     }
 
-    Mutex::Autolock _l(thread->mLock);
-    PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
+    Mutex::Autolock _l(thread->mutex());
+    auto* const playbackThread = thread->asIAfPlaybackThread().get();
     return playbackThread->getTimestamp_l(timestamp);
 }
 
-status_t AudioFlinger::PlaybackThread::Track::attachAuxEffect(int EffectId)
+status_t Track::attachAuxEffect(int EffectId)
 {
-    sp<ThreadBase> thread = mThread.promote();
+    const sp<IAfThreadBase> thread = mThread.promote();
     if (thread == nullptr) {
         return DEAD_OBJECT;
     }
 
-    sp<PlaybackThread> dstThread = (PlaybackThread *)thread.get();
-    sp<PlaybackThread> srcThread; // srcThread is initialized by call to moveAuxEffectToIo()
-    sp<AudioFlinger> af = mClient->audioFlinger();
+    auto dstThread = thread->asIAfPlaybackThread();
+    // srcThread is initialized by call to moveAuxEffectToIo()
+    sp<IAfPlaybackThread> srcThread;
+    const auto& af = mClient->afClientCallback();
     status_t status = af->moveAuxEffectToIo(EffectId, dstThread, &srcThread);
 
     if (EffectId != 0 && status == NO_ERROR) {
@@ -1645,14 +1696,14 @@
     return status;
 }
 
-void AudioFlinger::PlaybackThread::Track::setAuxBuffer(int EffectId, int32_t *buffer)
+void Track::setAuxBuffer(int EffectId, int32_t *buffer)
 {
     mAuxEffectId = EffectId;
     mAuxBuffer = buffer;
 }
 
 // presentationComplete verified by frames, used by Mixed tracks.
-bool AudioFlinger::PlaybackThread::Track::presentationComplete(
+bool Track::presentationComplete(
         int64_t framesWritten, size_t audioHalFrames)
 {
     // TODO: improve this based on FrameMap if it exists, to ensure full drain.
@@ -1695,7 +1746,7 @@
 }
 
 // presentationComplete checked by time, used by DirectTracks.
-bool AudioFlinger::PlaybackThread::Track::presentationComplete(uint32_t latencyMs)
+bool Track::presentationComplete(uint32_t latencyMs)
 {
     // For Offloaded or Direct tracks.
 
@@ -1727,14 +1778,14 @@
     return false;
 }
 
-void AudioFlinger::PlaybackThread::Track::notifyPresentationComplete()
+void Track::notifyPresentationComplete()
 {
     // This only triggers once. TODO: should we enforce this?
     triggerEvents(AudioSystem::SYNC_EVENT_PRESENTATION_COMPLETE);
     mAudioTrackServerProxy->setStreamEndDone();
 }
 
-void AudioFlinger::PlaybackThread::Track::triggerEvents(AudioSystem::sync_event_t type)
+void Track::triggerEvents(AudioSystem::sync_event_t type)
 {
     for (auto it = mSyncEvents.begin(); it != mSyncEvents.end();) {
         if ((*it)->type() == type) {
@@ -1749,7 +1800,7 @@
 
 // implement VolumeBufferProvider interface
 
-gain_minifloat_packed_t AudioFlinger::PlaybackThread::Track::getVolumeLR()
+gain_minifloat_packed_t Track::getVolumeLR() const
 {
     // called by FastMixer, so not allowed to take any locks, block, or do I/O including logs
     ALOG_ASSERT(isFastTrack() && (mCblk != NULL));
@@ -1774,7 +1825,7 @@
     return vlr;
 }
 
-status_t AudioFlinger::PlaybackThread::Track::setSyncEvent(
+status_t Track::setSyncEvent(
         const sp<audioflinger::SyncEvent>& event)
 {
     if (isTerminated() || mState == PAUSED ||
@@ -1790,19 +1841,19 @@
     return NO_ERROR;
 }
 
-void AudioFlinger::PlaybackThread::Track::invalidate()
+void Track::invalidate()
 {
     TrackBase::invalidate();
     signalClientFlag(CBLK_INVALID);
 }
 
-void AudioFlinger::PlaybackThread::Track::disable()
+void Track::disable()
 {
     // TODO(b/142394888): the filling status should also be reset to filling
     signalClientFlag(CBLK_DISABLED);
 }
 
-void AudioFlinger::PlaybackThread::Track::signalClientFlag(int32_t flag)
+void Track::signalClientFlag(int32_t flag)
 {
     // FIXME should use proxy, and needs work
     audio_track_cblk_t* cblk = mCblk;
@@ -1812,25 +1863,25 @@
     (void) syscall(__NR_futex, &cblk->mFutex, FUTEX_WAKE, INT_MAX);
 }
 
-void AudioFlinger::PlaybackThread::Track::signal()
+void Track::signal()
 {
-    sp<ThreadBase> thread = mThread.promote();
+    const sp<IAfThreadBase> thread = mThread.promote();
     if (thread != 0) {
-        PlaybackThread *t = (PlaybackThread *)thread.get();
-        Mutex::Autolock _l(t->mLock);
+        auto* const t = thread->asIAfPlaybackThread().get();
+        Mutex::Autolock _l(t->mutex());
         t->broadcast_l();
     }
 }
 
-status_t AudioFlinger::PlaybackThread::Track::getDualMonoMode(audio_dual_mono_mode_t* mode)
+status_t Track::getDualMonoMode(audio_dual_mono_mode_t* mode) const
 {
     status_t status = INVALID_OPERATION;
     if (isOffloadedOrDirect()) {
-        sp<ThreadBase> thread = mThread.promote();
+        const sp<IAfThreadBase> thread = mThread.promote();
         if (thread != nullptr) {
-            PlaybackThread *t = (PlaybackThread *)thread.get();
-            Mutex::Autolock _l(t->mLock);
-            status = t->mOutput->stream->getDualMonoMode(mode);
+            auto* const t = thread->asIAfPlaybackThread().get();
+            Mutex::Autolock _l(t->mutex());
+            status = t->getOutput_l()->stream->getDualMonoMode(mode);
             ALOGD_IF((status == NO_ERROR) && (mDualMonoMode != *mode),
                     "%s: mode %d inconsistent", __func__, mDualMonoMode);
         }
@@ -1838,15 +1889,15 @@
     return status;
 }
 
-status_t AudioFlinger::PlaybackThread::Track::setDualMonoMode(audio_dual_mono_mode_t mode)
+status_t Track::setDualMonoMode(audio_dual_mono_mode_t mode)
 {
     status_t status = INVALID_OPERATION;
     if (isOffloadedOrDirect()) {
-        sp<ThreadBase> thread = mThread.promote();
+        const sp<IAfThreadBase> thread = mThread.promote();
         if (thread != nullptr) {
-            auto t = static_cast<PlaybackThread *>(thread.get());
-            Mutex::Autolock lock(t->mLock);
-            status = t->mOutput->stream->setDualMonoMode(mode);
+            auto* const t = thread->asIAfPlaybackThread().get();
+            Mutex::Autolock lock(t->mutex());
+            status = t->getOutput_l()->stream->setDualMonoMode(mode);
             if (status == NO_ERROR) {
                 mDualMonoMode = mode;
             }
@@ -1855,15 +1906,15 @@
     return status;
 }
 
-status_t AudioFlinger::PlaybackThread::Track::getAudioDescriptionMixLevel(float* leveldB)
+status_t Track::getAudioDescriptionMixLevel(float* leveldB) const
 {
     status_t status = INVALID_OPERATION;
     if (isOffloadedOrDirect()) {
-        sp<ThreadBase> thread = mThread.promote();
+        sp<IAfThreadBase> thread = mThread.promote();
         if (thread != nullptr) {
-            auto t = static_cast<PlaybackThread *>(thread.get());
-            Mutex::Autolock lock(t->mLock);
-            status = t->mOutput->stream->getAudioDescriptionMixLevel(leveldB);
+            auto* const t = thread->asIAfPlaybackThread().get();
+            Mutex::Autolock lock(t->mutex());
+            status = t->getOutput_l()->stream->getAudioDescriptionMixLevel(leveldB);
             ALOGD_IF((status == NO_ERROR) && (mAudioDescriptionMixLevel != *leveldB),
                     "%s: level %.3f inconsistent", __func__, mAudioDescriptionMixLevel);
         }
@@ -1871,15 +1922,15 @@
     return status;
 }
 
-status_t AudioFlinger::PlaybackThread::Track::setAudioDescriptionMixLevel(float leveldB)
+status_t Track::setAudioDescriptionMixLevel(float leveldB)
 {
     status_t status = INVALID_OPERATION;
     if (isOffloadedOrDirect()) {
-        sp<ThreadBase> thread = mThread.promote();
+        const sp<IAfThreadBase> thread = mThread.promote();
         if (thread != nullptr) {
-            auto t = static_cast<PlaybackThread *>(thread.get());
-            Mutex::Autolock lock(t->mLock);
-            status = t->mOutput->stream->setAudioDescriptionMixLevel(leveldB);
+            auto* const t = thread->asIAfPlaybackThread().get();
+            Mutex::Autolock lock(t->mutex());
+            status = t->getOutput_l()->stream->setAudioDescriptionMixLevel(leveldB);
             if (status == NO_ERROR) {
                 mAudioDescriptionMixLevel = leveldB;
             }
@@ -1888,16 +1939,16 @@
     return status;
 }
 
-status_t AudioFlinger::PlaybackThread::Track::getPlaybackRateParameters(
-        audio_playback_rate_t* playbackRate)
+status_t Track::getPlaybackRateParameters(
+        audio_playback_rate_t* playbackRate) const
 {
     status_t status = INVALID_OPERATION;
     if (isOffloadedOrDirect()) {
-        sp<ThreadBase> thread = mThread.promote();
+        const sp<IAfThreadBase> thread = mThread.promote();
         if (thread != nullptr) {
-            auto t = static_cast<PlaybackThread *>(thread.get());
-            Mutex::Autolock lock(t->mLock);
-            status = t->mOutput->stream->getPlaybackRateParameters(playbackRate);
+            auto* const t = thread->asIAfPlaybackThread().get();
+            Mutex::Autolock lock(t->mutex());
+            status = t->getOutput_l()->stream->getPlaybackRateParameters(playbackRate);
             ALOGD_IF((status == NO_ERROR) &&
                     !isAudioPlaybackRateEqual(mPlaybackRateParameters, *playbackRate),
                     "%s: playbackRate inconsistent", __func__);
@@ -1906,16 +1957,16 @@
     return status;
 }
 
-status_t AudioFlinger::PlaybackThread::Track::setPlaybackRateParameters(
+status_t Track::setPlaybackRateParameters(
         const audio_playback_rate_t& playbackRate)
 {
     status_t status = INVALID_OPERATION;
     if (isOffloadedOrDirect()) {
-        sp<ThreadBase> thread = mThread.promote();
+        const sp<IAfThreadBase> thread = mThread.promote();
         if (thread != nullptr) {
-            auto t = static_cast<PlaybackThread *>(thread.get());
-            Mutex::Autolock lock(t->mLock);
-            status = t->mOutput->stream->setPlaybackRateParameters(playbackRate);
+            auto* const t = thread->asIAfPlaybackThread().get();
+            Mutex::Autolock lock(t->mutex());
+            status = t->getOutput_l()->stream->setPlaybackRateParameters(playbackRate);
             if (status == NO_ERROR) {
                 mPlaybackRateParameters = playbackRate;
             }
@@ -1925,7 +1976,7 @@
 }
 
 //To be called with thread lock held
-bool AudioFlinger::PlaybackThread::Track::isResumePending() {
+bool Track::isResumePending() const {
     if (mState == RESUMING) {
         return true;
     }
@@ -1939,7 +1990,7 @@
 }
 
 //To be called with thread lock held
-void AudioFlinger::PlaybackThread::Track::resumeAck() {
+void Track::resumeAck() {
     if (mState == RESUMING) {
         mState = ACTIVE;
     }
@@ -1953,7 +2004,7 @@
 }
 
 //To be called with thread lock held
-void AudioFlinger::PlaybackThread::Track::updateTrackFrameInfo(
+void Track::updateTrackFrameInfo(
         int64_t trackFramesReleased, int64_t sinkFramesWritten,
         uint32_t halSampleRate, const ExtendedTimestamp &timeStamp) {
    // Make the kernel frametime available.
@@ -2033,14 +2084,14 @@
     }
 }
 
-bool AudioFlinger::PlaybackThread::Track::AudioVibrationController::setMute(bool muted) {
-    sp<ThreadBase> thread = mTrack->mThread.promote();
+bool Track::AudioVibrationController::setMute(bool muted) {
+    const sp<IAfThreadBase> thread = mTrack->mThread.promote();
     if (thread != 0) {
         // Lock for updating mHapticPlaybackEnabled.
-        Mutex::Autolock _l(thread->mLock);
-        PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
+        Mutex::Autolock _l(thread->mutex());
+        auto* const playbackThread = thread->asIAfPlaybackThread().get();
         if ((mTrack->channelMask() & AUDIO_CHANNEL_HAPTIC_ALL) != AUDIO_CHANNEL_NONE
-                && playbackThread->mHapticChannelCount > 0) {
+                && playbackThread->hapticChannelCount() > 0) {
             ALOGD("%s, haptic playback was %s for track %d",
                     __func__, muted ? "muted" : "unmuted", mTrack->id());
             mTrack->setHapticPlaybackEnabled(!muted);
@@ -2050,13 +2101,13 @@
     return false;
 }
 
-binder::Status AudioFlinger::PlaybackThread::Track::AudioVibrationController::mute(
+binder::Status Track::AudioVibrationController::mute(
         /*out*/ bool *ret) {
     *ret = setMute(true);
     return binder::Status::ok();
 }
 
-binder::Status AudioFlinger::PlaybackThread::Track::AudioVibrationController::unmute(
+binder::Status Track::AudioVibrationController::unmute(
         /*out*/ bool *ret) {
     *ret = setMute(false);
     return binder::Status::ok();
@@ -2066,9 +2117,28 @@
 #undef LOG_TAG
 #define LOG_TAG "AF::OutputTrack"
 
-AudioFlinger::PlaybackThread::OutputTrack::OutputTrack(
-            PlaybackThread *playbackThread,
-            DuplicatingThread *sourceThread,
+/* static */
+sp<IAfOutputTrack> IAfOutputTrack::create(
+        IAfPlaybackThread* playbackThread,
+        IAfDuplicatingThread* sourceThread,
+        uint32_t sampleRate,
+        audio_format_t format,
+        audio_channel_mask_t channelMask,
+        size_t frameCount,
+        const AttributionSourceState& attributionSource) {
+    return sp<OutputTrack>::make(
+            playbackThread,
+            sourceThread,
+            sampleRate,
+            format,
+            channelMask,
+            frameCount,
+            attributionSource);
+}
+
+OutputTrack::OutputTrack(
+            IAfPlaybackThread* playbackThread,
+            IAfDuplicatingThread* sourceThread,
             uint32_t sampleRate,
             audio_format_t format,
             audio_channel_mask_t channelMask,
@@ -2085,7 +2155,7 @@
 
     if (mCblk != NULL) {
         mOutBuffer.frameCount = 0;
-        playbackThread->mTracks.add(this);
+        playbackThread->addOutputTrack_l(this);
         ALOGV("%s(): mCblk %p, mBuffer %p, "
                 "frameCount %zu, mChannelMask 0x%08x",
                 __func__, mCblk, mBuffer,
@@ -2103,13 +2173,13 @@
     }
 }
 
-AudioFlinger::PlaybackThread::OutputTrack::~OutputTrack()
+OutputTrack::~OutputTrack()
 {
     clearBufferQueue();
     // superclass destructor will now delete the server proxy and shared memory both refer to
 }
 
-status_t AudioFlinger::PlaybackThread::OutputTrack::start(AudioSystem::sync_event_t event,
+status_t OutputTrack::start(AudioSystem::sync_event_t event,
                                                           audio_session_t triggerSession)
 {
     status_t status = Track::start(event, triggerSession);
@@ -2122,7 +2192,7 @@
     return status;
 }
 
-void AudioFlinger::PlaybackThread::OutputTrack::stop()
+void OutputTrack::stop()
 {
     Track::stop();
     clearBufferQueue();
@@ -2130,11 +2200,11 @@
     mActive = false;
 }
 
-ssize_t AudioFlinger::PlaybackThread::OutputTrack::write(void* data, uint32_t frames)
+ssize_t OutputTrack::write(void* data, uint32_t frames)
 {
     if (!mActive && frames != 0) {
-        sp<ThreadBase> thread = mThread.promote();
-        if (thread != nullptr && thread->standby()) {
+        const sp<IAfThreadBase> thread = mThread.promote();
+        if (thread != nullptr && thread->inStandby()) {
             // preload one silent buffer to trigger mixer on start()
             ClientProxy::Buffer buf { .mFrameCount = mClientProxy->getStartThresholdInFrames() };
             status_t status = mClientProxy->obtainBuffer(&buf);
@@ -2152,7 +2222,7 @@
             // If another OutputTrack has already started it can underrun but this is OK
             // as only silence has been played so far and the retry count is very high on
             // OutputTrack.
-            auto pt = static_cast<PlaybackThread *>(thread.get());
+            auto* const pt = thread->asIAfPlaybackThread().get();
             if (!pt->waitForHalStart()) {
                 ALOGW("%s(%d): timeout waiting for thread to exit standby", __func__, mId);
                 stop();
@@ -2241,8 +2311,8 @@
 
     // If we could not write all frames, allocate a buffer and queue it for next time.
     if (inBuffer.frameCount) {
-        sp<ThreadBase> thread = mThread.promote();
-        if (thread != 0 && !thread->standby()) {
+        const sp<IAfThreadBase> thread = mThread.promote();
+        if (thread != nullptr && !thread->inStandby()) {
             queueBuffer(inBuffer);
         }
     }
@@ -2256,7 +2326,7 @@
     return frames - inBuffer.frameCount;  // number of frames consumed.
 }
 
-void AudioFlinger::PlaybackThread::OutputTrack::queueBuffer(Buffer& inBuffer) {
+void OutputTrack::queueBuffer(Buffer& inBuffer) {
 
     if (mBufferQueue.size() < kMaxOverFlowBuffers) {
         Buffer *pInBuffer = new Buffer;
@@ -2279,13 +2349,13 @@
     }
 }
 
-void AudioFlinger::PlaybackThread::OutputTrack::copyMetadataTo(MetadataInserter& backInserter) const
+void OutputTrack::copyMetadataTo(MetadataInserter& backInserter) const
 {
     std::lock_guard<std::mutex> lock(mTrackMetadatasMutex);
     backInserter = std::copy(mTrackMetadatas.begin(), mTrackMetadatas.end(), backInserter);
 }
 
-void AudioFlinger::PlaybackThread::OutputTrack::setMetadatas(const SourceMetadatas& metadatas) {
+void OutputTrack::setMetadatas(const SourceMetadatas& metadatas) {
     {
         std::lock_guard<std::mutex> lock(mTrackMetadatasMutex);
         mTrackMetadatas = metadatas;
@@ -2294,7 +2364,7 @@
     setMetadataHasChanged();
 }
 
-status_t AudioFlinger::PlaybackThread::OutputTrack::obtainBuffer(
+status_t OutputTrack::obtainBuffer(
         AudioBufferProvider::Buffer* buffer, uint32_t waitTimeMs)
 {
     ClientProxy::Buffer buf;
@@ -2308,7 +2378,7 @@
     return status;
 }
 
-void AudioFlinger::PlaybackThread::OutputTrack::clearBufferQueue()
+void OutputTrack::clearBufferQueue()
 {
     size_t size = mBufferQueue.size();
 
@@ -2320,7 +2390,7 @@
     mBufferQueue.clear();
 }
 
-void AudioFlinger::PlaybackThread::OutputTrack::restartIfDisabled()
+void OutputTrack::restartIfDisabled()
 {
     int32_t flags = android_atomic_and(~CBLK_DISABLED, &mCblk->mFlags);
     if (mActive && (flags & CBLK_DISABLED)) {
@@ -2332,7 +2402,38 @@
 #undef LOG_TAG
 #define LOG_TAG "AF::PatchTrack"
 
-AudioFlinger::PlaybackThread::PatchTrack::PatchTrack(PlaybackThread *playbackThread,
+/* static */
+sp<IAfPatchTrack> IAfPatchTrack::create(
+        IAfPlaybackThread* playbackThread,
+        audio_stream_type_t streamType,
+        uint32_t sampleRate,
+        audio_channel_mask_t channelMask,
+        audio_format_t format,
+        size_t frameCount,
+        void* buffer,
+        size_t bufferSize,
+        audio_output_flags_t flags,
+        const Timeout& timeout,
+        size_t frameCountToBeReady /** Default behaviour is to start
+                                         *  as soon as possible to have
+                                         *  the lowest possible latency
+                                         *  even if it might glitch. */)
+{
+    return sp<PatchTrack>::make(
+            playbackThread,
+            streamType,
+            sampleRate,
+            channelMask,
+            format,
+            frameCount,
+            buffer,
+            bufferSize,
+            flags,
+            timeout,
+            frameCountToBeReady);
+}
+
+PatchTrack::PatchTrack(IAfPlaybackThread* playbackThread,
                                                      audio_stream_type_t streamType,
                                                      uint32_t sampleRate,
                                                      audio_channel_mask_t channelMask,
@@ -2351,7 +2452,7 @@
               TYPE_PATCH, AUDIO_PORT_HANDLE_NONE, frameCountToBeReady),
         PatchTrackBase(mCblk ? new ClientProxy(mCblk, mBuffer, frameCount, mFrameSize, true, true)
                         : nullptr,
-                       *playbackThread, timeout)
+                       playbackThread, timeout)
 {
     ALOGV("%s(%d): sampleRate %d mPeerTimeout %d.%03d sec",
                                       __func__, mId, sampleRate,
@@ -2359,12 +2460,12 @@
                                       (int)(mPeerTimeout.tv_nsec / 1000000));
 }
 
-AudioFlinger::PlaybackThread::PatchTrack::~PatchTrack()
+PatchTrack::~PatchTrack()
 {
     ALOGV("%s(%d)", __func__, mId);
 }
 
-size_t AudioFlinger::PlaybackThread::PatchTrack::framesReady() const
+size_t PatchTrack::framesReady() const
 {
     if (mPeerProxy && mPeerProxy->producesBufferOnDemand()) {
         return std::numeric_limits<size_t>::max();
@@ -2373,7 +2474,7 @@
     }
 }
 
-status_t AudioFlinger::PlaybackThread::PatchTrack::start(AudioSystem::sync_event_t event,
+status_t PatchTrack::start(AudioSystem::sync_event_t event,
                                                          audio_session_t triggerSession)
 {
     status_t status = Track::start(event, triggerSession);
@@ -2385,7 +2486,7 @@
 }
 
 // AudioBufferProvider interface
-status_t AudioFlinger::PlaybackThread::PatchTrack::getNextBuffer(
+status_t PatchTrack::getNextBuffer(
         AudioBufferProvider::Buffer* buffer)
 {
     ALOG_ASSERT(mPeerProxy != 0, "%s(%d): called without peer proxy", __func__, mId);
@@ -2411,7 +2512,7 @@
     return status;
 }
 
-void AudioFlinger::PlaybackThread::PatchTrack::releaseBuffer(AudioBufferProvider::Buffer* buffer)
+void PatchTrack::releaseBuffer(AudioBufferProvider::Buffer* buffer)
 {
     ALOG_ASSERT(mPeerProxy != 0, "%s(%d): called without peer proxy", __func__, mId);
     Proxy::Buffer buf;
@@ -2421,7 +2522,7 @@
     TrackBase::releaseBuffer(buffer); // Note: this is the base class.
 }
 
-status_t AudioFlinger::PlaybackThread::PatchTrack::obtainBuffer(Proxy::Buffer* buffer,
+status_t PatchTrack::obtainBuffer(Proxy::Buffer* buffer,
                                                                 const struct timespec *timeOut)
 {
     status_t status = NO_ERROR;
@@ -2438,7 +2539,7 @@
     return status;
 }
 
-void AudioFlinger::PlaybackThread::PatchTrack::releaseBuffer(Proxy::Buffer* buffer)
+void PatchTrack::releaseBuffer(Proxy::Buffer* buffer)
 {
     mProxy->releaseBuffer(buffer);
     restartIfDisabled();
@@ -2447,23 +2548,23 @@
     // If not, prevent an underrun from occurring by moving the track into FS_FILLING;
     // this logic avoids glitches when suspending A2DP with AudioPlaybackCapture.
     // TODO: perhaps underrun avoidance could be a track property checked in isReady() instead.
-    if (mFillingUpStatus == FS_ACTIVE
+    if (mFillingStatus == FS_ACTIVE
             && audio_is_linear_pcm(mFormat)
             && !isOffloadedOrDirect()) {
-        if (sp<ThreadBase> thread = mThread.promote();
+        if (const sp<IAfThreadBase> thread = mThread.promote();
             thread != 0) {
-            PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
+            auto* const playbackThread = thread->asIAfPlaybackThread().get();
             const size_t frameCount = playbackThread->frameCount() * sampleRate()
                     / playbackThread->sampleRate();
             if (framesReady() < frameCount) {
                 ALOGD("%s(%d) Not enough data, wait for buffer to fill", __func__, mId);
-                mFillingUpStatus = FS_FILLING;
+                mFillingStatus = FS_FILLING;
             }
         }
     }
 }
 
-void AudioFlinger::PlaybackThread::PatchTrack::restartIfDisabled()
+void PatchTrack::restartIfDisabled()
 {
     if (android_atomic_and(~CBLK_DISABLED, &mCblk->mFlags) & CBLK_DISABLED) {
         ALOGW("%s(%d): disabled due to previous underrun, restarting", __func__, mId);
@@ -2481,7 +2582,7 @@
 
 class RecordHandle : public android::media::BnAudioRecord {
 public:
-    explicit RecordHandle(const sp<AudioFlinger::RecordThread::RecordTrack>& recordTrack);
+    explicit RecordHandle(const sp<IAfRecordTrack>& recordTrack);
     ~RecordHandle() override;
     binder::Status start(int /*AudioSystem::sync_event_t*/ event,
             int /*audio_session_t*/ triggerSession) final;
@@ -2495,24 +2596,23 @@
             const std::string& sharedAudioPackageName, int64_t sharedAudioStartMs) final;
 
 private:
-    const sp<AudioFlinger::RecordThread::RecordTrack> mRecordTrack;
+    const sp<IAfRecordTrack> mRecordTrack;
 
     // for use from destructor
     void stop_nonvirtual();
 };
 
 /* static */
-sp<media::IAudioRecord> AudioFlinger::RecordThread::RecordTrack::createIAudioRecordAdapter(
-        const sp<RecordTrack>& recordTrack) {
+sp<media::IAudioRecord> IAfRecordTrack::createIAudioRecordAdapter(
+        const sp<IAfRecordTrack>& recordTrack) {
     return sp<RecordHandle>::make(recordTrack);
 }
 
 RecordHandle::RecordHandle(
-        const sp<AudioFlinger::RecordThread::RecordTrack>& recordTrack)
+        const sp<IAfRecordTrack>& recordTrack)
     : BnAudioRecord(),
     mRecordTrack(recordTrack)
 {
-    // TODO(b/288339104) binder thread priority change not needed.
     setMinSchedulerPolicy(SCHED_NORMAL, ANDROID_PRIORITY_AUDIO);
 }
 
@@ -2566,9 +2666,47 @@
 #undef LOG_TAG
 #define LOG_TAG "AF::RecordTrack"
 
+
+/* static */
+sp<IAfRecordTrack> IAfRecordTrack::create(IAfRecordThread* thread,
+        const sp<Client>& client,
+        const audio_attributes_t& attr,
+        uint32_t sampleRate,
+        audio_format_t format,
+        audio_channel_mask_t channelMask,
+        size_t frameCount,
+        void* buffer,
+        size_t bufferSize,
+        audio_session_t sessionId,
+        pid_t creatorPid,
+        const AttributionSourceState& attributionSource,
+        audio_input_flags_t flags,
+        track_type type,
+        audio_port_handle_t portId,
+        int32_t startFrames)
+{
+    return sp<RecordTrack>::make(
+        thread,
+        client,
+        attr,
+        sampleRate,
+        format,
+        channelMask,
+        frameCount,
+        buffer,
+        bufferSize,
+        sessionId,
+        creatorPid,
+        attributionSource,
+        flags,
+        type,
+        portId,
+        startFrames);
+}
+
 // RecordTrack constructor must be called with AudioFlinger::mLock and ThreadBase::mLock held
-AudioFlinger::RecordThread::RecordTrack::RecordTrack(
-            RecordThread *thread,
+RecordTrack::RecordTrack(
+            IAfRecordThread* thread,
             const sp<Client>& client,
             const audio_attributes_t& attr,
             uint32_t sampleRate,
@@ -2607,7 +2745,7 @@
 
     if (!isDirect()) {
         mRecordBufferConverter = new RecordBufferConverter(
-                thread->mChannelMask, thread->mFormat, thread->mSampleRate,
+                thread->channelMask(), thread->format(), thread->sampleRate(),
                 channelMask, format, sampleRate);
         // Check if the RecordBufferConverter construction was successful.
         // If not, don't continue with construction.
@@ -2627,8 +2765,8 @@
     mResamplerBufferProvider = new ResamplerBufferProvider(this);
 
     if (flags & AUDIO_INPUT_FLAG_FAST) {
-        ALOG_ASSERT(thread->mFastTrackAvail);
-        thread->mFastTrackAvail = false;
+        ALOG_ASSERT(thread->fastTrackAvailable());
+        thread->setFastTrackAvailable(false);
     } else {
         // TODO: only Normal Record has timestamps (Fast Record does not).
         mServerLatencySupported = checkServerLatencySupported(mFormat, flags);
@@ -2643,14 +2781,14 @@
     mTrackMetrics.logConstructor(creatorPid, uid(), id());
 }
 
-AudioFlinger::RecordThread::RecordTrack::~RecordTrack()
+RecordTrack::~RecordTrack()
 {
     ALOGV("%s()", __func__);
     delete mRecordBufferConverter;
     delete mResamplerBufferProvider;
 }
 
-status_t AudioFlinger::RecordThread::RecordTrack::initCheck() const
+status_t RecordTrack::initCheck() const
 {
     status_t status = TrackBase::initCheck();
     if (status == NO_ERROR && mServerProxy == 0) {
@@ -2660,7 +2798,7 @@
 }
 
 // AudioBufferProvider interface
-status_t AudioFlinger::RecordThread::RecordTrack::getNextBuffer(AudioBufferProvider::Buffer* buffer)
+status_t RecordTrack::getNextBuffer(AudioBufferProvider::Buffer* buffer)
 {
     ServerProxy::Buffer buf;
     buf.mFrameCount = buffer->frameCount;
@@ -2674,12 +2812,12 @@
     return status;
 }
 
-status_t AudioFlinger::RecordThread::RecordTrack::start(AudioSystem::sync_event_t event,
+status_t RecordTrack::start(AudioSystem::sync_event_t event,
                                                         audio_session_t triggerSession)
 {
-    sp<ThreadBase> thread = mThread.promote();
+    const sp<IAfThreadBase> thread = mThread.promote();
     if (thread != 0) {
-        RecordThread *recordThread = (RecordThread *)thread.get();
+        auto* const recordThread = thread->asIAfRecordThread().get();
         return recordThread->start(this, event, triggerSession);
     } else {
         ALOGW("%s track %d: thread was destroyed", __func__, portId());
@@ -2687,27 +2825,27 @@
     }
 }
 
-void AudioFlinger::RecordThread::RecordTrack::stop()
+void RecordTrack::stop()
 {
-    sp<ThreadBase> thread = mThread.promote();
+    const sp<IAfThreadBase> thread = mThread.promote();
     if (thread != 0) {
-        RecordThread *recordThread = (RecordThread *)thread.get();
+        auto* const recordThread = thread->asIAfRecordThread().get();
         if (recordThread->stop(this) && isExternalTrack()) {
             AudioSystem::stopInput(mPortId);
         }
     }
 }
 
-void AudioFlinger::RecordThread::RecordTrack::destroy()
+void RecordTrack::destroy()
 {
-    // see comments at AudioFlinger::PlaybackThread::Track::destroy()
+    // see comments at Track::destroy()
     sp<RecordTrack> keep(this);
     {
         track_state priorState = mState;
-        sp<ThreadBase> thread = mThread.promote();
+        const sp<IAfThreadBase> thread = mThread.promote();
         if (thread != 0) {
-            Mutex::Autolock _l(thread->mLock);
-            RecordThread *recordThread = (RecordThread *) thread.get();
+            Mutex::Autolock _l(thread->mutex());
+            auto* const recordThread = thread->asIAfRecordThread().get();
             priorState = mState;
             if (!mSharedAudioPackageName.empty()) {
                 recordThread->resetAudioHistory_l();
@@ -2738,7 +2876,7 @@
     }
 }
 
-void AudioFlinger::RecordThread::RecordTrack::invalidate()
+void RecordTrack::invalidate()
 {
     TrackBase::invalidate();
     // FIXME should use proxy, and needs work
@@ -2750,7 +2888,7 @@
 }
 
 
-void AudioFlinger::RecordThread::RecordTrack::appendDumpHeader(String8& result)
+void RecordTrack::appendDumpHeader(String8& result) const
 {
     result.appendFormat("Active     Id Client Session Port Id  S  Flags  "
                         " Format Chn mask  SRate Source  "
@@ -2758,7 +2896,7 @@
                         isServerLatencySupported() ? "   Latency" : "");
 }
 
-void AudioFlinger::RecordThread::RecordTrack::appendDump(String8& result, bool active)
+void RecordTrack::appendDump(String8& result, bool active) const
 {
     result.appendFormat("%c%5s %6d %6u %7u %7u  %2s 0x%03X "
             "%08X %08X %6u %6X "
@@ -2797,26 +2935,26 @@
 }
 
 // This is invoked by SyncEvent callback.
-void AudioFlinger::RecordThread::RecordTrack::handleSyncStartEvent(
+void RecordTrack::handleSyncStartEvent(
         const sp<audioflinger::SyncEvent>& event)
 {
     size_t framesToDrop = 0;
-    sp<ThreadBase> threadBase = mThread.promote();
+    const sp<IAfThreadBase> threadBase = mThread.promote();
     if (threadBase != 0) {
         // TODO: use actual buffer filling status instead of 2 buffers when info is available
         // from audio HAL
-        framesToDrop = threadBase->mFrameCount * 2;
+        framesToDrop = threadBase->frameCount() * 2;
     }
 
     mSynchronizedRecordState.onPlaybackFinished(event, framesToDrop);
 }
 
-void AudioFlinger::RecordThread::RecordTrack::clearSyncStartEvent()
+void RecordTrack::clearSyncStartEvent()
 {
     mSynchronizedRecordState.clear();
 }
 
-void AudioFlinger::RecordThread::RecordTrack::updateTrackFrameInfo(
+void RecordTrack::updateTrackFrameInfo(
         int64_t trackFramesReleased, int64_t sourceFramesRead,
         uint32_t halSampleRate, const ExtendedTimestamp &timestamp)
 {
@@ -2856,40 +2994,40 @@
     mServerLatencyMs.store(latencyMs);
 }
 
-status_t AudioFlinger::RecordThread::RecordTrack::getActiveMicrophones(
-        std::vector<media::MicrophoneInfoFw>* activeMicrophones)
+status_t RecordTrack::getActiveMicrophones(
+        std::vector<media::MicrophoneInfoFw>* activeMicrophones) const
 {
-    sp<ThreadBase> thread = mThread.promote();
+    const sp<IAfThreadBase> thread = mThread.promote();
     if (thread != 0) {
-        RecordThread *recordThread = (RecordThread *)thread.get();
+        auto* const recordThread = thread->asIAfRecordThread().get();
         return recordThread->getActiveMicrophones(activeMicrophones);
     } else {
         return BAD_VALUE;
     }
 }
 
-status_t AudioFlinger::RecordThread::RecordTrack::setPreferredMicrophoneDirection(
+status_t RecordTrack::setPreferredMicrophoneDirection(
         audio_microphone_direction_t direction) {
-    sp<ThreadBase> thread = mThread.promote();
+    const sp<IAfThreadBase> thread = mThread.promote();
     if (thread != 0) {
-        RecordThread *recordThread = (RecordThread *)thread.get();
+        auto* const recordThread = thread->asIAfRecordThread().get();
         return recordThread->setPreferredMicrophoneDirection(direction);
     } else {
         return BAD_VALUE;
     }
 }
 
-status_t AudioFlinger::RecordThread::RecordTrack::setPreferredMicrophoneFieldDimension(float zoom) {
-    sp<ThreadBase> thread = mThread.promote();
+status_t RecordTrack::setPreferredMicrophoneFieldDimension(float zoom) {
+    const sp<IAfThreadBase> thread = mThread.promote();
     if (thread != 0) {
-        RecordThread *recordThread = (RecordThread *)thread.get();
+        auto* const recordThread = thread->asIAfRecordThread().get();
         return recordThread->setPreferredMicrophoneFieldDimension(zoom);
     } else {
         return BAD_VALUE;
     }
 }
 
-status_t AudioFlinger::RecordThread::RecordTrack::shareAudioHistory(
+status_t RecordTrack::shareAudioHistory(
         const std::string& sharedAudioPackageName, int64_t sharedAudioStartMs) {
 
     const uid_t callingUid = IPCThreadState::self()->getCallingUid();
@@ -2906,9 +3044,9 @@
         return PERMISSION_DENIED;
     }
 
-    sp<ThreadBase> thread = mThread.promote();
+    const sp<IAfThreadBase> thread = mThread.promote();
     if (thread != 0) {
-        RecordThread *recordThread = (RecordThread *)thread.get();
+        auto* const recordThread = thread->asIAfRecordThread().get();
         status_t status = recordThread->shareAudioHistory(
                 sharedAudioPackageName, mSessionId, sharedAudioStartMs);
         if (status == NO_ERROR) {
@@ -2920,7 +3058,7 @@
     }
 }
 
-void AudioFlinger::RecordThread::RecordTrack::copyMetadataTo(MetadataInserter& backInserter) const
+void RecordTrack::copyMetadataTo(MetadataInserter& backInserter) const
 {
 
     // Do not forward PatchRecord metadata with unspecified audio source
@@ -2944,7 +3082,33 @@
 #undef LOG_TAG
 #define LOG_TAG "AF::PatchRecord"
 
-AudioFlinger::RecordThread::PatchRecord::PatchRecord(RecordThread *recordThread,
+/* static */
+sp<IAfPatchRecord> IAfPatchRecord::create(
+        IAfRecordThread* recordThread,
+        uint32_t sampleRate,
+        audio_channel_mask_t channelMask,
+        audio_format_t format,
+        size_t frameCount,
+        void *buffer,
+        size_t bufferSize,
+        audio_input_flags_t flags,
+        const Timeout& timeout,
+        audio_source_t source)
+{
+    return sp<PatchRecord>::make(
+            recordThread,
+            sampleRate,
+            channelMask,
+            format,
+            frameCount,
+            buffer,
+            bufferSize,
+            flags,
+            timeout,
+            source);
+}
+
+PatchRecord::PatchRecord(IAfRecordThread* recordThread,
                                                      uint32_t sampleRate,
                                                      audio_channel_mask_t channelMask,
                                                      audio_format_t format,
@@ -2961,7 +3125,7 @@
                 audioServerAttributionSource(getpid()), flags, TYPE_PATCH),
         PatchTrackBase(mCblk ? new ClientProxy(mCblk, mBuffer, frameCount, mFrameSize, false, true)
                         : nullptr,
-                       *recordThread, timeout)
+                       recordThread, timeout)
 {
     ALOGV("%s(%d): sampleRate %d mPeerTimeout %d.%03d sec",
                                       __func__, mId, sampleRate,
@@ -2969,7 +3133,7 @@
                                       (int)(mPeerTimeout.tv_nsec / 1000000));
 }
 
-AudioFlinger::RecordThread::PatchRecord::~PatchRecord()
+PatchRecord::~PatchRecord()
 {
     ALOGV("%s(%d)", __func__, mId);
 }
@@ -2993,7 +3157,7 @@
 }
 
 // static
-size_t AudioFlinger::RecordThread::PatchRecord::writeFrames(
+size_t PatchRecord::writeFrames(
         AudioBufferProvider* dest, const void* src, size_t frameCount, size_t frameSize)
 {
     size_t framesWritten = writeFramesHelper(dest, src, frameCount, frameSize);
@@ -3008,7 +3172,7 @@
 }
 
 // AudioBufferProvider interface
-status_t AudioFlinger::RecordThread::PatchRecord::getNextBuffer(
+status_t PatchRecord::getNextBuffer(
                                                   AudioBufferProvider::Buffer* buffer)
 {
     ALOG_ASSERT(mPeerProxy != 0, "%s(%d): called without peer proxy", __func__, mId);
@@ -3030,7 +3194,7 @@
     return status;
 }
 
-void AudioFlinger::RecordThread::PatchRecord::releaseBuffer(AudioBufferProvider::Buffer* buffer)
+void PatchRecord::releaseBuffer(AudioBufferProvider::Buffer* buffer)
 {
     ALOG_ASSERT(mPeerProxy != 0, "%s(%d): called without peer proxy", __func__, mId);
     Proxy::Buffer buf;
@@ -3040,13 +3204,13 @@
     TrackBase::releaseBuffer(buffer);
 }
 
-status_t AudioFlinger::RecordThread::PatchRecord::obtainBuffer(Proxy::Buffer* buffer,
+status_t PatchRecord::obtainBuffer(Proxy::Buffer* buffer,
                                                                const struct timespec *timeOut)
 {
     return mProxy->obtainBuffer(buffer, timeOut);
 }
 
-void AudioFlinger::RecordThread::PatchRecord::releaseBuffer(Proxy::Buffer* buffer)
+void PatchRecord::releaseBuffer(Proxy::Buffer* buffer)
 {
     mProxy->releaseBuffer(buffer);
 }
@@ -3061,8 +3225,28 @@
     return {ptr, free};
 }
 
-AudioFlinger::RecordThread::PassthruPatchRecord::PassthruPatchRecord(
-        RecordThread *recordThread,
+/* static */
+sp<IAfPatchRecord> IAfPatchRecord::createPassThru(
+        IAfRecordThread* recordThread,
+        uint32_t sampleRate,
+        audio_channel_mask_t channelMask,
+        audio_format_t format,
+        size_t frameCount,
+        audio_input_flags_t flags,
+        audio_source_t source)
+{
+    return sp<PassthruPatchRecord>::make(
+            recordThread,
+            sampleRate,
+            channelMask,
+            format,
+            frameCount,
+            flags,
+            source);
+}
+
+PassthruPatchRecord::PassthruPatchRecord(
+        IAfRecordThread* recordThread,
         uint32_t sampleRate,
         audio_channel_mask_t channelMask,
         audio_format_t format,
@@ -3078,18 +3262,18 @@
     memset(mStubBuffer.get(), 0, mFrameCount * mFrameSize);
 }
 
-sp<StreamInHalInterface> AudioFlinger::RecordThread::PassthruPatchRecord::obtainStream(
-        sp<ThreadBase>* thread)
+sp<StreamInHalInterface> PassthruPatchRecord::obtainStream(
+        sp<IAfThreadBase>* 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;
+    auto* const recordThread = (*thread)->asIAfRecordThread().get();
+    Mutex::Autolock _l(recordThread->mutex());
+    return recordThread->getInput() ? recordThread->getInput()->stream : nullptr;
 }
 
 // PatchProxyBufferProvider methods are called on DirectOutputThread
-status_t AudioFlinger::RecordThread::PassthruPatchRecord::obtainBuffer(
+status_t PassthruPatchRecord::obtainBuffer(
         Proxy::Buffer* buffer, const struct timespec* timeOut)
 {
     if (mUnconsumedFrames) {
@@ -3107,7 +3291,7 @@
     const size_t framesToRead = std::min(buffer->mFrameCount, mFrameCount);
     buffer->mFrameCount = 0;
     buffer->mRaw = nullptr;
-    sp<ThreadBase> thread;
+    sp<IAfThreadBase> thread;
     sp<StreamInHalInterface> stream = obtainStream(&thread);
     if (!stream) return NO_INIT;  // If there is no stream, RecordThread is not reading.
 
@@ -3155,7 +3339,7 @@
     return result;
 }
 
-void AudioFlinger::RecordThread::PassthruPatchRecord::releaseBuffer(Proxy::Buffer* buffer)
+void PassthruPatchRecord::releaseBuffer(Proxy::Buffer* buffer)
 {
     if (buffer->mFrameCount <= mUnconsumedFrames) {
         mUnconsumedFrames -= buffer->mFrameCount;
@@ -3172,7 +3356,7 @@
 // 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(
+status_t PassthruPatchRecord::read(
         void* buffer, size_t bytes, size_t* read)
 {
     bytes = std::min(bytes, mFrameCount * mFrameSize);
@@ -3191,15 +3375,15 @@
     return 0;
 }
 
-status_t AudioFlinger::RecordThread::PassthruPatchRecord::getCapturePosition(
+status_t PassthruPatchRecord::getCapturePosition(
         int64_t* frames, int64_t* time)
 {
-    sp<ThreadBase> thread;
+    sp<IAfThreadBase> thread;
     sp<StreamInHalInterface> stream = obtainStream(&thread);
     return stream ? stream->getCapturePosition(frames, time) : NO_INIT;
 }
 
-status_t AudioFlinger::RecordThread::PassthruPatchRecord::standby()
+status_t PassthruPatchRecord::standby()
 {
     // RecordThread issues 'standby' command in two major cases:
     // 1. Error on read--this case is handled in 'obtainBuffer'.
@@ -3211,7 +3395,7 @@
 }
 
 // As the buffer gets filled in obtainBuffer, here we only simulate data consumption.
-status_t AudioFlinger::RecordThread::PassthruPatchRecord::getNextBuffer(
+status_t PassthruPatchRecord::getNextBuffer(
         AudioBufferProvider::Buffer* buffer)
 {
     buffer->frameCount = mLastReadFrames;
@@ -3219,7 +3403,7 @@
     return NO_ERROR;
 }
 
-void AudioFlinger::RecordThread::PassthruPatchRecord::releaseBuffer(
+void PassthruPatchRecord::releaseBuffer(
         AudioBufferProvider::Buffer* buffer)
 {
     buffer->frameCount = 0;
@@ -3230,7 +3414,32 @@
 #undef LOG_TAG
 #define LOG_TAG "AF::MmapTrack"
 
-AudioFlinger::MmapThread::MmapTrack::MmapTrack(ThreadBase *thread,
+/* static */
+sp<IAfMmapTrack> IAfMmapTrack::create(IAfThreadBase* thread,
+          const audio_attributes_t& attr,
+          uint32_t sampleRate,
+          audio_format_t format,
+          audio_channel_mask_t channelMask,
+          audio_session_t sessionId,
+          bool isOut,
+          const android::content::AttributionSourceState& attributionSource,
+          pid_t creatorPid,
+          audio_port_handle_t portId)
+{
+    return sp<MmapTrack>::make(
+            thread,
+            attr,
+            sampleRate,
+            format,
+            channelMask,
+            sessionId,
+            isOut,
+            attributionSource,
+            creatorPid,
+            portId);
+}
+
+MmapTrack::MmapTrack(IAfThreadBase* thread,
         const audio_attributes_t& attr,
         uint32_t sampleRate,
         audio_format_t format,
@@ -3256,27 +3465,27 @@
     mTrackMetrics.logConstructor(creatorPid, uid(), id());
 }
 
-AudioFlinger::MmapThread::MmapTrack::~MmapTrack()
+MmapTrack::~MmapTrack()
 {
 }
 
-status_t AudioFlinger::MmapThread::MmapTrack::initCheck() const
+status_t MmapTrack::initCheck() const
 {
     return NO_ERROR;
 }
 
-status_t AudioFlinger::MmapThread::MmapTrack::start(AudioSystem::sync_event_t event __unused,
+status_t MmapTrack::start(AudioSystem::sync_event_t event __unused,
                                                     audio_session_t triggerSession __unused)
 {
     return NO_ERROR;
 }
 
-void AudioFlinger::MmapThread::MmapTrack::stop()
+void MmapTrack::stop()
 {
 }
 
 // AudioBufferProvider interface
-status_t AudioFlinger::MmapThread::MmapTrack::getNextBuffer(AudioBufferProvider::Buffer* buffer)
+status_t MmapTrack::getNextBuffer(AudioBufferProvider::Buffer* buffer)
 {
     buffer->frameCount = 0;
     buffer->raw = nullptr;
@@ -3284,21 +3493,20 @@
 }
 
 // ExtendedAudioBufferProvider interface
-size_t AudioFlinger::MmapThread::MmapTrack::framesReady() const {
+size_t MmapTrack::framesReady() const {
     return 0;
 }
 
-int64_t AudioFlinger::MmapThread::MmapTrack::framesReleased() const
+int64_t MmapTrack::framesReleased() const
 {
     return 0;
 }
 
-void AudioFlinger::MmapThread::MmapTrack::onTimestamp(const ExtendedTimestamp &timestamp __unused)
+void MmapTrack::onTimestamp(const ExtendedTimestamp& timestamp __unused)
 {
 }
 
-void AudioFlinger::MmapThread::MmapTrack::processMuteEvent_l(const sp<
-    IAudioManager>& audioManager, mute_state_t muteState)
+void MmapTrack::processMuteEvent_l(const sp<IAudioManager>& audioManager, mute_state_t muteState)
 {
     if (mMuteState == muteState) {
         // mute state did not change, do nothing
@@ -3329,13 +3537,13 @@
     }
 }
 
-void AudioFlinger::MmapThread::MmapTrack::appendDumpHeader(String8& result)
+void MmapTrack::appendDumpHeader(String8& result) const
 {
     result.appendFormat("Client Session Port Id  Format Chn mask  SRate Flags %s\n",
                         isOut() ? "Usg CT": "Source");
 }
 
-void AudioFlinger::MmapThread::MmapTrack::appendDump(String8& result, bool active __unused)
+void MmapTrack::appendDump(String8& result, bool active __unused) const
 {
     result.appendFormat("%6u %7u %7u %08X %08X %6u 0x%03X ",
             mPid,
diff --git a/services/audioflinger/afutils/Android.bp b/services/audioflinger/afutils/Android.bp
index 1580b8f..5e29ce9 100644
--- a/services/audioflinger/afutils/Android.bp
+++ b/services/audioflinger/afutils/Android.bp
@@ -39,18 +39,24 @@
         "AudioWatchdog.cpp",
         "BufLog.cpp",
         "NBAIO_Tee.cpp",
+        "Permission.cpp",
         "PropertyUtils.cpp",
         "TypedLogger.cpp",
+        "Vibrator.cpp",
     ],
 
     shared_libs: [
+        "framework-permission-aidl-cpp",
+        "libaudioclient_aidl_conversion",
         "libaudioutils",
         "libbase",
+        "libbinder",
         "libcutils", // property_get_int32
         "liblog",
         "libnbaio",
         "libnblog",
         "libutils",
+        "libvibrator",
     ],
 
     static_libs: [
diff --git a/services/audioflinger/afutils/DumpTryLock.h b/services/audioflinger/afutils/DumpTryLock.h
new file mode 100644
index 0000000..c185a68
--- /dev/null
+++ b/services/audioflinger/afutils/DumpTryLock.h
@@ -0,0 +1,31 @@
+/*
+ *
+ * Copyright 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <utils/Mutex.h>
+
+namespace android::afutils {
+
+inline bool dumpTryLock(Mutex& mutex)
+{
+    static constexpr int kDumpLockTimeoutNs = 1'000'000'000;
+    const status_t err = mutex.timedLock(kDumpLockTimeoutNs);
+    return err == NO_ERROR;
+}
+
+}  // android::afutils
\ No newline at end of file
diff --git a/services/audioflinger/afutils/Permission.cpp b/services/audioflinger/afutils/Permission.cpp
new file mode 100644
index 0000000..35448e3
--- /dev/null
+++ b/services/audioflinger/afutils/Permission.cpp
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "Permission"
+//#define LOG_NDEBUG 0
+
+#include "Permission.h"
+
+#include <binder/PermissionController.h>
+#include <media/AidlConversionCppNdk.h>
+#include <utils/Log.h>
+
+namespace android::afutils {
+
+// TODO b/182392769: use attribution source util
+content::AttributionSourceState checkAttributionSourcePackage(
+        const content::AttributionSourceState& attributionSource) {
+    Vector<String16> packages;
+    PermissionController{}.getPackagesForUid(attributionSource.uid, packages);
+
+    content::AttributionSourceState checkedAttributionSource = attributionSource;
+    if (!attributionSource.packageName.has_value()
+            || attributionSource.packageName.value().size() == 0) {
+        if (!packages.isEmpty()) {
+            checkedAttributionSource.packageName =
+                std::move(legacy2aidl_String16_string(packages[0]).value());
+        }
+    } else {
+        const String16 opPackageLegacy = VALUE_OR_FATAL(
+                aidl2legacy_string_view_String16(attributionSource.packageName.value_or("")));
+        if (std::find_if(packages.begin(), packages.end(),
+                [&opPackageLegacy](const auto& package) {
+                return opPackageLegacy == package; }) == packages.end()) {
+            ALOGW("The package name(%s) provided does not correspond to the uid %d",
+                    attributionSource.packageName.value_or("").c_str(), attributionSource.uid);
+        }
+    }
+    return checkedAttributionSource;
+}
+
+}  // namespace android::afutils
diff --git a/services/audioflinger/afutils/Permission.h b/services/audioflinger/afutils/Permission.h
new file mode 100644
index 0000000..97c7ff9
--- /dev/null
+++ b/services/audioflinger/afutils/Permission.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <android/content/AttributionSourceState.h>
+
+namespace android::afutils {
+
+content::AttributionSourceState checkAttributionSourcePackage(
+        const content::AttributionSourceState& attributionSource);
+
+}  // namespace android::afutils
diff --git a/services/audioflinger/afutils/Vibrator.cpp b/services/audioflinger/afutils/Vibrator.cpp
new file mode 100644
index 0000000..25fcc6a
--- /dev/null
+++ b/services/audioflinger/afutils/Vibrator.cpp
@@ -0,0 +1,71 @@
+/*
+ *
+ * Copyright 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "AudioFlinger::Vibrator"
+//#define LOG_NDEBUG 0
+
+#include "Vibrator.h"
+
+#include <android/os/IExternalVibratorService.h>
+#include <binder/IServiceManager.h>
+#include <utils/Log.h>
+
+#include <mutex>
+
+namespace android::afutils {
+
+static sp<os::IExternalVibratorService> getExternalVibratorService() {
+    static std::mutex m;
+    static sp<os::IExternalVibratorService> sExternalVibratorService;
+
+    std::lock_guard l(m);
+    if (sExternalVibratorService == nullptr) {
+        const sp<IBinder> binder = defaultServiceManager()->getService(
+                String16("external_vibrator_service"));
+        if (binder != nullptr) {
+            sExternalVibratorService = interface_cast<os::IExternalVibratorService>(binder);
+        }
+    }
+    return sExternalVibratorService;
+}
+
+os::HapticScale onExternalVibrationStart(const sp<os::ExternalVibration>& externalVibration) {
+    const sp<os::IExternalVibratorService> evs = getExternalVibratorService();
+    if (evs != nullptr) {
+        int32_t ret;
+        binder::Status status = evs->onExternalVibrationStart(*externalVibration, &ret);
+        if (status.isOk()) {
+            ALOGD("%s, start external vibration with intensity as %d", __func__, ret);
+            return os::ExternalVibration::externalVibrationScaleToHapticScale(ret);
+        }
+    }
+    ALOGD("%s, start external vibration with intensity as MUTE due to %s",
+            __func__,
+            evs == nullptr ? "external vibration service not found"
+                           : "error when querying intensity");
+    return os::HapticScale::MUTE;
+}
+
+void onExternalVibrationStop(const sp<os::ExternalVibration>& externalVibration) {
+    const sp<os::IExternalVibratorService> evs = getExternalVibratorService();
+    if (evs != nullptr) {
+        ALOGD("%s, stop external vibration", __func__);
+        evs->onExternalVibrationStop(*externalVibration);
+    }
+}
+
+}  // namespace android::afutils
diff --git a/services/audioflinger/afutils/Vibrator.h b/services/audioflinger/afutils/Vibrator.h
new file mode 100644
index 0000000..4354872
--- /dev/null
+++ b/services/audioflinger/afutils/Vibrator.h
@@ -0,0 +1,29 @@
+/*
+ *
+ * Copyright 2023, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <vibrator/ExternalVibration.h>
+#include <vibrator/ExternalVibrationUtils.h>
+
+namespace android::afutils {
+
+os::HapticScale onExternalVibrationStart(const sp<os::ExternalVibration>& externalVibration);
+
+void onExternalVibrationStop(const sp<os::ExternalVibration>& externalVibration);
+
+} // namespace android::afutils
diff --git a/services/audioflinger/datapath/AudioStreamIn.h b/services/audioflinger/datapath/AudioStreamIn.h
new file mode 100644
index 0000000..604a4e4
--- /dev/null
+++ b/services/audioflinger/datapath/AudioStreamIn.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include "AudioHwDevice.h"
+#include <media/audiohal/DeviceHalInterface.h>
+#include <media/audiohal/StreamHalInterface.h>
+
+namespace android {
+
+// 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;
+};
+
+// AudioStreamIn is immutable, so its fields are const.
+// The methods must not be const to match StreamHalInterface signature.
+
+struct AudioStreamIn : public Source {
+    const AudioHwDevice* const audioHwDev;
+    const sp<StreamInHalInterface> stream;
+    const audio_input_flags_t flags;
+
+    AudioStreamIn(
+            const AudioHwDevice* dev, const 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) final {
+        return stream->read(buffer, bytes, read);
+    }
+
+    status_t getCapturePosition(int64_t* frames, int64_t* time) final {
+        return stream->getCapturePosition(frames, time);
+    }
+
+    status_t standby() final { return stream->standby(); }
+
+    sp<DeviceHalInterface> hwDev() const { return audioHwDev->hwDevice(); }
+};
+
+}  // namespace android
diff --git a/services/audioflinger/datapath/ThreadMetrics.h b/services/audioflinger/datapath/ThreadMetrics.h
index 5493b3c..c643a57 100644
--- a/services/audioflinger/datapath/ThreadMetrics.h
+++ b/services/audioflinger/datapath/ThreadMetrics.h
@@ -17,6 +17,8 @@
 #ifndef ANDROID_AUDIO_THREADMETRICS_H
 #define ANDROID_AUDIO_THREADMETRICS_H
 
+#include <media/MediaMetricsItem.h>
+
 #include <mutex>
 
 namespace android {
diff --git a/services/audioflinger/datapath/TrackMetrics.h b/services/audioflinger/datapath/TrackMetrics.h
index f3425df..2b44acb 100644
--- a/services/audioflinger/datapath/TrackMetrics.h
+++ b/services/audioflinger/datapath/TrackMetrics.h
@@ -20,6 +20,8 @@
 #include <binder/IActivityManager.h>
 #include <binder/IPCThreadState.h>
 #include <binder/IServiceManager.h>
+#include <media/MediaMetricsItem.h>
+
 #include <mutex>
 
 namespace android {
diff --git a/services/audioflinger/datapath/VolumeInterface.h b/services/audioflinger/datapath/VolumeInterface.h
new file mode 100644
index 0000000..1564fe1
--- /dev/null
+++ b/services/audioflinger/datapath/VolumeInterface.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <system/audio.h>
+
+namespace android {
+
+class VolumeInterface : public virtual RefBase {
+public:
+    virtual void setMasterVolume(float value) = 0;
+    virtual void setMasterBalance(float balance) = 0;
+    virtual void setMasterMute(bool muted) = 0;
+    virtual void setStreamVolume(audio_stream_type_t stream, float value) = 0;
+    virtual void setStreamMute(audio_stream_type_t stream, bool muted) = 0;
+    // TODO(b/290699744) add "get" prefix for getter below.
+    virtual float streamVolume(audio_stream_type_t stream) const = 0;
+};
+
+}  // namespace android
diff --git a/services/audioflinger/fastpath/FastMixerState.h b/services/audioflinger/fastpath/FastMixerState.h
index c70e42a..8ab6d25 100644
--- a/services/audioflinger/fastpath/FastMixerState.h
+++ b/services/audioflinger/fastpath/FastMixerState.h
@@ -35,7 +35,7 @@
 class VolumeProvider {
 public:
     // The provider implementation is responsible for validating that the return value is in range.
-    virtual gain_minifloat_packed_t getVolumeLR() = 0;
+    virtual gain_minifloat_packed_t getVolumeLR() const = 0;
 protected:
     VolumeProvider() = default;
     virtual ~VolumeProvider() = default;
diff --git a/services/audiopolicy/common/managerdefinitions/include/EffectDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/EffectDescriptor.h
index 59eee52..d40bbcb 100644
--- a/services/audiopolicy/common/managerdefinitions/include/EffectDescriptor.h
+++ b/services/audiopolicy/common/managerdefinitions/include/EffectDescriptor.h
@@ -25,6 +25,10 @@
 
 namespace android {
 
+class AudioInputCollection;
+class AudioInputDescriptor;
+class AudioPolicyClientInterface;
+
 class EffectDescriptor : public RefBase
 {
 public:
@@ -40,6 +44,8 @@
 
     int mId;                   // effect unique ID
     audio_io_handle_t mIo;     // io the effect is attached to
+    bool mIsOrphan = false;    // on creation, effect is not yet attached but not yet orphan
+    bool mEnabledWhenMoved = false;    // Backup enabled state before being moved
     audio_session_t mSession;  // audio session the effect is on
     effect_descriptor_t mDesc; // effect descriptor
     bool mEnabled;             // enabled state: CPU load being used or not
@@ -69,12 +75,28 @@
 
     void moveEffects(audio_session_t session,
                      audio_io_handle_t srcOutput,
-                     audio_io_handle_t dstOutput);
+                     audio_io_handle_t dstOutput,
+                     AudioPolicyClientInterface *clientInterface);
     void moveEffects(const std::vector<int>& ids, audio_io_handle_t dstOutput);
+    void moveEffects(audio_session_t sessionId, audio_io_handle_t srcIo, audio_io_handle_t dstIo,
+            const AudioInputCollection *inputs, AudioPolicyClientInterface *clientInterface);
+    void moveEffectsForIo(audio_session_t sessionId, audio_io_handle_t dstIo,
+            const AudioInputCollection *inputs, AudioPolicyClientInterface *mClientInterface);
+    void putOrphanEffects(audio_session_t sessionId, audio_io_handle_t srcIo,
+            const AudioInputCollection *inputs, AudioPolicyClientInterface *clientInterface);
 
+    /**
+     * @brief Checks if an effect session was already attached to an io handle and return it if
+     * found. Check only for a given effect type if effectType is not null or for any effect
+     * otherwise.
+     * @param sessionId to consider.
+     * @param effectType to consider.
+     * @return ioHandle if found, AUDIO_IO_HANDLE_NONE otherwise.
+     */
     audio_io_handle_t getIoForSession(audio_session_t sessionId,
                                       const effect_uuid_t *effectType = nullptr);
-
+    bool hasOrphansForSession(audio_session_t sessionId);
+    EffectDescriptorCollection getOrphanEffectsForSession(audio_session_t sessionId) const;
     void dump(String8 *dst, int spaces = 0, bool verbose = true) const;
 
 private:
diff --git a/services/audiopolicy/common/managerdefinitions/src/EffectDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/EffectDescriptor.cpp
index 3f9c8b0..216d2eb 100644
--- a/services/audiopolicy/common/managerdefinitions/src/EffectDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/EffectDescriptor.cpp
@@ -18,9 +18,15 @@
 //#define LOG_NDEBUG 0
 
 #include <android-base/stringprintf.h>
+
+#include "AudioInputDescriptor.h"
 #include "EffectDescriptor.h"
 #include <utils/String8.h>
 
+#include <AudioPolicyInterface.h>
+#include "AudioPolicyMix.h"
+#include "HwModule.h"
+
 namespace android {
 
 void EffectDescriptor::dump(String8 *dst, int spaces) const
@@ -175,30 +181,57 @@
     return MAX_EFFECTS_MEMORY;
 }
 
-void EffectDescriptorCollection::moveEffects(audio_session_t session,
-                                             audio_io_handle_t srcOutput,
-                                             audio_io_handle_t dstOutput)
+void EffectDescriptorCollection::moveEffects(audio_session_t sessionId, audio_io_handle_t srcIo,
+                                             audio_io_handle_t dstIo,
+                                             AudioPolicyClientInterface *clientInterface)
 {
-    ALOGV("%s session %d srcOutput %d dstOutput %d", __func__, session, srcOutput, dstOutput);
+    ALOGV("%s session %d srcIo %d dstIo %d", __func__, sessionId, srcIo, dstIo);
     for (size_t i = 0; i < size(); i++) {
         sp<EffectDescriptor> effect = valueAt(i);
-        if (effect->mSession == session && effect->mIo == srcOutput) {
-            effect->mIo = dstOutput;
+        if (effect->mSession == sessionId && effect->mIo == srcIo) {
+            effect->mIo = dstIo;
+            // Backup enable state before any updatePolicyState call
+            effect->mIsOrphan = (dstIo == AUDIO_IO_HANDLE_NONE);
+        }
+    }
+    clientInterface->moveEffects(sessionId, srcIo, dstIo);
+}
+
+void EffectDescriptorCollection::moveEffects(const std::vector<int>& ids, audio_io_handle_t dstIo)
+{
+    ALOGV("%s num effects %zu, first ID %d, dstIo %d",
+        __func__, ids.size(), ids.size() ? ids[0] : 0, dstIo);
+    for (size_t i = 0; i < size(); i++) {
+        sp<EffectDescriptor> effect = valueAt(i);
+        if (std::find(begin(ids), end(ids), effect->mId) != end(ids)) {
+            effect->mIo = dstIo;
+            effect->mIsOrphan = (dstIo == AUDIO_IO_HANDLE_NONE);
         }
     }
 }
 
-void EffectDescriptorCollection::moveEffects(const std::vector<int>& ids,
-                                             audio_io_handle_t dstOutput)
+bool EffectDescriptorCollection::hasOrphansForSession(audio_session_t sessionId)
 {
-    ALOGV("%s num effects %zu, first ID %d, dstOutput %d",
-        __func__, ids.size(), ids.size() ? ids[0] : 0, dstOutput);
-    for (size_t i = 0; i < size(); i++) {
+    for (size_t i = 0; i < size(); ++i) {
         sp<EffectDescriptor> effect = valueAt(i);
-        if (std::find(begin(ids), end(ids), effect->mId) != end(ids)) {
-            effect->mIo = dstOutput;
+        if (effect->mSession == sessionId && effect->mIsOrphan) {
+            return true;
         }
     }
+    return false;
+}
+
+EffectDescriptorCollection EffectDescriptorCollection::getOrphanEffectsForSession(
+        audio_session_t sessionId) const
+{
+    EffectDescriptorCollection effects;
+    for (size_t i = 0; i < size(); i++) {
+        sp<EffectDescriptor> effect = valueAt(i);
+        if (effect->mSession == sessionId && effect->mIsOrphan) {
+            effects.add(keyAt(i), effect);
+        }
+    }
+    return effects;
 }
 
 audio_io_handle_t EffectDescriptorCollection::getIoForSession(audio_session_t sessionId,
@@ -214,6 +247,67 @@
     return AUDIO_IO_HANDLE_NONE;
 }
 
+void EffectDescriptorCollection::moveEffectsForIo(audio_session_t session,
+        audio_io_handle_t dstIo, const AudioInputCollection *inputs,
+        AudioPolicyClientInterface *clientInterface)
+{
+    // No src io: try to find from effect session the src Io to move from
+    audio_io_handle_t srcIo = getIoForSession(session);
+    if (hasOrphansForSession(session) || (srcIo != AUDIO_IO_HANDLE_NONE && srcIo != dstIo)) {
+        moveEffects(session, srcIo, dstIo, inputs, clientInterface);
+    }
+}
+
+void EffectDescriptorCollection::moveEffects(audio_session_t session,
+        audio_io_handle_t srcIo, audio_io_handle_t dstIo, const AudioInputCollection *inputs,
+        AudioPolicyClientInterface *clientInterface)
+{
+    if ((srcIo != AUDIO_IO_HANDLE_NONE && srcIo == dstIo)
+            || (srcIo == AUDIO_IO_HANDLE_NONE && !hasOrphansForSession(session))) {
+        return;
+    }
+    // Either we may find orphan effects for given session or effects for this session might have
+    // been assigned first to another input (it may happen when an input is released or recreated
+    // after client sets its preferred device)
+    EffectDescriptorCollection effectsToMove;
+    if (srcIo == AUDIO_IO_HANDLE_NONE) {
+        ALOGV("%s: restoring effects for session %d from orphan park to io=%d", __func__,
+                session, dstIo);
+        effectsToMove = getOrphanEffectsForSession(session);
+    } else {
+        ALOGV("%s: moving effects for session %d from io=%d to io=%d", __func__,
+                session, srcIo, dstIo);
+        sp<AudioInputDescriptor> previousInputDesc = inputs->valueFor(srcIo);
+        effectsToMove = getEffectsForIo(srcIo);
+        for (size_t i = 0; i < effectsToMove.size(); ++i) {
+            sp<EffectDescriptor> effect = effectsToMove.valueAt(i);
+            effect->mEnabledWhenMoved = effect->mEnabled;
+            previousInputDesc->trackEffectEnabled(effect, false);
+        }
+    }
+    moveEffects(session, srcIo, dstIo, clientInterface);
+
+    if (dstIo != AUDIO_IO_HANDLE_NONE) {
+        sp<AudioInputDescriptor> inputDesc = inputs->valueFor(dstIo);
+        for (size_t i = 0; i < effectsToMove.size(); ++i) {
+            sp<EffectDescriptor> effect = effectsToMove.valueAt(i);
+            inputDesc->trackEffectEnabled(effect, effect->mEnabledWhenMoved);
+        }
+    }
+}
+
+void EffectDescriptorCollection::putOrphanEffects(audio_session_t session,
+        audio_io_handle_t srcIo, const AudioInputCollection *inputs,
+        AudioPolicyClientInterface *clientInterface)
+{
+    if (getIoForSession(session) != srcIo) {
+       // Effect session not held by this client io handle
+       return;
+    }
+    ALOGV("%s: park effects for session %d and io=%d to orphans", __func__, session, srcIo);
+    moveEffects(session, srcIo, AUDIO_IO_HANDLE_NONE, inputs, clientInterface);
+}
+
 EffectDescriptorCollection EffectDescriptorCollection::getEffectsForIo(audio_io_handle_t io) const
 {
     EffectDescriptorCollection effects;
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index 8e8fc0a..f1f2048 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -1325,10 +1325,15 @@
         AudioProfileVector profiles;
         status_t ret = getProfilesForDevices(outputDevices, profiles, *flags, false /*isInput*/);
         if (ret == NO_ERROR && !profiles.empty()) {
-            config->channel_mask = profiles[0]->getChannels().empty() ? config->channel_mask
-                    : *profiles[0]->getChannels().begin();
-            config->sample_rate = profiles[0]->getSampleRates().empty() ? config->sample_rate
-                    : *profiles[0]->getSampleRates().begin();
+            const auto channels = profiles[0]->getChannels();
+            if (!channels.empty() && (channels.find(config->channel_mask) == channels.end())) {
+                config->channel_mask = *channels.begin();
+            }
+            const auto sampleRates = profiles[0]->getSampleRates();
+            if (!sampleRates.empty() &&
+                    (sampleRates.find(config->sample_rate) == sampleRates.end())) {
+                config->sample_rate = *sampleRates.begin();
+            }
             config->format = profiles[0]->getFormat();
         }
         return INVALID_OPERATION;
@@ -2645,6 +2650,7 @@
     sp<AudioPolicyMix> policyMix;
     sp<DeviceDescriptor> device;
     sp<AudioInputDescriptor> inputDesc;
+    sp<AudioInputDescriptor> previousInputDesc;
     sp<RecordClientDescriptor> clientDesc;
     audio_port_handle_t requestedDeviceId = *selectedDeviceId;
     uid_t uid = VALUE_OR_RETURN_STATUS(aidl2legacy_int32_t_uid_t(attributionSource.uid));
@@ -2774,10 +2780,15 @@
         status_t ret = getProfilesForDevices(
                 DeviceVector(device), profiles, flags, true /*isInput*/);
         if (ret == NO_ERROR && !profiles.empty()) {
-            config->channel_mask = profiles[0]->getChannels().empty() ? config->channel_mask
-                    : *profiles[0]->getChannels().begin();
-            config->sample_rate = profiles[0]->getSampleRates().empty() ? config->sample_rate
-                    : *profiles[0]->getSampleRates().begin();
+            const auto channels = profiles[0]->getChannels();
+            if (!channels.empty() && (channels.find(config->channel_mask) == channels.end())) {
+                config->channel_mask = *channels.begin();
+            }
+            const auto sampleRates = profiles[0]->getSampleRates();
+            if (!sampleRates.empty() &&
+                    (sampleRates.find(config->sample_rate) == sampleRates.end())) {
+                config->sample_rate = *sampleRates.begin();
+            }
             config->format = profiles[0]->getFormat();
         }
         goto error;
@@ -2796,6 +2807,8 @@
                                             requestedDeviceId, attributes.source, flags,
                                             isSoundTrigger);
     inputDesc = mInputs.valueFor(*input);
+    // Move (if found) effect for the client session to its input
+    mEffects.moveEffectsForIo(session, *input, &mInputs, mpClientInterface);
     inputDesc->addClient(clientDesc);
 
     ALOGV("getInputForAttr() returns input %d type %d selectedDeviceId %d for port ID %d",
@@ -3105,7 +3118,7 @@
     ALOGV("%s %d", __FUNCTION__, input);
 
     inputDesc->removeClient(portId);
-
+    mEffects.putOrphanEffects(client->session(), input, &mInputs, mpClientInterface);
     if (inputDesc->getClientCount() > 0) {
         ALOGV("%s(%d) %zu clients remaining", __func__, portId, inputDesc->getClientCount());
         return;
@@ -3467,8 +3480,8 @@
     }
 
     if (output != mMusicEffectOutput) {
-        mEffects.moveEffects(AUDIO_SESSION_OUTPUT_MIX, mMusicEffectOutput, output);
-        mpClientInterface->moveEffects(AUDIO_SESSION_OUTPUT_MIX, mMusicEffectOutput, output);
+        mEffects.moveEffects(AUDIO_SESSION_OUTPUT_MIX, mMusicEffectOutput, output,
+                mpClientInterface);
         mMusicEffectOutput = output;
     }
 
diff --git a/services/audiopolicy/service/Android.bp b/services/audiopolicy/service/Android.bp
index f4fc8f1..c674909 100644
--- a/services/audiopolicy/service/Android.bp
+++ b/services/audiopolicy/service/Android.bp
@@ -7,26 +7,8 @@
     default_applicable_licenses: ["frameworks_av_license"],
 }
 
-cc_library_shared {
-    name: "libaudiopolicyservice",
-
-    defaults: [
-        "latest_android_media_audio_common_types_cpp_shared",
-    ],
-
-    srcs: [
-        "AudioPolicyClientImpl.cpp",
-        "AudioPolicyEffects.cpp",
-        "AudioPolicyInterfaceImpl.cpp",
-        "AudioPolicyService.cpp",
-        "CaptureStateNotifier.cpp",
-        "Spatializer.cpp",
-        "SpatializerPoseController.cpp",
-    ],
-
-    include_dirs: [
-        "frameworks/av/services/audioflinger"
-    ],
+cc_defaults {
+    name: "libaudiopolicyservice_dependencies",
 
     shared_libs: [
         "libactivitymanager_aidl",
@@ -41,7 +23,6 @@
         "libaudioutils",
         "libbinder",
         "libcutils",
-        "libeffectsconfig",
         "libhardware_legacy",
         "libheadtracking",
         "libheadtracking-binding",
@@ -67,6 +48,36 @@
     ],
 
     static_libs: [
+        "libeffectsconfig",
+        "libaudiopolicycomponents",
+    ]
+}
+
+cc_library {
+    name: "libaudiopolicyservice",
+
+    defaults: [
+        "libaudiopolicyservice_dependencies",
+        "latest_android_media_audio_common_types_cpp_shared",
+    ],
+
+    srcs: [
+        "AudioRecordClient.cpp",
+        "AudioPolicyClientImpl.cpp",
+        "AudioPolicyEffects.cpp",
+        "AudioPolicyInterfaceImpl.cpp",
+        "AudioPolicyService.cpp",
+        "CaptureStateNotifier.cpp",
+        "Spatializer.cpp",
+        "SpatializerPoseController.cpp",
+    ],
+
+    include_dirs: [
+        "frameworks/av/services/audioflinger"
+    ],
+
+
+    static_libs: [
         "framework-permission-aidl-cpp",
     ],
 
diff --git a/services/audiopolicy/service/AudioPolicyEffects.cpp b/services/audiopolicy/service/AudioPolicyEffects.cpp
index 70a1785..85b7ad9 100644
--- a/services/audiopolicy/service/AudioPolicyEffects.cpp
+++ b/services/audiopolicy/service/AudioPolicyEffects.cpp
@@ -44,10 +44,7 @@
 AudioPolicyEffects::AudioPolicyEffects(const sp<EffectsFactoryHalInterface>& effectsFactoryHal) {
     // load xml config with effectsFactoryHal
     status_t loadResult = loadAudioEffectConfig(effectsFactoryHal);
-    if (loadResult == NO_ERROR) {
-        mDefaultDeviceEffectFuture =
-                std::async(std::launch::async, &AudioPolicyEffects::initDefaultDeviceEffects, this);
-    } else if (loadResult < 0) {
+    if (loadResult < 0) {
         ALOGW("Failed to query effect configuration, fallback to load .conf");
         // load automatic audio effect modules
         if (access(AUDIO_EFFECT_VENDOR_CONFIG_FILE, R_OK) == 0) {
@@ -60,6 +57,11 @@
     }
 }
 
+void AudioPolicyEffects::setDefaultDeviceEffects() {
+    mDefaultDeviceEffectFuture = std::async(
+                std::launch::async, &AudioPolicyEffects::initDefaultDeviceEffects, this);
+}
+
 AudioPolicyEffects::~AudioPolicyEffects()
 {
     size_t i = 0;
diff --git a/services/audiopolicy/service/AudioPolicyEffects.h b/services/audiopolicy/service/AudioPolicyEffects.h
index 9f65a96..e17df48 100644
--- a/services/audiopolicy/service/AudioPolicyEffects.h
+++ b/services/audiopolicy/service/AudioPolicyEffects.h
@@ -117,6 +117,8 @@
     // Remove the default stream effect from wherever it's attached.
     status_t removeStreamDefaultEffect(audio_unique_id_t id);
 
+    void setDefaultDeviceEffects();
+
 private:
     void initDefaultDeviceEffects();
 
diff --git a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
index 5d86e7c..a7b2a56 100644
--- a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
+++ b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
@@ -18,6 +18,7 @@
 //#define LOG_NDEBUG 0
 
 #include "AudioPolicyService.h"
+#include "AudioRecordClient.h"
 #include "TypeConverter.h"
 #include <media/AidlConversion.h>
 #include <media/AudioPolicy.h>
diff --git a/services/audiopolicy/service/AudioPolicyService.cpp b/services/audiopolicy/service/AudioPolicyService.cpp
index 5d22ed4..72fa245 100644
--- a/services/audiopolicy/service/AudioPolicyService.cpp
+++ b/services/audiopolicy/service/AudioPolicyService.cpp
@@ -34,6 +34,7 @@
 #include <binder/IResultReceiver.h>
 #include <utils/String16.h>
 #include <utils/threads.h>
+#include "AudioRecordClient.h"
 #include "AudioPolicyService.h"
 #include <hardware_legacy/power.h>
 #include <media/AidlConversion.h>
@@ -305,6 +306,9 @@
         }
     }
     AudioSystem::audioPolicyReady();
+    // AudioFlinger will handle effect creation and register these effects on audio_policy
+    // service. Hence, audio_policy service must be ready.
+    audioPolicyEffects->setDefaultDeviceEffects();
 }
 
 void AudioPolicyService::unloadAudioPolicyManager()
@@ -1164,20 +1168,6 @@
     return false;
 }
 
-/* static */
-bool AudioPolicyService::isAppOpSource(audio_source_t source)
-{
-    switch (source) {
-        case AUDIO_SOURCE_FM_TUNER:
-        case AUDIO_SOURCE_ECHO_REFERENCE:
-        case AUDIO_SOURCE_REMOTE_SUBMIX:
-            return false;
-        default:
-            break;
-    }
-    return true;
-}
-
 void AudioPolicyService::setAppState_l(sp<AudioRecordClient> client, app_state_t state)
 {
     AutoCallerClear acc;
@@ -1878,109 +1868,6 @@
     return binder::Status::ok();
 }
 
-// -----------  AudioPolicyService::OpRecordAudioMonitor implementation ----------
-
-// static
-sp<AudioPolicyService::OpRecordAudioMonitor>
-AudioPolicyService::OpRecordAudioMonitor::createIfNeeded(
-            const AttributionSourceState& attributionSource, const audio_attributes_t& attr,
-            wp<AudioCommandThread> commandThread)
-{
-    if (isAudioServerOrRootUid(attributionSource.uid)) {
-        ALOGV("not silencing record for audio or root source %s",
-                attributionSource.toString().c_str());
-        return nullptr;
-    }
-
-    if (!AudioPolicyService::isAppOpSource(attr.source)) {
-        ALOGD("not monitoring app op for uid %d and source %d",
-                attributionSource.uid, attr.source);
-        return nullptr;
-    }
-
-    if (!attributionSource.packageName.has_value()
-            || attributionSource.packageName.value().size() == 0) {
-        return nullptr;
-    }
-    return new OpRecordAudioMonitor(attributionSource, getOpForSource(attr.source), commandThread);
-}
-
-AudioPolicyService::OpRecordAudioMonitor::OpRecordAudioMonitor(
-        const AttributionSourceState& attributionSource, int32_t appOp,
-        wp<AudioCommandThread> commandThread) :
-            mHasOp(true), mAttributionSource(attributionSource), mAppOp(appOp),
-            mCommandThread(commandThread)
-{
-}
-
-AudioPolicyService::OpRecordAudioMonitor::~OpRecordAudioMonitor()
-{
-    if (mOpCallback != 0) {
-        mAppOpsManager.stopWatchingMode(mOpCallback);
-    }
-    mOpCallback.clear();
-}
-
-void AudioPolicyService::OpRecordAudioMonitor::onFirstRef()
-{
-    checkOp();
-    mOpCallback = new RecordAudioOpCallback(this);
-    ALOGV("start watching op %d for %s", mAppOp, mAttributionSource.toString().c_str());
-    // TODO: We need to always watch AppOpsManager::OP_RECORD_AUDIO too
-    // since it controls the mic permission for legacy apps.
-    mAppOpsManager.startWatchingMode(mAppOp, VALUE_OR_FATAL(aidl2legacy_string_view_String16(
-        mAttributionSource.packageName.value_or(""))),
-        mOpCallback);
-}
-
-bool AudioPolicyService::OpRecordAudioMonitor::hasOp() const {
-    return mHasOp.load();
-}
-
-// Called by RecordAudioOpCallback when the app op corresponding to this OpRecordAudioMonitor
-// is updated in AppOp callback and in onFirstRef()
-// Note this method is never called (and never to be) for audio server / root track
-// due to the UID in createIfNeeded(). As a result for those record track, it's:
-// - not called from constructor,
-// - not called from RecordAudioOpCallback because the callback is not installed in this case
-void AudioPolicyService::OpRecordAudioMonitor::checkOp(bool updateUidStates)
-{
-    // TODO: We need to always check AppOpsManager::OP_RECORD_AUDIO too
-    // since it controls the mic permission for legacy apps.
-    const int32_t mode = mAppOpsManager.checkOp(mAppOp,
-            mAttributionSource.uid, VALUE_OR_FATAL(aidl2legacy_string_view_String16(
-                mAttributionSource.packageName.value_or(""))));
-    const bool hasIt = (mode == AppOpsManager::MODE_ALLOWED);
-    // verbose logging only log when appOp changed
-    ALOGI_IF(hasIt != mHasOp.load(),
-            "App op %d missing, %ssilencing record %s",
-            mAppOp, hasIt ? "un" : "", mAttributionSource.toString().c_str());
-    mHasOp.store(hasIt);
-
-    if (updateUidStates) {
-          sp<AudioCommandThread> commandThread = mCommandThread.promote();
-          if (commandThread != nullptr) {
-              commandThread->updateUidStatesCommand();
-          }
-    }
-}
-
-AudioPolicyService::OpRecordAudioMonitor::RecordAudioOpCallback::RecordAudioOpCallback(
-        const wp<OpRecordAudioMonitor>& monitor) : mMonitor(monitor)
-{ }
-
-void AudioPolicyService::OpRecordAudioMonitor::RecordAudioOpCallback::opChanged(int32_t op,
-            const String16& packageName __unused) {
-    sp<OpRecordAudioMonitor> monitor = mMonitor.promote();
-    if (monitor != NULL) {
-        if (op != monitor->getOp()) {
-            return;
-        }
-        monitor->checkOp(true);
-    }
-}
-
-
 // -----------  AudioPolicyService::AudioCommandThread implementation ----------
 
 AudioPolicyService::AudioCommandThread::AudioCommandThread(String8 name,
diff --git a/services/audiopolicy/service/AudioPolicyService.h b/services/audiopolicy/service/AudioPolicyService.h
index d0cde64..94b48ea 100644
--- a/services/audiopolicy/service/AudioPolicyService.h
+++ b/services/audiopolicy/service/AudioPolicyService.h
@@ -1,4 +1,3 @@
-
 /*
  * Copyright (C) 2009 The Android Open Source Project
  *
@@ -28,7 +27,6 @@
 #include <utils/Vector.h>
 #include <utils/SortedVector.h>
 #include <binder/ActivityManager.h>
-#include <binder/AppOpsManager.h>
 #include <binder/BinderService.h>
 #include <binder/IUidObserver.h>
 #include <system/audio.h>
@@ -64,6 +62,12 @@
 
 // ----------------------------------------------------------------------------
 
+namespace media::audiopolicy {
+    class AudioRecordClient;
+}
+
+using ::android::media::audiopolicy::AudioRecordClient;
+
 class AudioPolicyService :
     public BinderService<AudioPolicyService>,
     public media::BnAudioPolicyService,
@@ -401,7 +405,6 @@
     // Handles binder shell commands
     virtual status_t shellCommand(int in, int out, int err, Vector<String16>& args);
 
-    class AudioRecordClient;
 
     // Sets whether the given UID records only silence
     virtual void setAppState_l(sp<AudioRecordClient> client, app_state_t state) REQUIRES(mLock);
@@ -542,6 +545,7 @@
     // Thread used to send audio config commands to audio flinger
     // For audio config commands, it is necessary because audio flinger requires that the calling
     // process (user) has permission to modify audio settings.
+    public:
     class AudioCommandThread : public Thread {
         class AudioCommand;
     public:
@@ -732,6 +736,7 @@
         wp<AudioPolicyService> mService;
     };
 
+    private:
     class AudioPolicyClient : public AudioPolicyClientInterface
     {
      public:
@@ -906,6 +911,7 @@
               bool                                 mAudioVolumeGroupCallbacksEnabled;
     };
 
+    public:
     class AudioClient : public virtual RefBase {
     public:
                 AudioClient(const audio_attributes_t attributes,
@@ -927,82 +933,8 @@
         const audio_port_handle_t deviceId;  // selected input device port ID
               bool active;                   // Playback/Capture is active or inactive
     };
-
-    // Checks and monitors app ops for AudioRecordClient
-    class OpRecordAudioMonitor : public RefBase {
-    public:
-        ~OpRecordAudioMonitor() override;
-        bool hasOp() const;
-        int32_t getOp() const { return mAppOp; }
-
-        static sp<OpRecordAudioMonitor> createIfNeeded(
-                const AttributionSourceState& attributionSource,
-                const audio_attributes_t& attr, wp<AudioCommandThread> commandThread);
-
     private:
-        OpRecordAudioMonitor(const AttributionSourceState& attributionSource, int32_t appOp,
-                wp<AudioCommandThread> commandThread);
 
-        void onFirstRef() override;
-
-        AppOpsManager mAppOpsManager;
-
-        class RecordAudioOpCallback : public BnAppOpsCallback {
-        public:
-            explicit RecordAudioOpCallback(const wp<OpRecordAudioMonitor>& monitor);
-            void opChanged(int32_t op, const String16& packageName) override;
-
-        private:
-            const wp<OpRecordAudioMonitor> mMonitor;
-        };
-
-        sp<RecordAudioOpCallback> mOpCallback;
-        // called by RecordAudioOpCallback when the app op for this OpRecordAudioMonitor is updated
-        // in AppOp callback and in onFirstRef()
-        // updateUidStates is true when the silenced state of active AudioRecordClients must be
-        // re-evaluated
-        void checkOp(bool updateUidStates = false);
-
-        std::atomic_bool mHasOp;
-        const AttributionSourceState mAttributionSource;
-        const int32_t mAppOp;
-        wp<AudioCommandThread> mCommandThread;
-    };
-
-    // --- AudioRecordClient ---
-    // Information about each registered AudioRecord client
-    // (between calls to getInputForAttr() and releaseInput())
-    class AudioRecordClient : public AudioClient {
-    public:
-                AudioRecordClient(const audio_attributes_t attributes,
-                          const audio_io_handle_t io,
-                          const audio_session_t session, audio_port_handle_t portId,
-                          const audio_port_handle_t deviceId,
-                          const AttributionSourceState& attributionSource,
-                          bool canCaptureOutput, bool canCaptureHotword,
-                          wp<AudioCommandThread> commandThread) :
-                    AudioClient(attributes, io, attributionSource,
-                        session, portId, deviceId), attributionSource(attributionSource),
-                        startTimeNs(0), canCaptureOutput(canCaptureOutput),
-                        canCaptureHotword(canCaptureHotword), silenced(false),
-                        mOpRecordAudioMonitor(
-                                OpRecordAudioMonitor::createIfNeeded(attributionSource,
-                                attributes, commandThread)) {}
-                ~AudioRecordClient() override = default;
-
-        bool hasOp() const {
-            return mOpRecordAudioMonitor ? mOpRecordAudioMonitor->hasOp() : true;
-        }
-
-        const AttributionSourceState attributionSource; // attribution source of client
-        nsecs_t startTimeNs;
-        const bool canCaptureOutput;
-        const bool canCaptureHotword;
-        bool silenced;
-
-    private:
-        sp<OpRecordAudioMonitor>           mOpRecordAudioMonitor;
-    };
 
 
     // --- AudioPlaybackClient ---
diff --git a/services/audiopolicy/service/AudioRecordClient.cpp b/services/audiopolicy/service/AudioRecordClient.cpp
new file mode 100644
index 0000000..de6a280
--- /dev/null
+++ b/services/audiopolicy/service/AudioRecordClient.cpp
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "AudioRecordClient.h"
+#include "AudioPolicyService.h"
+
+namespace android::media::audiopolicy {
+
+using android::AudioPolicyService;
+
+namespace {
+bool isAppOpSource(audio_source_t source)
+{
+    switch (source) {
+        case AUDIO_SOURCE_FM_TUNER:
+        case AUDIO_SOURCE_ECHO_REFERENCE:
+        case AUDIO_SOURCE_REMOTE_SUBMIX:
+            return false;
+        default:
+            break;
+    }
+    return true;
+}
+}
+
+// static
+sp<OpRecordAudioMonitor>
+OpRecordAudioMonitor::createIfNeeded(
+            const AttributionSourceState& attributionSource, const audio_attributes_t& attr,
+            wp<AudioPolicyService::AudioCommandThread> commandThread)
+{
+    if (isAudioServerOrRootUid(attributionSource.uid)) {
+        ALOGV("not silencing record for audio or root source %s",
+                attributionSource.toString().c_str());
+        return nullptr;
+    }
+
+    if (!isAppOpSource(attr.source)) {
+        ALOGD("not monitoring app op for uid %d and source %d",
+                attributionSource.uid, attr.source);
+        return nullptr;
+    }
+
+    if (!attributionSource.packageName.has_value()
+            || attributionSource.packageName.value().size() == 0) {
+        return nullptr;
+    }
+    return new OpRecordAudioMonitor(attributionSource, getOpForSource(attr.source), commandThread);
+}
+
+OpRecordAudioMonitor::OpRecordAudioMonitor(
+        const AttributionSourceState& attributionSource, int32_t appOp,
+        wp<AudioPolicyService::AudioCommandThread> commandThread) :
+            mHasOp(true), mAttributionSource(attributionSource), mAppOp(appOp),
+            mCommandThread(commandThread)
+{
+}
+
+OpRecordAudioMonitor::~OpRecordAudioMonitor()
+{
+    if (mOpCallback != 0) {
+        mAppOpsManager.stopWatchingMode(mOpCallback);
+    }
+    mOpCallback.clear();
+}
+
+void OpRecordAudioMonitor::onFirstRef()
+{
+    checkOp();
+    mOpCallback = new RecordAudioOpCallback(this);
+    ALOGV("start watching op %d for %s", mAppOp, mAttributionSource.toString().c_str());
+    // TODO: We need to always watch AppOpsManager::OP_RECORD_AUDIO too
+    // since it controls the mic permission for legacy apps.
+    mAppOpsManager.startWatchingMode(mAppOp, VALUE_OR_FATAL(aidl2legacy_string_view_String16(
+        mAttributionSource.packageName.value_or(""))),
+        AppOpsManager::WATCH_FOREGROUND_CHANGES,
+        mOpCallback);
+}
+
+bool OpRecordAudioMonitor::hasOp() const {
+    return mHasOp.load();
+}
+
+// Called by RecordAudioOpCallback when the app op corresponding to this OpRecordAudioMonitor
+// is updated in AppOp callback and in onFirstRef()
+// Note this method is never called (and never to be) for audio server / root track
+// due to the UID in createIfNeeded(). As a result for those record track, it's:
+// - not called from constructor,
+// - not called from RecordAudioOpCallback because the callback is not installed in this case
+void OpRecordAudioMonitor::checkOp(bool updateUidStates)
+{
+    // TODO: We need to always check AppOpsManager::OP_RECORD_AUDIO too
+    // since it controls the mic permission for legacy apps.
+    const int32_t mode = mAppOpsManager.checkOp(mAppOp,
+            mAttributionSource.uid, VALUE_OR_FATAL(aidl2legacy_string_view_String16(
+                mAttributionSource.packageName.value_or(""))));
+    const bool hasIt = (mode == AppOpsManager::MODE_ALLOWED);
+    // verbose logging only log when appOp changed
+    ALOGI_IF(hasIt != mHasOp.load(),
+            "App op %d missing, %ssilencing record %s",
+            mAppOp, hasIt ? "un" : "", mAttributionSource.toString().c_str());
+    mHasOp.store(hasIt);
+
+    if (updateUidStates) {
+          sp<AudioPolicyService::AudioCommandThread> commandThread = mCommandThread.promote();
+          if (commandThread != nullptr) {
+              commandThread->updateUidStatesCommand();
+          }
+    }
+}
+
+OpRecordAudioMonitor::RecordAudioOpCallback::RecordAudioOpCallback(
+        const wp<OpRecordAudioMonitor>& monitor) : mMonitor(monitor)
+{ }
+
+void OpRecordAudioMonitor::RecordAudioOpCallback::opChanged(int32_t op,
+            const String16& packageName __unused) {
+    sp<OpRecordAudioMonitor> monitor = mMonitor.promote();
+    if (monitor != NULL) {
+        if (op != monitor->getOp()) {
+            return;
+        }
+        monitor->checkOp(true);
+    }
+}
+
+} // android::media::audiopolicy::internal
diff --git a/services/audiopolicy/service/AudioRecordClient.h b/services/audiopolicy/service/AudioRecordClient.h
new file mode 100644
index 0000000..d3be316
--- /dev/null
+++ b/services/audiopolicy/service/AudioRecordClient.h
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <android/content/AttributionSourceState.h>
+#include <binder/AppOpsManager.h>
+#include <system/audio.h>
+#include <utils/RefBase.h>
+
+#include <cstdint>
+
+#include "AudioPolicyService.h"
+
+namespace android::media::audiopolicy {
+
+using ::android::content::AttributionSourceState;
+
+// Checks and monitors app ops for AudioRecordClient
+class OpRecordAudioMonitor : public RefBase {
+public:
+    ~OpRecordAudioMonitor() override;
+    bool hasOp() const;
+    int32_t getOp() const { return mAppOp; }
+
+    static sp<OpRecordAudioMonitor> createIfNeeded(
+            const AttributionSourceState& attributionSource,
+            const audio_attributes_t& attr,
+            wp<AudioPolicyService::AudioCommandThread> commandThread);
+
+private:
+    OpRecordAudioMonitor(const AttributionSourceState& attributionSource, int32_t appOp,
+            wp<AudioPolicyService::AudioCommandThread> commandThread);
+
+    void onFirstRef() override;
+
+    AppOpsManager mAppOpsManager;
+
+    class RecordAudioOpCallback : public BnAppOpsCallback {
+    public:
+        explicit RecordAudioOpCallback(const wp<OpRecordAudioMonitor>& monitor);
+        void opChanged(int32_t op, const String16& packageName) override;
+
+    private:
+        const wp<OpRecordAudioMonitor> mMonitor;
+    };
+
+    sp<RecordAudioOpCallback> mOpCallback;
+    // called by RecordAudioOpCallback when the app op for this OpRecordAudioMonitor is updated
+    // in AppOp callback and in onFirstRef()
+    // updateUidStates is true when the silenced state of active AudioRecordClients must be
+    // re-evaluated
+    void checkOp(bool updateUidStates = false);
+
+    std::atomic_bool mHasOp;
+    const AttributionSourceState mAttributionSource;
+    const int32_t mAppOp;
+    wp<AudioPolicyService::AudioCommandThread> mCommandThread;
+};
+
+// --- AudioRecordClient ---
+// Information about each registered AudioRecord client
+// (between calls to getInputForAttr() and releaseInput())
+class AudioRecordClient : public AudioPolicyService::AudioClient {
+public:
+            AudioRecordClient(const audio_attributes_t attributes,
+                      const audio_io_handle_t io,
+                      const audio_session_t session, audio_port_handle_t portId,
+                      const audio_port_handle_t deviceId,
+                      const AttributionSourceState& attributionSource,
+                      bool canCaptureOutput, bool canCaptureHotword,
+                      wp<AudioPolicyService::AudioCommandThread> commandThread) :
+                AudioClient(attributes, io, attributionSource,
+                    session, portId, deviceId), attributionSource(attributionSource),
+                    startTimeNs(0), canCaptureOutput(canCaptureOutput),
+                    canCaptureHotword(canCaptureHotword), silenced(false),
+                    mOpRecordAudioMonitor(
+                            OpRecordAudioMonitor::createIfNeeded(attributionSource,
+                            attributes, commandThread)) {}
+            ~AudioRecordClient() override = default;
+
+    bool hasOp() const {
+        return mOpRecordAudioMonitor ? mOpRecordAudioMonitor->hasOp() : true;
+    }
+
+    const AttributionSourceState attributionSource; // attribution source of client
+    nsecs_t startTimeNs;
+    const bool canCaptureOutput;
+    const bool canCaptureHotword;
+    bool silenced;
+
+private:
+    sp<OpRecordAudioMonitor>           mOpRecordAudioMonitor;
+};
+
+}; // namespace android::media::audiopolicy::internal
diff --git a/services/audiopolicy/tests/audiopolicymanager_tests.cpp b/services/audiopolicy/tests/audiopolicymanager_tests.cpp
index 15eae14..b56bb16 100644
--- a/services/audiopolicy/tests/audiopolicymanager_tests.cpp
+++ b/services/audiopolicy/tests/audiopolicymanager_tests.cpp
@@ -1905,7 +1905,7 @@
     audio_io_handle_t mOutput;
     audio_stream_type_t mStream = AUDIO_STREAM_DEFAULT;
     audio_port_handle_t mSelectedDeviceId = AUDIO_PORT_HANDLE_NONE;
-    audio_port_handle_t mPortId;
+    audio_port_handle_t mPortId = AUDIO_PORT_HANDLE_NONE;
     AudioPolicyInterface::output_type_t mOutputType;
     audio_attributes_t attr = AUDIO_ATTRIBUTES_INITIALIZER;
     bool mIsSpatialized;
diff --git a/services/camera/libcameraservice/Android.bp b/services/camera/libcameraservice/Android.bp
index a45365a..84dcf26 100644
--- a/services/camera/libcameraservice/Android.bp
+++ b/services/camera/libcameraservice/Android.bp
@@ -35,9 +35,91 @@
     ],
 }
 
-cc_library_shared {
+cc_defaults {
+    name: "libcameraservice_deps",
+
+    shared_libs: [
+        "libactivitymanager_aidl",
+        "libbase",
+        "libdl",
+        "libui",
+        "liblog",
+        "libutilscallstack",
+        "libutils",
+        "libbinder",
+        "libbinder_ndk",
+        "libactivitymanager_aidl",
+        "libpermission",
+        "libcutils",
+        "libexif",
+        "libmedia",
+        "libmediautils",
+        "libcamera_client",
+        "libcamera_metadata",
+        "libfmq",
+        "libgui",
+        "libhardware",
+        "libhidlbase",
+        "libimage_io",
+        "libjpeg",
+        "libultrahdr",
+        "libmedia_codeclist",
+        "libmedia_omx",
+        "libmemunreachable",
+        "libprocessgroup",
+        "libprocinfo",
+        "libsensorprivacy",
+        "libstagefright",
+        "libstagefright_foundation",
+        "libxml2",
+        "libyuv",
+        "android.hardware.camera.common@1.0",
+        "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",
+        "android.hardware.camera.device@3.7",
+        "android.hardware.common-V2-ndk",
+        "android.hardware.common.fmq-V1-ndk",
+        "android.hardware.graphics.common-V4-ndk",
+        "media_permission-aidl-cpp",
+    ],
+
+    static_libs: [
+        "android.frameworks.cameraservice.common@2.0",
+        "android.frameworks.cameraservice.service@2.0",
+        "android.frameworks.cameraservice.service@2.1",
+        "android.frameworks.cameraservice.service@2.2",
+        "android.frameworks.cameraservice.device@2.0",
+        "android.frameworks.cameraservice.device@2.1",
+        "android.frameworks.cameraservice.common-V1-ndk",
+        "android.frameworks.cameraservice.service-V1-ndk",
+        "android.frameworks.cameraservice.device-V1-ndk",
+        "android.hardware.camera.common-V1-ndk",
+        "android.hardware.camera.device-V2-ndk",
+        "android.hardware.camera.metadata-V2-ndk",
+        "android.hardware.camera.provider@2.4",
+        "android.hardware.camera.provider@2.5",
+        "android.hardware.camera.provider@2.6",
+        "android.hardware.camera.provider@2.7",
+        "android.hardware.camera.provider-V2-ndk",
+        "libaidlcommonsupport",
+        "libdynamic_depth",
+        "libprocessinfoservice_aidl",
+        "libbinderthreadstateutils",
+        "media_permission-aidl-cpp",
+        "libcameraservice_device_independent",
+    ],
+}
+
+cc_library {
     name: "libcameraservice",
 
+    defaults: [
+        "libcameraservice_deps",
+    ],
     // Camera service source
 
     srcs: [
@@ -105,6 +187,7 @@
         "utils/CameraThreadState.cpp",
         "utils/CameraTraces.cpp",
         "utils/AutoConditionLock.cpp",
+        "utils/SchedulingPolicyUtils.cpp",
         "utils/SessionConfigurationUtils.cpp",
         "utils/SessionConfigurationUtilsHidl.cpp",
         "utils/SessionStatsBuilder.cpp",
@@ -119,73 +202,6 @@
         "libmediametrics_headers",
     ],
 
-    shared_libs: [
-        "libactivitymanager_aidl",
-        "libbase",
-        "libdl",
-        "libexif",
-        "libui",
-        "liblog",
-        "libutilscallstack",
-        "libutils",
-        "libbinder",
-        "libbinder_ndk",
-        "libactivitymanager_aidl",
-        "libpermission",
-        "libcutils",
-        "libmedia",
-        "libmediautils",
-        "libcamera_client",
-        "libcamera_metadata",
-        "libdynamic_depth",
-        "libfmq",
-        "libgui",
-        "libhardware",
-        "libhidlbase",
-        "libimage_io",
-        "libjpeg",
-        "libultrahdr",
-        "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.service@2.2",
-        "android.frameworks.cameraservice.device@2.0",
-        "android.frameworks.cameraservice.device@2.1",
-        "android.frameworks.cameraservice.common-V1-ndk",
-        "android.frameworks.cameraservice.service-V1-ndk",
-        "android.frameworks.cameraservice.device-V1-ndk",
-        "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.provider@2.7",
-        "android.hardware.camera.provider-V2-ndk",
-        "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",
-        "android.hardware.camera.device@3.7",
-        "android.hardware.camera.device-V2-ndk",
-        "media_permission-aidl-cpp",
-    ],
-
-    static_libs: [
-        "libaidlcommonsupport",
-        "libprocessinfoservice_aidl",
-        "libbinderthreadstateutils",
-        "media_permission-aidl-cpp",
-        "libcameraservice_device_independent",
-    ],
-
     export_shared_lib_headers: [
         "libbinder",
         "libactivitymanager_aidl",
diff --git a/services/camera/libcameraservice/CameraFlashlight.cpp b/services/camera/libcameraservice/CameraFlashlight.cpp
index ffd38be..d9d8a3d 100644
--- a/services/camera/libcameraservice/CameraFlashlight.cpp
+++ b/services/camera/libcameraservice/CameraFlashlight.cpp
@@ -47,14 +47,14 @@
 CameraFlashlight::~CameraFlashlight() {
 }
 
-status_t CameraFlashlight::createFlashlightControl(const String8& cameraId) {
+status_t CameraFlashlight::createFlashlightControl(const std::string& cameraId) {
     ALOGV("%s: creating a flash light control for camera %s", __FUNCTION__,
-            cameraId.string());
+            cameraId.c_str());
     if (mFlashControl != NULL) {
         return INVALID_OPERATION;
     }
 
-    if (mProviderManager->supportSetTorchMode(cameraId.string())) {
+    if (mProviderManager->supportSetTorchMode(cameraId)) {
         mFlashControl = new ProviderFlashControl(mProviderManager);
     } else {
         ALOGE("Flashlight control not supported by this device!");
@@ -64,7 +64,7 @@
     return OK;
 }
 
-status_t CameraFlashlight::setTorchMode(const String8& cameraId, bool enabled) {
+status_t CameraFlashlight::setTorchMode(const std::string& cameraId, bool enabled) {
     if (!mFlashlightMapInitialized) {
         ALOGE("%s: findFlashUnits() must be called before this method.",
                __FUNCTION__);
@@ -72,7 +72,7 @@
     }
 
     ALOGV("%s: set torch mode of camera %s to %d", __FUNCTION__,
-            cameraId.string(), enabled);
+            cameraId.c_str(), enabled);
 
     status_t res = OK;
     Mutex::Autolock l(mLock);
@@ -87,7 +87,7 @@
         // TODO: Move torch status checks and state updates behind this CameraFlashlight lock
         // to avoid other similar race conditions.
         ALOGE("%s: Camera device %s is in use, cannot set torch mode.",
-                __FUNCTION__, cameraId.string());
+                __FUNCTION__, cameraId.c_str());
         return -EBUSY;
     }
 
@@ -117,7 +117,7 @@
     return res;
 }
 
-status_t CameraFlashlight::turnOnTorchWithStrengthLevel(const String8& cameraId,
+status_t CameraFlashlight::turnOnTorchWithStrengthLevel(const std::string& cameraId,
             int32_t torchStrength) {
     if (!mFlashlightMapInitialized) {
         ALOGE("%s: findFlashUnits() must be called before this method.",
@@ -126,13 +126,13 @@
     }
 
     ALOGV("%s: set torch strength of camera %s to %d", __FUNCTION__,
-            cameraId.string(), torchStrength);
+            cameraId.c_str(), torchStrength);
     status_t res = OK;
     Mutex::Autolock l(mLock);
 
     if (mOpenedCameraIds.indexOf(cameraId) != NAME_NOT_FOUND) {
         ALOGE("%s: Camera device %s is in use, cannot be turned ON.",
-                __FUNCTION__, cameraId.string());
+                __FUNCTION__, cameraId.c_str());
         return -EBUSY;
     }
 
@@ -148,7 +148,7 @@
 }
 
 
-status_t CameraFlashlight::getTorchStrengthLevel(const String8& cameraId,
+status_t CameraFlashlight::getTorchStrengthLevel(const std::string& cameraId,
             int32_t* torchStrength) {
     status_t res = OK;
     if (!mFlashlightMapInitialized) {
@@ -174,13 +174,13 @@
     Mutex::Autolock l(mLock);
     status_t res;
 
-    std::vector<String8> cameraIds;
+    std::vector<std::string> cameraIds;
     std::vector<std::string> ids = mProviderManager->getCameraDeviceIds();
     int numberOfCameras = static_cast<int>(ids.size());
     cameraIds.resize(numberOfCameras);
     // No module, must be provider
     for (size_t i = 0; i < cameraIds.size(); i++) {
-        cameraIds[i] = String8(ids[i].c_str());
+        cameraIds[i] = ids[i];
     }
 
     mFlashControl.clear();
@@ -195,17 +195,17 @@
         res = createFlashlightControl(id);
         if (res) {
             ALOGE("%s: failed to create flash control for %s", __FUNCTION__,
-                    id.string());
+                    id.c_str());
         } else {
             res = mFlashControl->hasFlashUnit(id, &hasFlash);
             if (res == -EUSERS || res == -EBUSY) {
                 ALOGE("%s: failed to check if camera %s has a flash unit. Some "
                         "camera devices may be opened", __FUNCTION__,
-                        id.string());
+                        id.c_str());
                 return res;
             } else if (res) {
                 ALOGE("%s: failed to check if camera %s has a flash unit. %s"
-                        " (%d)", __FUNCTION__, id.string(), strerror(-res),
+                        " (%d)", __FUNCTION__, id.c_str(), strerror(-res),
                         res);
             }
 
@@ -218,12 +218,12 @@
     return OK;
 }
 
-bool CameraFlashlight::hasFlashUnit(const String8& cameraId) {
+bool CameraFlashlight::hasFlashUnit(const std::string& cameraId) {
     Mutex::Autolock l(mLock);
     return hasFlashUnitLocked(cameraId);
 }
 
-bool CameraFlashlight::hasFlashUnitLocked(const String8& cameraId) {
+bool CameraFlashlight::hasFlashUnitLocked(const std::string& cameraId) {
     if (!mFlashlightMapInitialized) {
         ALOGE("%s: findFlashUnits() must be called before this method.",
                __FUNCTION__);
@@ -234,23 +234,23 @@
     if (index == NAME_NOT_FOUND) {
         // Might be external camera
         ALOGW("%s: camera %s not present when findFlashUnits() was called",
-                __FUNCTION__, cameraId.string());
+                __FUNCTION__, cameraId.c_str());
         return false;
     }
 
     return mHasFlashlightMap.valueAt(index);
 }
 
-bool CameraFlashlight::isBackwardCompatibleMode(const String8& cameraId) {
+bool CameraFlashlight::isBackwardCompatibleMode(const std::string& cameraId) {
     bool backwardCompatibleMode = false;
     if (mProviderManager != nullptr &&
-            !mProviderManager->supportSetTorchMode(cameraId.string())) {
+            !mProviderManager->supportSetTorchMode(cameraId)) {
         backwardCompatibleMode = true;
     }
     return backwardCompatibleMode;
 }
 
-status_t CameraFlashlight::prepareDeviceOpen(const String8& cameraId) {
+status_t CameraFlashlight::prepareDeviceOpen(const std::string& cameraId) {
     ALOGV("%s: prepare for device open", __FUNCTION__);
 
     Mutex::Autolock l(mLock);
@@ -270,10 +270,9 @@
             std::vector<std::string> ids = mProviderManager->getCameraDeviceIds();
             int numCameras = static_cast<int>(ids.size());
             for (int i = 0; i < numCameras; i++) {
-                String8 id8(ids[i].c_str());
-                if (hasFlashUnitLocked(id8)) {
+                if (hasFlashUnitLocked(ids[i])) {
                     mCallbacks->onTorchStatusChanged(
-                            id8, TorchModeStatus::NOT_AVAILABLE);
+                            ids[i], TorchModeStatus::NOT_AVAILABLE);
                 }
             }
         }
@@ -289,8 +288,8 @@
     return OK;
 }
 
-status_t CameraFlashlight::deviceClosed(const String8& cameraId) {
-    ALOGV("%s: device %s is closed", __FUNCTION__, cameraId.string());
+status_t CameraFlashlight::deviceClosed(const std::string& cameraId) {
+    ALOGV("%s: device %s is closed", __FUNCTION__, cameraId.c_str());
 
     Mutex::Autolock l(mLock);
     if (!mFlashlightMapInitialized) {
@@ -302,7 +301,7 @@
     ssize_t index = mOpenedCameraIds.indexOf(cameraId);
     if (index == NAME_NOT_FOUND) {
         ALOGE("%s: couldn't find camera %s in the opened list", __FUNCTION__,
-                cameraId.string());
+                cameraId.c_str());
     } else {
         mOpenedCameraIds.removeAt(index);
     }
@@ -316,10 +315,9 @@
         std::vector<std::string> ids = mProviderManager->getCameraDeviceIds();
         int numCameras = static_cast<int>(ids.size());
         for (int i = 0; i < numCameras; i++) {
-            String8 id8(ids[i].c_str());
-            if (hasFlashUnitLocked(id8)) {
+            if (hasFlashUnitLocked(ids[i])) {
                 mCallbacks->onTorchStatusChanged(
-                        id8, TorchModeStatus::AVAILABLE_OFF);
+                        ids[i], TorchModeStatus::AVAILABLE_OFF);
             }
         }
     }
@@ -343,35 +341,35 @@
 ProviderFlashControl::~ProviderFlashControl() {
 }
 
-status_t ProviderFlashControl::hasFlashUnit(const String8& cameraId, bool *hasFlash) {
+status_t ProviderFlashControl::hasFlashUnit(const std::string& cameraId, bool *hasFlash) {
     if (!hasFlash) {
         return BAD_VALUE;
     }
-    *hasFlash = mProviderManager->hasFlashUnit(cameraId.string());
+    *hasFlash = mProviderManager->hasFlashUnit(cameraId);
     return OK;
 }
 
-status_t ProviderFlashControl::setTorchMode(const String8& cameraId, bool enabled) {
+status_t ProviderFlashControl::setTorchMode(const std::string& cameraId, bool enabled) {
     ALOGV("%s: set camera %s torch mode to %d", __FUNCTION__,
-            cameraId.string(), enabled);
+            cameraId.c_str(), enabled);
 
-    return mProviderManager->setTorchMode(cameraId.string(), enabled);
+    return mProviderManager->setTorchMode(cameraId, enabled);
 }
 
-status_t ProviderFlashControl::turnOnTorchWithStrengthLevel(const String8& cameraId,
+status_t ProviderFlashControl::turnOnTorchWithStrengthLevel(const std::string& cameraId,
             int32_t torchStrength) {
     ALOGV("%s: change torch strength level of camera %s to %d", __FUNCTION__,
-            cameraId.string(), torchStrength);
+            cameraId.c_str(), torchStrength);
 
-    return mProviderManager->turnOnTorchWithStrengthLevel(cameraId.string(), torchStrength);
+    return mProviderManager->turnOnTorchWithStrengthLevel(cameraId, torchStrength);
 }
 
-status_t ProviderFlashControl::getTorchStrengthLevel(const String8& cameraId,
+status_t ProviderFlashControl::getTorchStrengthLevel(const std::string& cameraId,
             int32_t* torchStrength) {
     ALOGV("%s: get torch strength level of camera %s", __FUNCTION__,
-            cameraId.string());
+            cameraId.c_str());
 
-    return mProviderManager->getTorchStrengthLevel(cameraId.string(), torchStrength);
+    return mProviderManager->getTorchStrengthLevel(cameraId, torchStrength);
 }
 // ProviderFlashControl implementation ends
 
diff --git a/services/camera/libcameraservice/CameraFlashlight.h b/services/camera/libcameraservice/CameraFlashlight.h
index 1703ddc..733c928 100644
--- a/services/camera/libcameraservice/CameraFlashlight.h
+++ b/services/camera/libcameraservice/CameraFlashlight.h
@@ -17,6 +17,7 @@
 #ifndef ANDROID_SERVERS_CAMERA_CAMERAFLASHLIGHT_H
 #define ANDROID_SERVERS_CAMERA_CAMERAFLASHLIGHT_H
 
+#include <string>
 #include <gui/GLConsumer.h>
 #include <gui/Surface.h>
 #include <utils/KeyedVector.h>
@@ -38,20 +39,21 @@
         // cause the torch mode to be turned off in HAL v1 devices. If
         // previously-on torch mode is turned off,
         // callbacks.torch_mode_status_change() should be invoked.
-        virtual status_t hasFlashUnit(const String8& cameraId,
+        virtual status_t hasFlashUnit(const std::string& cameraId,
                     bool *hasFlash) = 0;
 
         // set the torch mode to on or off.
-        virtual status_t setTorchMode(const String8& cameraId,
+        virtual status_t setTorchMode(const std::string& cameraId,
                     bool enabled) = 0;
 
         // Change the brightness level of the torch. If the torch is OFF and
         // torchStrength >= 1, then the torch will also be turned ON.
-        virtual status_t turnOnTorchWithStrengthLevel(const String8& cameraId,
+        virtual status_t turnOnTorchWithStrengthLevel(const std::string& cameraId,
                     int32_t torchStrength) = 0;
 
         // Returns the torch strength level.
-        virtual status_t getTorchStrengthLevel(const String8& cameraId, int32_t* torchStrength) = 0;
+        virtual status_t getTorchStrengthLevel(const std::string& cameraId,
+                int32_t* torchStrength) = 0;
 };
 
 /**
@@ -70,49 +72,49 @@
 
         // Whether a camera device has a flash unit. Before findFlashUnits() is
         // called, this function always returns false.
-        bool hasFlashUnit(const String8& cameraId);
+        bool hasFlashUnit(const std::string& cameraId);
 
         // set the torch mode to on or off.
-        status_t setTorchMode(const String8& cameraId, bool enabled);
+        status_t setTorchMode(const std::string& cameraId, bool enabled);
 
         // Change the torch strength level of the flash unit in torch mode.
-        status_t turnOnTorchWithStrengthLevel(const String8& cameraId, int32_t torchStrength);
+        status_t turnOnTorchWithStrengthLevel(const std::string& cameraId, int32_t torchStrength);
 
         // Get the torch strength level
-        status_t getTorchStrengthLevel(const String8& cameraId, int32_t* torchStrength);
+        status_t getTorchStrengthLevel(const std::string& cameraId, int32_t* torchStrength);
 
         // Notify CameraFlashlight that camera service is going to open a camera
         // device. CameraFlashlight will free the resources that may cause the
         // camera open to fail. Camera service must call this function before
         // opening a camera device.
-        status_t prepareDeviceOpen(const String8& cameraId);
+        status_t prepareDeviceOpen(const std::string& cameraId);
 
         // Notify CameraFlashlight that camera service has closed a camera
         // device. CameraFlashlight may invoke callbacks for torch mode
         // available depending on the implementation.
-        status_t deviceClosed(const String8& cameraId);
+        status_t deviceClosed(const std::string& cameraId);
 
     private:
         // create flashlight control based on camera module API and camera
         // device API versions.
-        status_t createFlashlightControl(const String8& cameraId);
+        status_t createFlashlightControl(const std::string& cameraId);
 
         // mLock should be locked.
-        bool hasFlashUnitLocked(const String8& cameraId);
+        bool hasFlashUnitLocked(const std::string& cameraId);
 
         // Check if flash control is in backward compatible mode (simulated torch API by
         // opening cameras)
-        bool isBackwardCompatibleMode(const String8& cameraId);
+        bool isBackwardCompatibleMode(const std::string& cameraId);
 
         sp<FlashControlBase> mFlashControl;
 
         sp<CameraProviderManager> mProviderManager;
 
         CameraProviderManager::StatusListener* mCallbacks;
-        SortedVector<String8> mOpenedCameraIds;
+        SortedVector<std::string> mOpenedCameraIds;
 
         // camera id -> if it has a flash unit
-        KeyedVector<String8, bool> mHasFlashlightMap;
+        KeyedVector<std::string, bool> mHasFlashlightMap;
         bool mFlashlightMapInitialized;
 
         Mutex mLock; // protect CameraFlashlight API
@@ -127,10 +129,10 @@
         virtual ~ProviderFlashControl();
 
         // FlashControlBase
-        status_t hasFlashUnit(const String8& cameraId, bool *hasFlash);
-        status_t setTorchMode(const String8& cameraId, bool enabled);
-        status_t turnOnTorchWithStrengthLevel(const String8& cameraId, int32_t torchStrength);
-        status_t getTorchStrengthLevel(const String8& cameraId, int32_t* torchStrength);
+        status_t hasFlashUnit(const std::string& cameraId, bool *hasFlash);
+        status_t setTorchMode(const std::string& cameraId, bool enabled);
+        status_t turnOnTorchWithStrengthLevel(const std::string& cameraId, int32_t torchStrength);
+        status_t getTorchStrengthLevel(const std::string& cameraId, int32_t* torchStrength);
 
     private:
         sp<CameraProviderManager> mProviderManager;
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index 07b0279..6d3c7a5 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -24,6 +24,8 @@
 #include <cstdlib>
 #include <cstring>
 #include <ctime>
+#include <iostream>
+#include <sstream>
 #include <string>
 #include <sys/types.h>
 #include <inttypes.h>
@@ -36,7 +38,6 @@
 #include <aidl/AidlCameraService.h>
 #include <android-base/macros.h>
 #include <android-base/parseint.h>
-#include <android-base/stringprintf.h>
 #include <android/permission/PermissionChecker.h>
 #include <binder/ActivityManager.h>
 #include <binder/AppOpsManager.h>
@@ -71,6 +72,7 @@
 #include <system/camera_metadata.h>
 #include <binder/IServiceManager.h>
 #include <binder/IActivityManager.h>
+#include <camera/StringUtils.h>
 
 #include <system/camera.h>
 
@@ -87,11 +89,11 @@
     const char* kActivityServiceName = "activity";
     const char* kSensorPrivacyServiceName = "sensor_privacy";
     const char* kAppopsServiceName = "appops";
+    const char* kProcessInfoServiceName = "processinfo";
 }; // namespace anonymous
 
 namespace android {
 
-using base::StringPrintf;
 using binder::Status;
 using namespace camera3;
 using frameworks::cameraservice::service::V2_0::implementation::HidlCameraService;
@@ -116,28 +118,17 @@
     android_atomic_write(level, &gLogLevel);
 }
 
-// Convenience methods for constructing binder::Status objects for error returns
-
-#define STATUS_ERROR(errorCode, errorString) \
-    binder::Status::fromServiceSpecificError(errorCode, \
-            String8::format("%s:%d: %s", __FUNCTION__, __LINE__, errorString))
-
-#define STATUS_ERROR_FMT(errorCode, errorString, ...) \
-    binder::Status::fromServiceSpecificError(errorCode, \
-            String8::format("%s:%d: " errorString, __FUNCTION__, __LINE__, \
-                    __VA_ARGS__))
-
 // ----------------------------------------------------------------------------
 
-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
+static const std::string sDumpPermission("android.permission.DUMP");
+static const std::string sManageCameraPermission("android.permission.MANAGE_CAMERA");
+static const std::string sCameraPermission("android.permission.CAMERA");
+static const std::string sSystemCameraPermission("android.permission.SYSTEM_CAMERA");
+static const std::string
         sCameraSendSystemEventsPermission("android.permission.CAMERA_SEND_SYSTEM_EVENTS");
-static const String16 sCameraOpenCloseListenerPermission(
+static const std::string sCameraOpenCloseListenerPermission(
         "android.permission.CAMERA_OPEN_CLOSE_LISTENER");
-static const String16
+static const std::string
         sCameraInjectExternalCameraPermission("android.permission.CAMERA_INJECT_EXTERNAL_CAMERA");
 // Constant integer for FGS Logging, used to denote the API type for logger
 static const int LOG_FGS_CAMERA_API = 1;
@@ -145,12 +136,13 @@
 static constexpr int32_t kSystemNativeClientScore = resource_policy::PERCEPTIBLE_APP_ADJ;
 static constexpr int32_t kSystemNativeClientState =
         ActivityManager::PROCESS_STATE_PERSISTENT_UI;
+static const std::string kServiceName("cameraserver");
 
-const String8 CameraService::kOfflineDevice("offline-");
-const String16 CameraService::kWatchAllClientsFlag("all");
+const std::string CameraService::kOfflineDevice("offline-");
+const std::string CameraService::kWatchAllClientsFlag("all");
 
 // Set to keep track of logged service error events.
-static std::set<String8> sServiceErrorEventSet;
+static std::set<std::string> sServiceErrorEventSet;
 
 CameraService::CameraService(
         std::shared_ptr<CameraServiceProxyWrapper> cameraServiceProxyWrapper) :
@@ -181,7 +173,7 @@
 }
 
 void CameraService::onServiceRegistration(const String16& name, const sp<IBinder>&) {
-    if (name != String16(kAppopsServiceName)) {
+    if (name != toString16(kAppopsServiceName)) {
         return;
     }
 
@@ -219,9 +211,9 @@
     // boot availability for cameraservice, use checkService which is
     // non blocking and register for notifications
     sp<IServiceManager> sm = defaultServiceManager();
-    sp<IBinder> binder = sm->checkService(String16(kAppopsServiceName));
+    sp<IBinder> binder = sm->checkService(toString16(kAppopsServiceName));
     if (!binder) {
-        sm->registerForNotifications(String16(kAppopsServiceName), this);
+        sm->registerForNotifications(toString16(kAppopsServiceName), this);
     } else {
         mAppOps.setCameraAudioRestriction(mAudioRestriction);
     }
@@ -257,8 +249,8 @@
             if (res != OK) {
                 ALOGE("%s: Unable to initialize camera provider manager: %s (%d)",
                         __FUNCTION__, strerror(-res), res);
-                logServiceError(String8::format("Unable to initialize camera provider manager"),
-                ERROR_DISCONNECTED);
+                logServiceError("Unable to initialize camera provider manager",
+                        ERROR_DISCONNECTED);
                 return res;
             }
         }
@@ -283,14 +275,12 @@
 
 
     for (auto& cameraId : deviceIds) {
-        String8 id8 = String8(cameraId.c_str());
-        if (getCameraState(id8) == nullptr) {
-            onDeviceStatusChanged(id8, CameraDeviceStatus::PRESENT);
+        if (getCameraState(cameraId) == nullptr) {
+            onDeviceStatusChanged(cameraId, CameraDeviceStatus::PRESENT);
         }
         if (unavailPhysicalIds.count(cameraId) > 0) {
             for (const auto& physicalId : unavailPhysicalIds[cameraId]) {
-                String8 physicalId8 = String8(physicalId.c_str());
-                onDeviceStatusChanged(id8, physicalId8, CameraDeviceStatus::NOT_PRESENT);
+                onDeviceStatusChanged(cameraId, physicalId, CameraDeviceStatus::NOT_PRESENT);
             }
         }
     }
@@ -310,7 +300,7 @@
     return OK;
 }
 
-void CameraService::broadcastTorchModeStatus(const String8& cameraId, TorchModeStatus status,
+void CameraService::broadcastTorchModeStatus(const std::string& cameraId, TorchModeStatus status,
         SystemCameraKind systemCameraKind) {
     Mutex::Autolock lock(mStatusListenerLock);
     for (auto& i : mListenerList) {
@@ -321,7 +311,7 @@
             continue;
         }
         auto ret = i->getListener()->onTorchStatusChanged(mapToInterface(status),
-                String16{cameraId});
+                cameraId);
         i->handleBinderStatus(ret, "%s: Failed to trigger onTorchStatusChanged for %d:%d: %d",
                 __FUNCTION__, i->getListenerUid(), i->getListenerPid(), ret.exceptionCode());
     }
@@ -343,7 +333,7 @@
     mNormalDeviceIdsWithoutSystemCamera.clear();
     for (auto &deviceId : normalDeviceIds) {
         SystemCameraKind deviceKind = SystemCameraKind::PUBLIC;
-        if (getSystemCameraKind(String8(deviceId.c_str()), &deviceKind) != OK) {
+        if (getSystemCameraKind(deviceId, &deviceKind) != OK) {
             ALOGE("%s: Invalid camera id %s, skipping", __FUNCTION__, deviceId.c_str());
             continue;
         }
@@ -358,14 +348,15 @@
               mNormalDeviceIdsWithoutSystemCamera.size());
 }
 
-status_t CameraService::getSystemCameraKind(const String8& cameraId, SystemCameraKind *kind) const {
+status_t CameraService::getSystemCameraKind(const std::string& cameraId,
+        SystemCameraKind *kind) const {
     auto state = getCameraState(cameraId);
     if (state != nullptr) {
         *kind = state->getSystemCameraKind();
         return OK;
     }
     // Hidden physical camera ids won't have CameraState
-    return mCameraProviderManager->getSystemCameraKind(cameraId.c_str(), kind);
+    return mCameraProviderManager->getSystemCameraKind(cameraId, kind);
 }
 
 void CameraService::updateCameraNumAndIds() {
@@ -388,9 +379,8 @@
     for (const auto& cameraId : mNormalDeviceIdsWithoutSystemCamera) {
         int facing = -1;
         int orientation = 0;
-        String8 cameraId8(cameraId.c_str());
         int portraitRotation;
-        getDeviceVersion(cameraId8, /*overrideToPortrait*/false, /*out*/&portraitRotation,
+        getDeviceVersion(cameraId, /*overrideToPortrait*/false, /*out*/&portraitRotation,
                 /*out*/&facing, /*out*/&orientation);
         if (facing == -1) {
             ALOGE("%s: Unable to get camera device \"%s\" facing", __FUNCTION__, cameraId.c_str());
@@ -422,8 +412,7 @@
     }
 }
 
-void CameraService::addStates(const String8 id) {
-    std::string cameraId(id.c_str());
+void CameraService::addStates(const std::string& cameraId) {
     CameraResourceCost cost;
     status_t res = mCameraProviderManager->getResourceCost(cameraId, &cost);
     if (res != OK) {
@@ -438,61 +427,61 @@
     }
     std::vector<std::string> physicalCameraIds;
     mCameraProviderManager->isLogicalCamera(cameraId, &physicalCameraIds);
-    std::set<String8> conflicting;
+    std::set<std::string> conflicting;
     for (size_t i = 0; i < cost.conflictingDevices.size(); i++) {
-        conflicting.emplace(String8(cost.conflictingDevices[i].c_str()));
+        conflicting.emplace(cost.conflictingDevices[i]);
     }
 
     {
         Mutex::Autolock lock(mCameraStatesLock);
-        mCameraStates.emplace(id, std::make_shared<CameraState>(id, cost.resourceCost,
+        mCameraStates.emplace(cameraId, std::make_shared<CameraState>(cameraId, cost.resourceCost,
                 conflicting, deviceKind, physicalCameraIds));
     }
 
-    if (mFlashlight->hasFlashUnit(id)) {
+    if (mFlashlight->hasFlashUnit(cameraId)) {
         Mutex::Autolock al(mTorchStatusMutex);
-        mTorchStatusMap.add(id, TorchModeStatus::AVAILABLE_OFF);
+        mTorchStatusMap.add(cameraId, TorchModeStatus::AVAILABLE_OFF);
 
-        broadcastTorchModeStatus(id, TorchModeStatus::AVAILABLE_OFF, deviceKind);
+        broadcastTorchModeStatus(cameraId, TorchModeStatus::AVAILABLE_OFF, deviceKind);
     }
 
     updateCameraNumAndIds();
-    logDeviceAdded(id, "Device added");
+    logDeviceAdded(cameraId, "Device added");
 }
 
-void CameraService::removeStates(const String8 id) {
+void CameraService::removeStates(const std::string& cameraId) {
     updateCameraNumAndIds();
-    if (mFlashlight->hasFlashUnit(id)) {
+    if (mFlashlight->hasFlashUnit(cameraId)) {
         Mutex::Autolock al(mTorchStatusMutex);
-        mTorchStatusMap.removeItem(id);
+        mTorchStatusMap.removeItem(cameraId);
     }
 
     {
         Mutex::Autolock lock(mCameraStatesLock);
-        mCameraStates.erase(id);
+        mCameraStates.erase(cameraId);
     }
 }
 
-void CameraService::onDeviceStatusChanged(const String8& id,
+void CameraService::onDeviceStatusChanged(const std::string& cameraId,
         CameraDeviceStatus newHalStatus) {
     ALOGI("%s: Status changed for cameraId=%s, newStatus=%d", __FUNCTION__,
-            id.string(), newHalStatus);
+            cameraId.c_str(), newHalStatus);
 
     StatusInternal newStatus = mapToInternal(newHalStatus);
 
-    std::shared_ptr<CameraState> state = getCameraState(id);
+    std::shared_ptr<CameraState> state = getCameraState(cameraId);
 
     if (state == nullptr) {
         if (newStatus == StatusInternal::PRESENT) {
             ALOGI("%s: Unknown camera ID %s, a new camera is added",
-                    __FUNCTION__, id.string());
+                    __FUNCTION__, cameraId.c_str());
 
             // First add as absent to make sure clients are notified below
-            addStates(id);
+            addStates(cameraId);
 
-            updateStatus(newStatus, id);
+            updateStatus(newStatus, cameraId);
         } else {
-            ALOGE("%s: Bad camera ID %s", __FUNCTION__, id.string());
+            ALOGE("%s: Bad camera ID %s", __FUNCTION__, cameraId.c_str());
         }
         return;
     }
@@ -505,12 +494,12 @@
     }
 
     if (newStatus == StatusInternal::NOT_PRESENT) {
-        logDeviceRemoved(id, String8::format("Device status changed from %d to %d", oldStatus,
+        logDeviceRemoved(cameraId, fmt::sprintf("Device status changed from %d to %d", oldStatus,
                 newStatus));
 
         // Set the device status to NOT_PRESENT, clients will no longer be able to connect
         // to this device until the status changes
-        updateStatus(StatusInternal::NOT_PRESENT, id);
+        updateStatus(StatusInternal::NOT_PRESENT, cameraId);
 
         sp<BasicClient> clientToDisconnectOnline, clientToDisconnectOffline;
         {
@@ -522,28 +511,28 @@
 
             // Remove online as well as offline client from the list of active clients,
             // if they are present
-            clientToDisconnectOnline = removeClientLocked(id);
-            clientToDisconnectOffline = removeClientLocked(kOfflineDevice + id);
+            clientToDisconnectOnline = removeClientLocked(cameraId);
+            clientToDisconnectOffline = removeClientLocked(kOfflineDevice + cameraId);
         }
 
-        disconnectClient(id, clientToDisconnectOnline);
-        disconnectClient(kOfflineDevice + id, clientToDisconnectOffline);
+        disconnectClient(cameraId, clientToDisconnectOnline);
+        disconnectClient(kOfflineDevice + cameraId, clientToDisconnectOffline);
 
-        removeStates(id);
+        removeStates(cameraId);
     } else {
         if (oldStatus == StatusInternal::NOT_PRESENT) {
-            logDeviceAdded(id, String8::format("Device status changed from %d to %d", oldStatus,
+            logDeviceAdded(cameraId, fmt::sprintf("Device status changed from %d to %d", oldStatus,
                     newStatus));
         }
-        updateStatus(newStatus, id);
+        updateStatus(newStatus, cameraId);
     }
 }
 
-void CameraService::onDeviceStatusChanged(const String8& id,
-        const String8& physicalId,
+void CameraService::onDeviceStatusChanged(const std::string& id,
+        const std::string& physicalId,
         CameraDeviceStatus newHalStatus) {
     ALOGI("%s: Status changed for cameraId=%s, physicalCameraId=%s, newStatus=%d",
-            __FUNCTION__, id.string(), physicalId.string(), newHalStatus);
+            __FUNCTION__, id.c_str(), physicalId.c_str(), newHalStatus);
 
     StatusInternal newStatus = mapToInternal(newHalStatus);
 
@@ -551,7 +540,7 @@
 
     if (state == nullptr) {
         ALOGE("%s: Physical camera id %s status change on a non-present ID %s",
-                __FUNCTION__, physicalId.string(), id.string());
+                __FUNCTION__, physicalId.c_str(), id.c_str());
         return;
     }
 
@@ -559,7 +548,7 @@
     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);
+                __FUNCTION__, physicalId.c_str(), newHalStatus, logicalCameraStatus);
         return;
     }
 
@@ -571,21 +560,18 @@
     }
 
     if (updated) {
-        String8 idCombo = id + " : " + physicalId;
+        std::string idCombo = id + " : " + physicalId;
         if (newStatus == StatusInternal::PRESENT) {
-            logDeviceAdded(idCombo,
-                    String8::format("Device status changed to %d", newStatus));
+            logDeviceAdded(idCombo, fmt::sprintf("Device status changed to %d", newStatus));
         } else {
-            logDeviceRemoved(idCombo,
-                    String8::format("Device status changed to %d", newStatus));
+            logDeviceRemoved(idCombo, fmt::sprintf("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());
+            ALOGE("%s: Invalid camera id %s, skipping", __FUNCTION__, id.c_str());
             return;
         }
-        String16 id16(id), physicalId16(physicalId);
         Mutex::Autolock lock(mStatusListenerLock);
         for (auto& listener : mListenerList) {
             if (shouldSkipStatusUpdates(deviceKind, listener->isVendorListener(),
@@ -595,7 +581,7 @@
                 continue;
             }
             auto ret = listener->getListener()->onPhysicalCameraStatusChanged(
-                    mapToInterface(newStatus), id16, physicalId16);
+                    mapToInterface(newStatus), id, physicalId);
             listener->handleBinderStatus(ret,
                     "%s: Failed to trigger onPhysicalCameraStatusChanged for %d:%d: %d",
                     __FUNCTION__, listener->getListenerUid(), listener->getListenerPid(),
@@ -604,10 +590,10 @@
     }
 }
 
-void CameraService::disconnectClient(const String8& id, sp<BasicClient> clientToDisconnect) {
+void CameraService::disconnectClient(const std::string& 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());
+                __FUNCTION__, id.c_str());
         // Notify the client of disconnection
         clientToDisconnect->notifyError(
                 hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_DISCONNECTED,
@@ -616,13 +602,13 @@
     }
 }
 
-void CameraService::onTorchStatusChanged(const String8& cameraId,
+void CameraService::onTorchStatusChanged(const std::string& cameraId,
         TorchModeStatus newStatus) {
     SystemCameraKind systemCameraKind = SystemCameraKind::PUBLIC;
     status_t res = getSystemCameraKind(cameraId, &systemCameraKind);
     if (res != OK) {
         ALOGE("%s: Could not get system camera kind for camera id %s", __FUNCTION__,
-                cameraId.string());
+                cameraId.c_str());
         return;
     }
     Mutex::Autolock al(mTorchStatusMutex);
@@ -630,34 +616,33 @@
 }
 
 
-void CameraService::onTorchStatusChanged(const String8& cameraId,
+void CameraService::onTorchStatusChanged(const std::string& cameraId,
         TorchModeStatus newStatus, SystemCameraKind systemCameraKind) {
     Mutex::Autolock al(mTorchStatusMutex);
     onTorchStatusChangedLocked(cameraId, newStatus, systemCameraKind);
 }
 
-void CameraService::broadcastTorchStrengthLevel(const String8& cameraId,
+void CameraService::broadcastTorchStrengthLevel(const std::string& cameraId,
         int32_t newStrengthLevel) {
     Mutex::Autolock lock(mStatusListenerLock);
     for (auto& i : mListenerList) {
-        auto ret = i->getListener()->onTorchStrengthLevelChanged(String16{cameraId},
-                newStrengthLevel);
+        auto ret = i->getListener()->onTorchStrengthLevelChanged(cameraId, newStrengthLevel);
         i->handleBinderStatus(ret,
                 "%s: Failed to trigger onTorchStrengthLevelChanged for %d:%d: %d", __FUNCTION__,
                 i->getListenerUid(), i->getListenerPid(), ret.exceptionCode());
     }
 }
 
-void CameraService::onTorchStatusChangedLocked(const String8& cameraId,
+void CameraService::onTorchStatusChangedLocked(const std::string& cameraId,
         TorchModeStatus newStatus, SystemCameraKind systemCameraKind) {
     ALOGI("%s: Torch status changed for cameraId=%s, newStatus=%d",
-            __FUNCTION__, cameraId.string(), newStatus);
+            __FUNCTION__, cameraId.c_str(), newStatus);
 
     TorchModeStatus status;
     status_t res = getTorchStatusLocked(cameraId, &status);
     if (res) {
         ALOGE("%s: cannot get torch status of camera %s: %s (%d)",
-                __FUNCTION__, cameraId.string(), strerror(-res), res);
+                __FUNCTION__, cameraId.c_str(), strerror(-res), res);
         return;
     }
     if (status == newStatus) {
@@ -682,18 +667,18 @@
             if (oldUid != newUid) {
                 // If the UID has changed, log the status and update current UID in mTorchUidMap
                 if (status == TorchModeStatus::AVAILABLE_ON) {
-                    notifier.noteFlashlightOff(cameraId, oldUid);
+                    notifier.noteFlashlightOff(toString8(cameraId), oldUid);
                 }
                 if (newStatus == TorchModeStatus::AVAILABLE_ON) {
-                    notifier.noteFlashlightOn(cameraId, newUid);
+                    notifier.noteFlashlightOn(toString8(cameraId), newUid);
                 }
                 iter->second.second = newUid;
             } else {
                 // If the UID has not changed, log the status
                 if (newStatus == TorchModeStatus::AVAILABLE_ON) {
-                    notifier.noteFlashlightOn(cameraId, oldUid);
+                    notifier.noteFlashlightOn(toString8(cameraId), oldUid);
                 } else {
-                    notifier.noteFlashlightOff(cameraId, oldUid);
+                    notifier.noteFlashlightOff(toString8(cameraId), oldUid);
                 }
             }
         }
@@ -701,17 +686,100 @@
     broadcastTorchModeStatus(cameraId, newStatus, systemCameraKind);
 }
 
-static bool hasPermissionsForSystemCamera(int callingPid, int callingUid) {
+static bool isAutomotiveDevice() {
+    // Checks the property ro.hardware.type and returns true if it is
+    // automotive.
+    char value[PROPERTY_VALUE_MAX] = {0};
+    property_get("ro.hardware.type", value, "");
+    return strncmp(value, "automotive", PROPERTY_VALUE_MAX) == 0;
+}
+
+static bool isAutomotivePrivilegedClient(int32_t uid) {
+    // Returns false if this is not an automotive device type.
+    if (!isAutomotiveDevice())
+        return false;
+
+    // Returns true if the uid is AID_AUTOMOTIVE_EVS which is a
+    // privileged client uid used for safety critical use cases such as
+    // rear view and surround view.
+    return uid == AID_AUTOMOTIVE_EVS;
+}
+
+bool CameraService::isAutomotiveExteriorSystemCamera(const std::string& cam_id) const{
+    // Returns false if this is not an automotive device type.
+    if (!isAutomotiveDevice())
+        return false;
+
+    // Returns false if no camera id is provided.
+    if (cam_id.empty())
+        return false;
+
+    SystemCameraKind systemCameraKind = SystemCameraKind::PUBLIC;
+    if (getSystemCameraKind(cam_id, &systemCameraKind) != OK) {
+        // This isn't a known camera ID, so it's not a system camera.
+        ALOGE("%s: Unknown camera id %s, ", __FUNCTION__, cam_id.c_str());
+        return false;
+    }
+
+    if (systemCameraKind != SystemCameraKind::SYSTEM_ONLY_CAMERA) {
+        ALOGE("%s: camera id %s is not a system camera", __FUNCTION__, cam_id.c_str());
+        return false;
+    }
+
+    CameraMetadata cameraInfo;
+    status_t res = mCameraProviderManager->getCameraCharacteristics(
+            cam_id, false, &cameraInfo, false);
+    if (res != OK){
+        ALOGE("%s: Not able to get camera characteristics for camera id %s",__FUNCTION__,
+                cam_id.c_str());
+        return false;
+    }
+
+    camera_metadata_entry auto_location  = cameraInfo.find(ANDROID_AUTOMOTIVE_LOCATION);
+    if (auto_location.count != 1)
+        return false;
+
+    uint8_t location = auto_location.data.u8[0];
+    if ((location != ANDROID_AUTOMOTIVE_LOCATION_EXTERIOR_FRONT) &&
+            (location != ANDROID_AUTOMOTIVE_LOCATION_EXTERIOR_REAR) &&
+            (location != ANDROID_AUTOMOTIVE_LOCATION_EXTERIOR_LEFT) &&
+            (location != ANDROID_AUTOMOTIVE_LOCATION_EXTERIOR_RIGHT)) {
+        return false;
+    }
+
+    return true;
+}
+
+bool CameraService::checkPermission(const std::string& cameraId, const std::string& permission,
+        const AttributionSourceState& attributionSource, const std::string& message,
+        int32_t attributedOpCode) const{
+    if (isAutomotivePrivilegedClient(attributionSource.uid)) {
+        // If cameraId is empty, then it means that this check is not used for the
+        // purpose of accessing a specific camera, hence grant permission just
+        // based on uid to the automotive privileged client.
+        if (cameraId.empty())
+            return true;
+        // If this call is used for accessing a specific camera then cam_id must be provided.
+        // In that case, only pre-grants the permission for accessing the exterior system only
+        // camera.
+        return isAutomotiveExteriorSystemCamera(cameraId);
+    }
+
     permission::PermissionChecker permissionChecker;
+    return permissionChecker.checkPermissionForPreflight(toString16(permission), attributionSource,
+            toString16(message), attributedOpCode)
+            != permission::PermissionChecker::PERMISSION_HARD_DENIED;
+}
+
+bool CameraService::hasPermissionsForSystemCamera(const std::string& cameraId, int callingPid,
+        int callingUid) const{
     AttributionSourceState attributionSource{};
     attributionSource.pid = callingPid;
     attributionSource.uid = callingUid;
-    bool checkPermissionForSystemCamera = permissionChecker.checkPermissionForPreflight(
-            sSystemCameraPermission, attributionSource, String16(), AppOpsManager::OP_NONE)
-            != permission::PermissionChecker::PERMISSION_HARD_DENIED;
-    bool checkPermissionForCamera = permissionChecker.checkPermissionForPreflight(
-            sCameraPermission, attributionSource, String16(), AppOpsManager::OP_NONE)
-            != permission::PermissionChecker::PERMISSION_HARD_DENIED;
+    bool checkPermissionForSystemCamera = checkPermission(cameraId,
+            sSystemCameraPermission, attributionSource, std::string(), AppOpsManager::OP_NONE);
+    bool checkPermissionForCamera = checkPermission(cameraId,
+            sCameraPermission, attributionSource, std::string(), AppOpsManager::OP_NONE);
     return checkPermissionForSystemCamera && checkPermissionForCamera;
 }
 
@@ -719,7 +787,7 @@
     ATRACE_CALL();
     Mutex::Autolock l(mServiceLock);
     bool hasSystemCameraPermissions =
-            hasPermissionsForSystemCamera(CameraThreadState::getCallingPid(),
+            hasPermissionsForSystemCamera(std::string(), CameraThreadState::getCallingPid(),
                     CameraThreadState::getCallingUid());
     switch (type) {
         case CAMERA_TYPE_BACKWARD_COMPATIBLE:
@@ -750,19 +818,18 @@
     ATRACE_CALL();
     Mutex::Autolock l(mServiceLock);
     std::string cameraIdStr = cameraIdIntToStrLocked(cameraId);
-    if (shouldRejectSystemCameraConnection(String8(cameraIdStr.c_str()))) {
+    if (shouldRejectSystemCameraConnection(cameraIdStr)) {
         return STATUS_ERROR_FMT(ERROR_INVALID_OPERATION, "Unable to retrieve camera"
                 "characteristics for system only device %s: ", cameraIdStr.c_str());
     }
 
     if (!mInitialized) {
-        logServiceError(String8::format("Camera subsystem is not available"),ERROR_DISCONNECTED);
+        logServiceError("Camera subsystem is not available", ERROR_DISCONNECTED);
         return STATUS_ERROR(ERROR_DISCONNECTED,
                 "Camera subsystem is not available");
     }
-    bool hasSystemCameraPermissions =
-            hasPermissionsForSystemCamera(CameraThreadState::getCallingPid(),
-                    CameraThreadState::getCallingUid());
+    bool hasSystemCameraPermissions = hasPermissionsForSystemCamera(std::to_string(cameraId),
+            CameraThreadState::getCallingPid(), CameraThreadState::getCallingUid());
     int cameraIdBound = mNumberOfCamerasWithoutSystemCamera;
     if (hasSystemCameraPermissions) {
         cameraIdBound = mNumberOfCameras;
@@ -775,13 +842,13 @@
     Status ret = Status::ok();
     int portraitRotation;
     status_t err = mCameraProviderManager->getCameraInfo(
-            cameraIdStr.c_str(), overrideToPortrait, &portraitRotation, cameraInfo);
+            cameraIdStr, overrideToPortrait, &portraitRotation, cameraInfo);
     if (err != OK) {
         ret = STATUS_ERROR_FMT(ERROR_INVALID_OPERATION,
                 "Error retrieving camera info from device %d: %s (%d)", cameraId,
                 strerror(-err), err);
-        logServiceError(String8::format("Error retrieving camera info from device %d",cameraId),
-            ERROR_INVALID_OPERATION);
+        logServiceError(std::string("Error retrieving camera info from device ")
+                + std::to_string(cameraId), ERROR_INVALID_OPERATION);
     }
 
     return ret;
@@ -791,13 +858,12 @@
     const std::vector<std::string> *deviceIds = &mNormalDeviceIdsWithoutSystemCamera;
     auto callingPid = CameraThreadState::getCallingPid();
     auto callingUid = CameraThreadState::getCallingUid();
-    permission::PermissionChecker permissionChecker;
     AttributionSourceState attributionSource{};
     attributionSource.pid = callingPid;
     attributionSource.uid = callingUid;
-    bool checkPermissionForSystemCamera = permissionChecker.checkPermissionForPreflight(
-                sSystemCameraPermission, attributionSource, String16(), AppOpsManager::OP_NONE)
-                != permission::PermissionChecker::PERMISSION_HARD_DENIED;
+    bool checkPermissionForSystemCamera = checkPermission(std::to_string(cameraIdInt),
+                sSystemCameraPermission, attributionSource, std::string(),
+                AppOpsManager::OP_NONE);
     if (checkPermissionForSystemCamera || getpid() == callingPid) {
         deviceIds = &mNormalDeviceIds;
     }
@@ -810,12 +876,12 @@
     return (*deviceIds)[cameraIdInt];
 }
 
-String8 CameraService::cameraIdIntToStr(int cameraIdInt) {
+std::string CameraService::cameraIdIntToStr(int cameraIdInt) {
     Mutex::Autolock lock(mServiceLock);
-    return String8(cameraIdIntToStrLocked(cameraIdInt).c_str());
+    return cameraIdIntToStrLocked(cameraIdInt);
 }
 
-Status CameraService::getCameraCharacteristics(const String16& cameraId,
+Status CameraService::getCameraCharacteristics(const std::string& cameraId,
         int targetSdkVersion, bool overrideToPortrait, CameraMetadata* cameraInfo) {
     ATRACE_CALL();
     if (!cameraInfo) {
@@ -825,43 +891,41 @@
 
     if (!mInitialized) {
         ALOGE("%s: Camera HAL couldn't be initialized", __FUNCTION__);
-        logServiceError(String8::format("Camera subsystem is not available"),ERROR_DISCONNECTED);
+        logServiceError("Camera subsystem is not available", ERROR_DISCONNECTED);
         return STATUS_ERROR(ERROR_DISCONNECTED,
                 "Camera subsystem is not available");;
     }
 
-    if (shouldRejectSystemCameraConnection(String8(cameraId))) {
+    if (shouldRejectSystemCameraConnection(cameraId)) {
         return STATUS_ERROR_FMT(ERROR_INVALID_OPERATION, "Unable to retrieve camera"
-                "characteristics for system only device %s: ", String8(cameraId).string());
+                "characteristics for system only device %s: ", cameraId.c_str());
     }
 
     Status ret{};
 
-
-    std::string cameraIdStr = String8(cameraId).string();
     bool overrideForPerfClass =
             SessionConfigurationUtils::targetPerfClassPrimaryCamera(mPerfClassPrimaryCameraIds,
-                    cameraIdStr, targetSdkVersion);
+                    cameraId, targetSdkVersion);
     status_t res = mCameraProviderManager->getCameraCharacteristics(
-            cameraIdStr, overrideForPerfClass, cameraInfo, overrideToPortrait);
+            cameraId, overrideForPerfClass, cameraInfo, overrideToPortrait);
     if (res != OK) {
         if (res == NAME_NOT_FOUND) {
             return STATUS_ERROR_FMT(ERROR_ILLEGAL_ARGUMENT, "Unable to retrieve camera "
-                    "characteristics for unknown device %s: %s (%d)", String8(cameraId).string(),
+                    "characteristics for unknown device %s: %s (%d)", cameraId.c_str(),
                     strerror(-res), res);
         } else {
-            logServiceError(String8::format("Unable to retrieve camera characteristics for "
-            "device %s.", String8(cameraId).string()),ERROR_INVALID_OPERATION);
+            logServiceError(fmt::sprintf("Unable to retrieve camera characteristics for device %s.",
+                    cameraId.c_str()), ERROR_INVALID_OPERATION);
             return STATUS_ERROR_FMT(ERROR_INVALID_OPERATION, "Unable to retrieve camera "
-                    "characteristics for device %s: %s (%d)", String8(cameraId).string(),
+                    "characteristics for device %s: %s (%d)", cameraId.c_str(),
                     strerror(-res), res);
         }
     }
     SystemCameraKind deviceKind = SystemCameraKind::PUBLIC;
-    if (getSystemCameraKind(String8(cameraId), &deviceKind) != OK) {
-        ALOGE("%s: Invalid camera id %s, skipping", __FUNCTION__, String8(cameraId).string());
+    if (getSystemCameraKind(cameraId, &deviceKind) != OK) {
+        ALOGE("%s: Invalid camera id %s, skipping", __FUNCTION__, cameraId.c_str());
         return STATUS_ERROR_FMT(ERROR_INVALID_OPERATION, "Unable to retrieve camera kind "
-                "for device %s", String8(cameraId).string());
+                "for device %s", cameraId.c_str());
     }
     int callingPid = CameraThreadState::getCallingPid();
     int callingUid = CameraThreadState::getCallingUid();
@@ -869,24 +933,22 @@
     // 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.
-    permission::PermissionChecker permissionChecker;
     AttributionSourceState attributionSource{};
     attributionSource.pid = callingPid;
     attributionSource.uid = callingUid;
-    bool checkPermissionForCamera = permissionChecker.checkPermissionForPreflight(
-                sCameraPermission, attributionSource, String16(), AppOpsManager::OP_NONE)
-                != permission::PermissionChecker::PERMISSION_HARD_DENIED;
+    bool checkPermissionForCamera = checkPermission(cameraId, sCameraPermission,
+            attributionSource, std::string(), AppOpsManager::OP_NONE);
     if ((callingPid != getpid()) &&
             (deviceKind != SystemCameraKind::SYSTEM_ONLY_CAMERA) &&
             !checkPermissionForCamera) {
         res = cameraInfo->removePermissionEntries(
-                mCameraProviderManager->getProviderTagIdLocked(String8(cameraId).string()),
+                mCameraProviderManager->getProviderTagIdLocked(cameraId),
                 &tagsRemoved);
         if (res != OK) {
             cameraInfo->clear();
             return STATUS_ERROR_FMT(ERROR_INVALID_OPERATION, "Failed to remove camera"
                     " characteristics needing camera permission for device %s: %s (%d)",
-                    String8(cameraId).string(), strerror(-res), res);
+                    cameraId.c_str(), strerror(-res), res);
         }
     }
 
@@ -896,7 +958,7 @@
         if (res != OK) {
             cameraInfo->clear();
             return STATUS_ERROR_FMT(ERROR_INVALID_OPERATION, "Failed to insert camera "
-                    "keys needing permission for device %s: %s (%d)", String8(cameraId).string(),
+                    "keys needing permission for device %s: %s (%d)", cameraId.c_str(),
                     strerror(-res), res);
         }
     }
@@ -904,7 +966,7 @@
     return ret;
 }
 
-Status CameraService::getTorchStrengthLevel(const String16& cameraId,
+Status CameraService::getTorchStrengthLevel(const std::string& cameraId,
         int32_t* torchStrength) {
     ATRACE_CALL();
     Mutex::Autolock l(mServiceLock);
@@ -918,22 +980,21 @@
         return STATUS_ERROR(ERROR_ILLEGAL_ARGUMENT, "Strength level should not be null.");
     }
 
-    status_t res = mCameraProviderManager->getTorchStrengthLevel(String8(cameraId).string(),
-        torchStrength);
+    status_t res = mCameraProviderManager->getTorchStrengthLevel(cameraId, torchStrength);
     if (res != OK) {
         return STATUS_ERROR_FMT(ERROR_INVALID_OPERATION, "Unable to retrieve torch "
-            "strength level for device %s: %s (%d)", String8(cameraId).string(),
+            "strength level for device %s: %s (%d)", cameraId.c_str(),
             strerror(-res), res);
     }
     ALOGI("%s: Torch strength level is: %d", __FUNCTION__, *torchStrength);
     return Status::ok();
 }
 
-String8 CameraService::getFormattedCurrentTime() {
+std::string CameraService::getFormattedCurrentTime() {
     time_t now = time(nullptr);
     char formattedTime[64];
     strftime(formattedTime, sizeof(formattedTime), "%m-%d %H:%M:%S", localtime(&now));
-    return String8(formattedTime);
+    return std::string(formattedTime);
 }
 
 Status CameraService::getCameraVendorTagDescriptor(
@@ -971,7 +1032,7 @@
     BasicClient::BasicClient::sCameraService = nullptr;
 }
 
-std::pair<int, IPCTransport> CameraService::getDeviceVersion(const String8& cameraId,
+std::pair<int, IPCTransport> CameraService::getDeviceVersion(const std::string& cameraId,
         bool overrideToPortrait, int* portraitRotation, int* facing, int* orientation) {
     ATRACE_CALL();
 
@@ -980,18 +1041,17 @@
     status_t res;
     hardware::hidl_version maxVersion{0,0};
     IPCTransport transport = IPCTransport::INVALID;
-    res = mCameraProviderManager->getHighestSupportedVersion(cameraId.string(),
-            &maxVersion, &transport);
+    res = mCameraProviderManager->getHighestSupportedVersion(cameraId, &maxVersion, &transport);
     if (res != OK || transport == IPCTransport::INVALID) {
         ALOGE("%s: Unable to get highest supported version for camera id %s", __FUNCTION__,
-                cameraId.string());
+                cameraId.c_str());
         return std::make_pair(-1, IPCTransport::INVALID) ;
     }
     deviceVersion = HARDWARE_DEVICE_API_VERSION(maxVersion.get_major(), maxVersion.get_minor());
 
     hardware::CameraInfo info;
     if (facing) {
-        res = mCameraProviderManager->getCameraInfo(cameraId.string(), overrideToPortrait,
+        res = mCameraProviderManager->getCameraInfo(cameraId, overrideToPortrait,
                 portraitRotation, &info);
         if (res != OK) {
             return std::make_pair(-1, IPCTransport::INVALID);
@@ -1023,8 +1083,8 @@
 }
 
 Status CameraService::makeClient(const sp<CameraService>& cameraService,
-        const sp<IInterface>& cameraCb, const String16& packageName, bool systemNativeClient,
-        const std::optional<String16>& featureId,  const String8& cameraId,
+        const sp<IInterface>& cameraCb, const std::string& packageName, bool systemNativeClient,
+        const std::optional<std::string>& featureId,  const std::string& cameraId,
         int api1CameraId, int facing, int sensorOrientation, int clientPid, uid_t clientUid,
         int servicePid, std::pair<int, IPCTransport> deviceVersionAndTransport,
         apiLevel effectiveApiLevel, bool overrideForPerfClass, bool overrideToPortrait,
@@ -1038,7 +1098,7 @@
                 ALOGE("Camera using old HAL version: %d", deviceVersion);
                 return STATUS_ERROR_FMT(ERROR_DEPRECATED_HAL,
                         "Camera device \"%s\" HAL version %d no longer supported",
-                        cameraId.string(), deviceVersion);
+                        cameraId.c_str(), deviceVersion);
                 break;
             case CAMERA_DEVICE_API_VERSION_3_0:
             case CAMERA_DEVICE_API_VERSION_3_1:
@@ -1054,13 +1114,14 @@
                 ALOGE("Unknown camera device HAL version: %d", deviceVersion);
                 return STATUS_ERROR_FMT(ERROR_INVALID_OPERATION,
                         "Camera device \"%s\" has unknown HAL version %d",
-                        cameraId.string(), deviceVersion);
+                        cameraId.c_str(), deviceVersion);
         }
     }
     if (effectiveApiLevel == API_1) { // Camera1 API route
         sp<ICameraClient> tmp = static_cast<ICameraClient*>(cameraCb.get());
         *client = new Camera2Client(cameraService, tmp, cameraService->mCameraServiceProxyWrapper,
-                packageName, featureId, cameraId, api1CameraId, facing, sensorOrientation,
+                packageName, featureId, cameraId,
+                api1CameraId, facing, sensorOrientation,
                 clientPid, clientUid, servicePid, overrideForPerfClass, overrideToPortrait,
                 forceSlowJpegMode);
         ALOGI("%s: Camera1 API (legacy), override to portrait %d, forceSlowJpegMode %d",
@@ -1077,18 +1138,18 @@
     return Status::ok();
 }
 
-String8 CameraService::toString(std::set<userid_t> intSet) {
-    String8 s("");
+std::string CameraService::toString(std::set<userid_t> intSet) {
+    std::ostringstream s;
     bool first = true;
     for (userid_t i : intSet) {
         if (first) {
-            s.appendFormat("%d", i);
+            s << std::to_string(i);
             first = false;
         } else {
-            s.appendFormat(", %d", i);
+            s << ", " << std::to_string(i);
         }
     }
-    return s;
+    return std::move(s.str());
 }
 
 int32_t CameraService::mapToInterface(TorchModeStatus status) {
@@ -1154,13 +1215,12 @@
 Status CameraService::initializeShimMetadata(int cameraId) {
     int uid = CameraThreadState::getCallingUid();
 
-    String16 internalPackageName("cameraserver");
-    String8 id = String8::format("%d", cameraId);
+    std::string cameraIdStr = std::to_string(cameraId);
     Status ret = Status::ok();
     sp<Client> tmp = nullptr;
     if (!(ret = connectHelper<ICameraClient,Client>(
-            sp<ICameraClient>{nullptr}, id, cameraId,
-            internalPackageName, /*systemNativeClient*/ false, {}, uid, USE_CALLING_PID,
+            sp<ICameraClient>{nullptr}, cameraIdStr, cameraId,
+            kServiceName, /*systemNativeClient*/ false, {}, uid, USE_CALLING_PID,
             API_1, /*shimUpdateOnly*/ true, /*oomScoreOffset*/ 0,
             /*targetSdkVersion*/ __ANDROID_API_FUTURE__, /*overrideToPortrait*/ true,
             /*forceSlowJpegMode*/false, /*out*/ tmp)
@@ -1183,17 +1243,17 @@
         return STATUS_ERROR(ERROR_ILLEGAL_ARGUMENT, "Parameters must not be null");
     }
 
-    String8 id = String8::format("%d", cameraId);
+    std::string cameraIdStr = std::to_string(cameraId);
 
     // Check if we already have parameters
     {
         // Scope for service lock
         Mutex::Autolock lock(mServiceLock);
-        auto cameraState = getCameraState(id);
+        auto cameraState = getCameraState(cameraIdStr);
         if (cameraState == nullptr) {
-            ALOGE("%s: Invalid camera ID: %s", __FUNCTION__, id.string());
+            ALOGE("%s: Invalid camera ID: %s", __FUNCTION__, cameraIdStr.c_str());
             return STATUS_ERROR_FMT(ERROR_ILLEGAL_ARGUMENT,
-                    "Invalid camera ID: %s", id.string());
+                    "Invalid camera ID: %s", cameraIdStr.c_str());
         }
         CameraParameters p = cameraState->getShimParams();
         if (!p.isEmpty()) {
@@ -1214,11 +1274,11 @@
     {
         // Scope for service lock
         Mutex::Autolock lock(mServiceLock);
-        auto cameraState = getCameraState(id);
+        auto cameraState = getCameraState(cameraIdStr);
         if (cameraState == nullptr) {
-            ALOGE("%s: Invalid camera ID: %s", __FUNCTION__, id.string());
+            ALOGE("%s: Invalid camera ID: %s", __FUNCTION__, cameraIdStr.c_str());
             return STATUS_ERROR_FMT(ERROR_ILLEGAL_ARGUMENT,
-                    "Invalid camera ID: %s", id.string());
+                    "Invalid camera ID: %s", cameraIdStr.c_str());
         }
         CameraParameters p = cameraState->getShimParams();
         if (!p.isEmpty()) {
@@ -1244,12 +1304,13 @@
     }
 }
 
-static status_t getUidForPackage(String16 packageName, int userId, /*inout*/uid_t& uid, int err) {
+static status_t getUidForPackage(const std::string &packageName, int userId, /*inout*/uid_t& uid,
+        int err) {
     PermissionController pc;
-    uid = pc.getPackageUid(packageName, 0);
+    uid = pc.getPackageUid(toString16(packageName), 0);
     if (uid <= 0) {
-        ALOGE("Unknown package: '%s'", String8(packageName).string());
-        dprintf(err, "Unknown package: '%s'\n", String8(packageName).string());
+        ALOGE("Unknown package: '%s'", packageName.c_str());
+        dprintf(err, "Unknown package: '%s'\n", packageName.c_str());
         return BAD_VALUE;
     }
 
@@ -1263,8 +1324,8 @@
     return NO_ERROR;
 }
 
-Status CameraService::validateConnectLocked(const String8& cameraId,
-        const String8& clientName8, /*inout*/int& clientUid, /*inout*/int& clientPid,
+Status CameraService::validateConnectLocked(const std::string& cameraId,
+        const std::string& clientName8, /*inout*/int& clientUid, /*inout*/int& clientPid,
         /*out*/int& originalClientPid) const {
 
 #ifdef __BRILLO__
@@ -1286,14 +1347,14 @@
         ALOGE("CameraService::connect X (PID %d) rejected (camera HAL module not loaded)",
                 callingPid);
         return STATUS_ERROR_FMT(ERROR_DISCONNECTED,
-                "No camera HAL module available to open camera device \"%s\"", cameraId.string());
+                "No camera HAL module available to open camera device \"%s\"", cameraId.c_str());
     }
 
     if (getCameraState(cameraId) == nullptr) {
         ALOGE("CameraService::connect X (PID %d) rejected (invalid camera ID %s)", callingPid,
-                cameraId.string());
+                cameraId.c_str());
         return STATUS_ERROR_FMT(ERROR_DISCONNECTED,
-                "No camera device with ID \"%s\" available", cameraId.string());
+                "No camera device with ID \"%s\" available", cameraId.c_str());
     }
 
     status_t err = checkIfDeviceIsUsable(cameraId);
@@ -1302,19 +1363,18 @@
             case -ENODEV:
             case -EBUSY:
                 return STATUS_ERROR_FMT(ERROR_DISCONNECTED,
-                        "No camera device with ID \"%s\" currently available", cameraId.string());
+                        "No camera device with ID \"%s\" currently available", cameraId.c_str());
             default:
                 return STATUS_ERROR_FMT(ERROR_INVALID_OPERATION,
-                        "Unknown error connecting to ID \"%s\"", cameraId.string());
+                        "Unknown error connecting to ID \"%s\"", cameraId.c_str());
         }
     }
     return Status::ok();
 }
 
-Status CameraService::validateClientPermissionsLocked(const String8& cameraId,
-        const String8& clientName8, int& clientUid, int& clientPid,
+Status CameraService::validateClientPermissionsLocked(const std::string& cameraId,
+        const std::string& clientName, int& clientUid, int& clientPid,
         /*out*/int& originalClientPid) const {
-    permission::PermissionChecker permissionChecker;
     AttributionSourceState attributionSource{};
 
     int callingPid = CameraThreadState::getCallingPid();
@@ -1329,8 +1389,8 @@
         return STATUS_ERROR_FMT(ERROR_PERMISSION_DENIED,
                 "Untrusted caller (calling PID %d, UID %d) trying to "
                 "forward camera access to camera %s for client %s (PID %d, UID %d)",
-                callingPid, callingUid, cameraId.string(),
-                clientName8.string(), clientUid, clientPid);
+                callingPid, callingUid, cameraId.c_str(),
+                clientName.c_str(), clientUid, clientPid);
     }
 
     // Check if we can trust clientPid
@@ -1342,21 +1402,21 @@
         return STATUS_ERROR_FMT(ERROR_PERMISSION_DENIED,
                 "Untrusted caller (calling PID %d, UID %d) trying to "
                 "forward camera access to camera %s for client %s (PID %d, UID %d)",
-                callingPid, callingUid, cameraId.string(),
-                clientName8.string(), clientUid, clientPid);
+                callingPid, callingUid, cameraId.c_str(),
+                clientName.c_str(), clientUid, clientPid);
     }
 
     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());
+                                "available", cameraId.c_str());
     }
     SystemCameraKind deviceKind = SystemCameraKind::PUBLIC;
     if (getSystemCameraKind(cameraId, &deviceKind) != OK) {
-        ALOGE("%s: Invalid camera id %s, skipping", __FUNCTION__, cameraId.string());
+        ALOGE("%s: Invalid camera id %s, skipping", __FUNCTION__, cameraId.c_str());
         return STATUS_ERROR_FMT(ERROR_ILLEGAL_ARGUMENT, "No camera device with ID \"%s\""
-                "found while trying to query device kind", cameraId.string());
+                "found while trying to query device kind", cameraId.c_str());
 
     }
 
@@ -1365,36 +1425,40 @@
     // android.permission.SYSTEM_CAMERA for system only camera devices).
     attributionSource.pid = clientPid;
     attributionSource.uid = clientUid;
-    attributionSource.packageName = clientName8;
-    bool checkPermissionForCamera = permissionChecker.checkPermissionForPreflight(
-            sCameraPermission, attributionSource, String16(), AppOpsManager::OP_NONE)
-            != permission::PermissionChecker::PERMISSION_HARD_DENIED;
+    attributionSource.packageName = clientName;
+    bool checkPermissionForCamera = checkPermission(cameraId, sCameraPermission, attributionSource,
+            std::string(), AppOpsManager::OP_NONE);
     if (callingPid != getpid() &&
                 (deviceKind != SystemCameraKind::SYSTEM_ONLY_CAMERA) && !checkPermissionForCamera) {
         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",
-                clientName8.string(), clientUid, clientPid, cameraId.string());
+                clientName.c_str(), clientUid, clientPid, cameraId.c_str());
     }
 
     // Make sure the UID is in an active state to use the camera
-    if (!mUidPolicy->isUidActive(callingUid, String16(clientName8))) {
+    if (!mUidPolicy->isUidActive(callingUid, clientName)) {
         int32_t procState = mUidPolicy->getProcState(callingUid);
         ALOGE("Access Denial: can't use the camera from an idle UID pid=%d, uid=%d",
             clientPid, clientUid);
         return STATUS_ERROR_FMT(ERROR_DISABLED,
                 "Caller \"%s\" (PID %d, UID %d) cannot open camera \"%s\" from background ("
                 "calling UID %d proc state %" PRId32 ")",
-                clientName8.string(), clientUid, clientPid, cameraId.string(),
+                clientName.c_str(), clientUid, clientPid, cameraId.c_str(),
                 callingUid, procState);
     }
 
-    // If sensor privacy is enabled then prevent access to the camera
-    if (mSensorPrivacyPolicy->isSensorPrivacyEnabled()) {
+
+    // Automotive privileged client AID_AUTOMOTIVE_EVS using exterior system camera for use cases
+    // such as rear view and surround view cannot be disabled and are exempt from sensor privacy
+    // policy. In all other cases,if sensor privacy is enabled then prevent access to the camera.
+    if ((!isAutomotivePrivilegedClient(callingUid) ||
+            !isAutomotiveExteriorSystemCamera(cameraId)) &&
+            mSensorPrivacyPolicy->isSensorPrivacyEnabled()) {
         ALOGE("Access Denial: cannot use the camera when sensor privacy is enabled");
         return STATUS_ERROR_FMT(ERROR_DISABLED,
                 "Caller \"%s\" (PID %d, UID %d) cannot open camera \"%s\" when sensor privacy "
-                "is enabled", clientName8.string(), clientUid, clientPid, cameraId.string());
+                "is enabled", clientName.c_str(), clientUid, clientPid, cameraId.c_str());
     }
 
     // Only use passed in clientPid to check permission. Use calling PID as the client PID that's
@@ -1410,32 +1474,32 @@
             (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,
-                toString(mAllowedUsers).string());
+                toString(mAllowedUsers).c_str());
         return STATUS_ERROR_FMT(ERROR_PERMISSION_DENIED,
                 "Callers from device user %d are not currently allowed to connect to camera \"%s\"",
-                clientUserId, cameraId.string());
+                clientUserId, cameraId.c_str());
     }
 
     return Status::ok();
 }
 
-status_t CameraService::checkIfDeviceIsUsable(const String8& cameraId) const {
+status_t CameraService::checkIfDeviceIsUsable(const std::string& cameraId) const {
     auto cameraState = getCameraState(cameraId);
     int callingPid = CameraThreadState::getCallingPid();
     if (cameraState == nullptr) {
         ALOGE("CameraService::connect X (PID %d) rejected (invalid camera ID %s)", callingPid,
-                cameraId.string());
+                cameraId.c_str());
         return -ENODEV;
     }
 
     StatusInternal currentStatus = cameraState->getStatus();
     if (currentStatus == StatusInternal::NOT_PRESENT) {
         ALOGE("CameraService::connect X (PID %d) rejected (camera %s is not connected)",
-                callingPid, cameraId.string());
+                callingPid, cameraId.c_str());
         return -ENODEV;
     } else if (currentStatus == StatusInternal::ENUMERATING) {
         ALOGE("CameraService::connect X (PID %d) rejected, (camera %s is initializing)",
-                callingPid, cameraId.string());
+                callingPid, cameraId.c_str());
         return -EBUSY;
     }
 
@@ -1452,13 +1516,13 @@
     auto evicted = mActiveClientManager.addAndEvict(clientDescriptor);
 
     logConnected(desc->getKey(), static_cast<int>(desc->getOwnerId()),
-            String8(client->getPackageName()));
+            client->getPackageName());
 
     if (evicted.size() > 0) {
         // This should never happen - clients should already have been removed in disconnect
         for (auto& i : evicted) {
             ALOGE("%s: Invalid state: Client for camera %s was not removed in disconnect",
-                    __FUNCTION__, i->getKey().string());
+                    __FUNCTION__, i->getKey().c_str());
         }
 
         LOG_ALWAYS_FATAL("%s: Invalid state for CameraService, clients not evicted properly",
@@ -1476,12 +1540,12 @@
     }
 }
 
-status_t CameraService::handleEvictionsLocked(const String8& cameraId, int clientPid,
-        apiLevel effectiveApiLevel, const sp<IBinder>& remoteCallback, const String8& packageName,
-        int oomScoreOffset, bool systemNativeClient,
+status_t CameraService::handleEvictionsLocked(const std::string& cameraId, int clientPid,
+        apiLevel effectiveApiLevel, const sp<IBinder>& remoteCallback,
+        const std::string& packageName, int oomScoreOffset, bool systemNativeClient,
         /*out*/
         sp<BasicClient>* client,
-        std::shared_ptr<resource_policy::ClientDescriptor<String8, sp<BasicClient>>>* partial) {
+        std::shared_ptr<resource_policy::ClientDescriptor<std::string, sp<BasicClient>>>* partial) {
     ATRACE_CALL();
     status_t ret = NO_ERROR;
     std::vector<DescriptorPtr> evictedClients;
@@ -1508,52 +1572,66 @@
             }
         }
 
-        // Get current active client PIDs
-        std::vector<int> ownerPids(mActiveClientManager.getAllOwners());
-        ownerPids.push_back(clientPid);
-
-        std::vector<int> priorityScores(ownerPids.size());
-        std::vector<int> states(ownerPids.size());
-
-        // Get priority scores of all active PIDs
-        status_t err = ProcessInfoService::getProcessStatesScoresFromPids(
-                ownerPids.size(), &ownerPids[0], /*out*/&states[0],
-                /*out*/&priorityScores[0]);
-        if (err != OK) {
-            ALOGE("%s: Priority score query failed: %d",
-                  __FUNCTION__, err);
-            return err;
-        }
-
-        // Update all active clients' priorities
-        std::map<int,resource_policy::ClientPriority> pidToPriorityMap;
-        for (size_t i = 0; i < ownerPids.size() - 1; i++) {
-            pidToPriorityMap.emplace(ownerPids[i],
-                    resource_policy::ClientPriority(priorityScores[i], states[i],
-                            /* isVendorClient won't get copied over*/ false,
-                            /* oomScoreOffset won't get copied over*/ 0));
-        }
-        mActiveClientManager.updatePriorities(pidToPriorityMap);
-
         // Get state for the given cameraId
         auto state = getCameraState(cameraId);
         if (state == nullptr) {
             ALOGE("CameraService::connect X (PID %d) rejected (no camera device with ID %s)",
-                clientPid, cameraId.string());
+                clientPid, cameraId.c_str());
             // Should never get here because validateConnectLocked should have errored out
             return BAD_VALUE;
         }
 
-        int32_t actualScore = priorityScores[priorityScores.size() - 1];
-        int32_t actualState = states[states.size() - 1];
+        sp<IServiceManager> sm = defaultServiceManager();
+        sp<IBinder> binder = sm->checkService(String16(kProcessInfoServiceName));
+        if (!binder && isAutomotivePrivilegedClient(CameraThreadState::getCallingUid())) {
+            // If processinfo service is not available and the client is automotive privileged
+            // client used for safety critical uses cases such as rear-view and surround-view which
+            // needs to be available before android boot completes, then use the hardcoded values
+            // for the process state and priority score. As this scenario is before android system
+            // services are up and client is native client, hence using NATIVE_ADJ as the priority
+            // score and state as PROCESS_STATE_BOUND_TOP as such automotive apps need to be
+            // visible on the top.
+            clientDescriptor = CameraClientManager::makeClientDescriptor(cameraId,
+                    sp<BasicClient>{nullptr}, static_cast<int32_t>(state->getCost()),
+                    state->getConflicting(), resource_policy::NATIVE_ADJ, clientPid,
+                    ActivityManager::PROCESS_STATE_BOUND_TOP, oomScoreOffset, systemNativeClient);
+        } else {
+            // Get current active client PIDs
+            std::vector<int> ownerPids(mActiveClientManager.getAllOwners());
+            ownerPids.push_back(clientPid);
 
-        // Make descriptor for incoming client. We store the oomScoreOffset
-        // since we might need it later on new handleEvictionsLocked and
-        // ProcessInfoService would not take that into account.
-        clientDescriptor = CameraClientManager::makeClientDescriptor(cameraId,
-                sp<BasicClient>{nullptr}, static_cast<int32_t>(state->getCost()),
-                state->getConflicting(), actualScore, clientPid, actualState,
-                oomScoreOffset, systemNativeClient);
+            std::vector<int> priorityScores(ownerPids.size());
+            std::vector<int> states(ownerPids.size());
+
+            // Get priority scores of all active PIDs
+            status_t err = ProcessInfoService::getProcessStatesScoresFromPids(ownerPids.size(),
+                    &ownerPids[0], /*out*/&states[0], /*out*/&priorityScores[0]);
+            if (err != OK) {
+                ALOGE("%s: Priority score query failed: %d", __FUNCTION__, err);
+                return err;
+            }
+
+            // Update all active clients' priorities
+            std::map<int,resource_policy::ClientPriority> pidToPriorityMap;
+            for (size_t i = 0; i < ownerPids.size() - 1; i++) {
+                pidToPriorityMap.emplace(ownerPids[i],
+                        resource_policy::ClientPriority(priorityScores[i], states[i],
+                        /* isVendorClient won't get copied over*/ false,
+                        /* oomScoreOffset won't get copied over*/ 0));
+            }
+            mActiveClientManager.updatePriorities(pidToPriorityMap);
+
+            int32_t actualScore = priorityScores[priorityScores.size() - 1];
+            int32_t actualState = states[states.size() - 1];
+
+            // Make descriptor for incoming client. We store the oomScoreOffset
+            // since we might need it later on new handleEvictionsLocked and
+            // ProcessInfoService would not take that into account.
+            clientDescriptor = CameraClientManager::makeClientDescriptor(cameraId,
+                    sp<BasicClient>{nullptr}, static_cast<int32_t>(state->getCost()),
+                    state->getConflicting(), actualScore, clientPid, actualState,
+                    oomScoreOffset, systemNativeClient);
+        }
 
         resource_policy::ClientPriority clientPriority = clientDescriptor->getPriority();
 
@@ -1567,25 +1645,25 @@
                     " priority).", clientPid);
 
             sp<BasicClient> clientSp = clientDescriptor->getValue();
-            String8 curTime = getFormattedCurrentTime();
+            std::string curTime = getFormattedCurrentTime();
             auto incompatibleClients =
                     mActiveClientManager.getIncompatibleClients(clientDescriptor);
 
-            String8 msg = String8::format("%s : DENIED connect device %s client for package %s "
-                    "(PID %d, score %d state %d) due to eviction policy", curTime.string(),
-                    cameraId.string(), packageName.string(), clientPid,
+            std::string msg = fmt::sprintf("%s : DENIED connect device %s client for package %s "
+                    "(PID %d, score %d state %d) due to eviction policy", curTime.c_str(),
+                    cameraId.c_str(), packageName.c_str(), clientPid,
                     clientPriority.getScore(), clientPriority.getState());
 
             for (auto& i : incompatibleClients) {
-                msg.appendFormat("\n   - Blocked by existing device %s client for package %s"
+                msg += fmt::sprintf("\n   - Blocked by existing device %s client for package %s"
                         "(PID %" PRId32 ", score %" PRId32 ", state %" PRId32 ")",
-                        i->getKey().string(),
-                        String8{i->getValue()->getPackageName()}.string(),
+                        i->getKey().c_str(),
+                        i->getValue()->getPackageName().c_str(),
                         i->getOwnerId(), i->getPriority().getScore(),
                         i->getPriority().getState());
                 ALOGE("   Conflicts with: Device %s, client package %s (PID %"
-                        PRId32 ", score %" PRId32 ", state %" PRId32 ")", i->getKey().string(),
-                        String8{i->getValue()->getPackageName()}.string(), i->getOwnerId(),
+                        PRId32 ", score %" PRId32 ", state %" PRId32 ")", i->getKey().c_str(),
+                        i->getValue()->getPackageName().c_str(), i->getOwnerId(),
                         i->getPriority().getScore(), i->getPriority().getState());
             }
 
@@ -1614,17 +1692,17 @@
             }
 
             ALOGE("CameraService::connect evicting conflicting client for camera ID %s",
-                    i->getKey().string());
+                    i->getKey().c_str());
             evictedClients.push_back(i);
 
             // Log the clients evicted
-            logEvent(String8::format("EVICT device %s client held by package %s (PID"
+            logEvent(fmt::sprintf("EVICT device %s client held by package %s (PID"
                     " %" PRId32 ", score %" PRId32 ", state %" PRId32 ")\n - Evicted by device %s client for"
                     " package %s (PID %d, score %" PRId32 ", state %" PRId32 ")",
-                    i->getKey().string(), String8{clientSp->getPackageName()}.string(),
+                    i->getKey().c_str(), clientSp->getPackageName().c_str(),
                     i->getOwnerId(), i->getPriority().getScore(),
-                    i->getPriority().getState(), cameraId.string(),
-                    packageName.string(), clientPid, clientPriority.getScore(),
+                    i->getPriority().getState(), cameraId.c_str(),
+                    packageName.c_str(), clientPid, clientPriority.getScore(),
                     clientPriority.getState()));
 
             // Notify the client of disconnection
@@ -1650,18 +1728,18 @@
 
     for (const auto& i : evictedClients) {
         ALOGV("%s: Waiting for disconnect to complete for client for device %s (PID %" PRId32 ")",
-                __FUNCTION__, i->getKey().string(), i->getOwnerId());
+                __FUNCTION__, i->getKey().c_str(), i->getOwnerId());
         ret = mActiveClientManager.waitUntilRemoved(i, DEFAULT_DISCONNECT_TIMEOUT_NS);
         if (ret == TIMED_OUT) {
             ALOGE("%s: Timed out waiting for client for device %s to disconnect, "
-                    "current clients:\n%s", __FUNCTION__, i->getKey().string(),
-                    mActiveClientManager.toString().string());
+                    "current clients:\n%s", __FUNCTION__, i->getKey().c_str(),
+                    mActiveClientManager.toString().c_str());
             return -EBUSY;
         }
         if (ret != NO_ERROR) {
             ALOGE("%s: Received error waiting for client for device %s to disconnect: %s (%d), "
-                    "current clients:\n%s", __FUNCTION__, i->getKey().string(), strerror(-ret),
-                    ret, mActiveClientManager.toString().string());
+                    "current clients:\n%s", __FUNCTION__, i->getKey().c_str(), strerror(-ret),
+                    ret, mActiveClientManager.toString().c_str());
             return ret;
         }
     }
@@ -1683,7 +1761,7 @@
 Status CameraService::connect(
         const sp<ICameraClient>& cameraClient,
         int api1CameraId,
-        const String16& clientPackageName,
+        const std::string& clientPackageName,
         int clientUid,
         int clientPid,
         int targetSdkVersion,
@@ -1695,16 +1773,16 @@
     ATRACE_CALL();
     Status ret = Status::ok();
 
-    String8 id = cameraIdIntToStr(api1CameraId);
+    std::string cameraIdStr = cameraIdIntToStr(api1CameraId);
     sp<Client> client = nullptr;
-    ret = connectHelper<ICameraClient,Client>(cameraClient, id, api1CameraId,
-            clientPackageName,/*systemNativeClient*/ false, {}, clientUid, clientPid, API_1,
+    ret = connectHelper<ICameraClient,Client>(cameraClient, cameraIdStr, api1CameraId,
+            clientPackageName, /*systemNativeClient*/ false, {}, clientUid, clientPid, API_1,
             /*shimUpdateOnly*/ false, /*oomScoreOffset*/ 0, targetSdkVersion,
             overrideToPortrait, forceSlowJpegMode, /*out*/client);
 
     if(!ret.isOk()) {
-        logRejected(id, CameraThreadState::getCallingPid(), String8(clientPackageName),
-                ret.toString8());
+        logRejected(cameraIdStr, CameraThreadState::getCallingPid(), clientPackageName,
+                toStdString(ret.toString8()));
         return ret;
     }
 
@@ -1729,13 +1807,13 @@
     //      have android.permission.SYSTEM_CAMERA permissions.
     if (!isVendorListener && (systemCameraKind == SystemCameraKind::HIDDEN_SECURE_CAMERA ||
             (systemCameraKind == SystemCameraKind::SYSTEM_ONLY_CAMERA &&
-            !hasPermissionsForSystemCamera(clientPid, clientUid)))) {
+            !hasPermissionsForSystemCamera(std::string(), clientPid, clientUid)))) {
         return true;
     }
     return false;
 }
 
-bool CameraService::shouldRejectSystemCameraConnection(const String8& cameraId) const {
+bool CameraService::shouldRejectSystemCameraConnection(const std::string& cameraId) const {
     // Rules for rejection:
     // 1) If cameraserver tries to access this camera device, accept the
     //    connection.
@@ -1769,7 +1847,7 @@
     //     characteristics) even if clients don't have android.permission.CAMERA. We do not want the
     //     same behavior for system camera devices.
     if (!systemClient && systemCameraKind == SystemCameraKind::SYSTEM_ONLY_CAMERA &&
-            !hasPermissionsForSystemCamera(cPid, cUid)) {
+            !hasPermissionsForSystemCamera(cameraId, cPid, cUid)) {
         ALOGW("Rejecting access to system only camera %s, inadequete permissions",
                 cameraId.c_str());
         return true;
@@ -1780,9 +1858,9 @@
 
 Status CameraService::connectDevice(
         const sp<hardware::camera2::ICameraDeviceCallbacks>& cameraCb,
-        const String16& cameraId,
-        const String16& clientPackageName,
-        const std::optional<String16>& clientFeatureId,
+        const std::string& cameraId,
+        const std::string& clientPackageName,
+        const std::optional<std::string>& clientFeatureId,
         int clientUid, int oomScoreOffset, int targetSdkVersion,
         bool overrideToPortrait,
         /*out*/
@@ -1790,25 +1868,24 @@
 
     ATRACE_CALL();
     Status ret = Status::ok();
-    String8 id = String8(cameraId);
     sp<CameraDeviceClient> client = nullptr;
-    String16 clientPackageNameAdj = clientPackageName;
+    std::string clientPackageNameAdj = clientPackageName;
     int callingPid = CameraThreadState::getCallingPid();
     bool systemNativeClient = false;
     if (doesClientHaveSystemUid() && (clientPackageNameAdj.size() == 0)) {
         std::string systemClient =
-                StringPrintf("client.pid<%d>", CameraThreadState::getCallingPid());
-        clientPackageNameAdj = String16(systemClient.c_str());
+                fmt::sprintf("client.pid<%d>", CameraThreadState::getCallingPid());
+        clientPackageNameAdj = systemClient;
         systemNativeClient = true;
     }
 
     if (oomScoreOffset < 0) {
-        String8 msg =
-                String8::format("Cannot increase the priority of a client %s pid %d for "
-                        "camera id %s", String8(clientPackageNameAdj).string(), callingPid,
-                        id.string());
-        ALOGE("%s: %s", __FUNCTION__, msg.string());
-        return STATUS_ERROR(ERROR_ILLEGAL_ARGUMENT, msg.string());
+        std::string msg =
+                fmt::sprintf("Cannot increase the priority of a client %s pid %d for "
+                        "camera id %s", clientPackageNameAdj.c_str(), callingPid,
+                        cameraId.c_str());
+        ALOGE("%s: %s", __FUNCTION__, msg.c_str());
+        return STATUS_ERROR(ERROR_ILLEGAL_ARGUMENT, msg.c_str());
     }
 
     userid_t clientUserId = multiuser_get_user_id(clientUid);
@@ -1817,33 +1894,35 @@
         clientUserId = multiuser_get_user_id(callingUid);
     }
 
-    if (mCameraServiceProxyWrapper->isCameraDisabled(clientUserId)) {
-        String8 msg =
-                String8::format("Camera disabled by device policy");
-        ALOGE("%s: %s", __FUNCTION__, msg.string());
-        return STATUS_ERROR(ERROR_DISABLED, msg.string());
+    // Automotive privileged client AID_AUTOMOTIVE_EVS using exterior system camera for use cases
+    // such as rear view and surround view cannot be disabled.
+    if ((!isAutomotivePrivilegedClient(callingUid) || !isAutomotiveExteriorSystemCamera(cameraId))
+            && mCameraServiceProxyWrapper->isCameraDisabled(clientUserId)) {
+        std::string msg = "Camera disabled by device policy";
+        ALOGE("%s: %s", __FUNCTION__, msg.c_str());
+        return STATUS_ERROR(ERROR_DISABLED, msg.c_str());
     }
 
     // enforce system camera permissions
-    if (oomScoreOffset > 0 &&
-            !hasPermissionsForSystemCamera(callingPid, CameraThreadState::getCallingUid()) &&
-            !isTrustedCallingUid(CameraThreadState::getCallingUid())) {
-        String8 msg =
-                String8::format("Cannot change the priority of a client %s pid %d for "
+    if (oomScoreOffset > 0
+            && !hasPermissionsForSystemCamera(cameraId, callingPid,
+                    CameraThreadState::getCallingUid())
+            && !isTrustedCallingUid(CameraThreadState::getCallingUid())) {
+        std::string msg = fmt::sprintf("Cannot change the priority of a client %s pid %d for "
                         "camera id %s without SYSTEM_CAMERA permissions",
-                        String8(clientPackageNameAdj).string(), callingPid, id.string());
-        ALOGE("%s: %s", __FUNCTION__, msg.string());
-        return STATUS_ERROR(ERROR_PERMISSION_DENIED, msg.string());
+                        clientPackageNameAdj.c_str(), callingPid, cameraId.c_str());
+        ALOGE("%s: %s", __FUNCTION__, msg.c_str());
+        return STATUS_ERROR(ERROR_PERMISSION_DENIED, msg.c_str());
     }
 
-    ret = connectHelper<hardware::camera2::ICameraDeviceCallbacks,CameraDeviceClient>(cameraCb, id,
-            /*api1CameraId*/-1, clientPackageNameAdj, systemNativeClient,clientFeatureId,
+    ret = connectHelper<hardware::camera2::ICameraDeviceCallbacks,CameraDeviceClient>(cameraCb,
+            cameraId, /*api1CameraId*/-1, clientPackageNameAdj, systemNativeClient, clientFeatureId,
             clientUid, USE_CALLING_PID, API_2, /*shimUpdateOnly*/ false, oomScoreOffset,
             targetSdkVersion, overrideToPortrait, /*forceSlowJpegMode*/false,
             /*out*/client);
 
     if(!ret.isOk()) {
-        logRejected(id, callingPid, String8(clientPackageNameAdj), ret.toString8());
+        logRejected(cameraId, callingPid, clientPackageNameAdj, toStdString(ret.toString8()));
         return ret;
     }
 
@@ -1874,11 +1953,11 @@
     return ret;
 }
 
-String16 CameraService::getPackageNameFromUid(int clientUid) {
-    String16 packageName("");
+std::string CameraService::getPackageNameFromUid(int clientUid) {
+    std::string packageName("");
 
     sp<IServiceManager> sm = defaultServiceManager();
-    sp<IBinder> binder = sm->getService(String16(kPermissionServiceName));
+    sp<IBinder> binder = sm->getService(toString16(kPermissionServiceName));
     if (binder == 0) {
         ALOGE("Cannot get permission service");
         // Return empty package name and the further interaction
@@ -1899,22 +1978,24 @@
     }
 
     // Arbitrarily pick the first name in the list
-    packageName = packages[0];
+    packageName = toStdString(packages[0]);
 
     return packageName;
 }
 
 template<class CALLBACK, class CLIENT>
-Status CameraService::connectHelper(const sp<CALLBACK>& cameraCb, const String8& cameraId,
-        int api1CameraId, const String16& clientPackageNameMaybe, bool systemNativeClient,
-        const std::optional<String16>& clientFeatureId, int clientUid, int clientPid,
+Status CameraService::connectHelper(const sp<CALLBACK>& cameraCb, const std::string& cameraId,
+        int api1CameraId, const std::string& clientPackageNameMaybe, bool systemNativeClient,
+        const std::optional<std::string>& clientFeatureId, int clientUid, int clientPid,
         apiLevel effectiveApiLevel, bool shimUpdateOnly, int oomScoreOffset, int targetSdkVersion,
         bool overrideToPortrait, bool forceSlowJpegMode,
         /*out*/sp<CLIENT>& device) {
     binder::Status ret = binder::Status::ok();
 
     bool isNonSystemNdk = false;
-    String16 clientPackageName;
+    std::string clientPackageName;
+    int packageUid = (clientUid == USE_CALLING_UID) ?
+            CameraThreadState::getCallingUid() : clientUid;
     if (clientPackageNameMaybe.size() <= 0) {
         // NDK calls don't come with package names, but we need one for various cases.
         // Generally, there's a 1:1 mapping between UID and package name, but shared UIDs
@@ -1922,21 +2003,17 @@
         // same permissions, so picking any associated package name is sufficient. For some
         // other cases, this may give inaccurate names for clients in logs.
         isNonSystemNdk = true;
-        int packageUid = (clientUid == USE_CALLING_UID) ?
-            CameraThreadState::getCallingUid() : clientUid;
         clientPackageName = getPackageNameFromUid(packageUid);
     } else {
         clientPackageName = clientPackageNameMaybe;
     }
 
-    String8 clientName8(clientPackageName);
-
     int originalClientPid = 0;
 
     int packagePid = (clientPid == USE_CALLING_PID) ?
         CameraThreadState::getCallingPid() : clientPid;
     ALOGI("CameraService::connect call (PID %d \"%s\", camera ID %s) and "
-            "Camera API version %d", packagePid, clientName8.string(), cameraId.string(),
+            "Camera API version %d", packagePid, clientPackageName.c_str(), cameraId.c_str(),
             static_cast<int>(effectiveApiLevel));
 
     nsecs_t openTimeNs = systemTime();
@@ -1955,11 +2032,11 @@
                     , clientPid);
             return STATUS_ERROR_FMT(ERROR_MAX_CAMERAS_IN_USE,
                     "Cannot open camera %s for \"%s\" (PID %d): Too many other clients connecting",
-                    cameraId.string(), clientName8.string(), clientPid);
+                    cameraId.c_str(), clientPackageName.c_str(), clientPid);
         }
 
         // Enforce client permissions and do basic validity checks
-        if(!(ret = validateConnectLocked(cameraId, clientName8,
+        if(!(ret = validateConnectLocked(cameraId, clientPackageName,
                 /*inout*/clientUid, /*inout*/clientPid, /*out*/originalClientPid)).isOk()) {
             return ret;
         }
@@ -1976,27 +2053,27 @@
         status_t err;
 
         sp<BasicClient> clientTmp = nullptr;
-        std::shared_ptr<resource_policy::ClientDescriptor<String8, sp<BasicClient>>> partial;
+        std::shared_ptr<resource_policy::ClientDescriptor<std::string, sp<BasicClient>>> partial;
         if ((err = handleEvictionsLocked(cameraId, originalClientPid, effectiveApiLevel,
-                IInterface::asBinder(cameraCb), clientName8, oomScoreOffset, systemNativeClient,
-                /*out*/&clientTmp, /*out*/&partial)) != NO_ERROR) {
+                IInterface::asBinder(cameraCb), clientPackageName, oomScoreOffset,
+                systemNativeClient, /*out*/&clientTmp, /*out*/&partial)) != NO_ERROR) {
             switch (err) {
                 case -ENODEV:
                     return STATUS_ERROR_FMT(ERROR_DISCONNECTED,
                             "No camera device with ID \"%s\" currently available",
-                            cameraId.string());
+                            cameraId.c_str());
                 case -EBUSY:
                     return STATUS_ERROR_FMT(ERROR_CAMERA_IN_USE,
                             "Higher-priority client using camera, ID \"%s\" currently unavailable",
-                            cameraId.string());
+                            cameraId.c_str());
                 case -EUSERS:
                     return STATUS_ERROR_FMT(ERROR_MAX_CAMERAS_IN_USE,
                             "Too many cameras already open, cannot open camera \"%s\"",
-                            cameraId.string());
+                            cameraId.c_str());
                 default:
                     return STATUS_ERROR_FMT(ERROR_INVALID_OPERATION,
                             "Unexpected error %s (%d) opening camera \"%s\"",
-                            strerror(-err), err, cameraId.string());
+                            strerror(-err), err, cameraId.c_str());
             }
         }
 
@@ -2014,17 +2091,17 @@
                 getDeviceVersion(cameraId, overrideToPortrait, /*out*/&portraitRotation,
                         /*out*/&facing, /*out*/&orientation);
         if (facing == -1) {
-            ALOGE("%s: Unable to get camera device \"%s\"  facing", __FUNCTION__, cameraId.string());
+            ALOGE("%s: Unable to get camera device \"%s\"  facing", __FUNCTION__, cameraId.c_str());
             return STATUS_ERROR_FMT(ERROR_INVALID_OPERATION,
-                    "Unable to get camera device \"%s\" facing", cameraId.string());
+                    "Unable to get camera device \"%s\" facing", cameraId.c_str());
         }
 
         sp<BasicClient> tmp = nullptr;
         bool overrideForPerfClass = SessionConfigurationUtils::targetPerfClassPrimaryCamera(
-                mPerfClassPrimaryCameraIds, cameraId.string(), targetSdkVersion);
+                mPerfClassPrimaryCameraIds, cameraId, targetSdkVersion);
         if(!(ret = makeClient(this, cameraCb, clientPackageName, systemNativeClient,
-                clientFeatureId, cameraId, api1CameraId, facing, orientation,
-                clientPid, clientUid, getpid(),
+                clientFeatureId, cameraId, api1CameraId, facing,
+                orientation, clientPid, clientUid, getpid(),
                 deviceVersionAndTransport, effectiveApiLevel, overrideForPerfClass,
                 overrideToPortrait, forceSlowJpegMode,
                 /*out*/&tmp)).isOk()) {
@@ -2035,7 +2112,7 @@
         LOG_ALWAYS_FATAL_IF(client.get() == nullptr, "%s: CameraService in invalid state",
                 __FUNCTION__);
 
-        String8 monitorTags = isClientWatched(client.get()) ? mMonitorTags : String8("");
+        std::string monitorTags = isClientWatched(client.get()) ? mMonitorTags : std::string();
         err = client->initialize(mCameraProviderManager, monitorTags);
         if (err != OK) {
             ALOGE("%s: Could not initialize client from HAL.", __FUNCTION__);
@@ -2046,24 +2123,24 @@
             switch(err) {
                 case BAD_VALUE:
                     return STATUS_ERROR_FMT(ERROR_ILLEGAL_ARGUMENT,
-                            "Illegal argument to HAL module for camera \"%s\"", cameraId.string());
+                            "Illegal argument to HAL module for camera \"%s\"", cameraId.c_str());
                 case -EBUSY:
                     return STATUS_ERROR_FMT(ERROR_CAMERA_IN_USE,
-                            "Camera \"%s\" is already open", cameraId.string());
+                            "Camera \"%s\" is already open", cameraId.c_str());
                 case -EUSERS:
                     return STATUS_ERROR_FMT(ERROR_MAX_CAMERAS_IN_USE,
                             "Too many cameras already open, cannot open camera \"%s\"",
-                            cameraId.string());
+                            cameraId.c_str());
                 case PERMISSION_DENIED:
                     return STATUS_ERROR_FMT(ERROR_PERMISSION_DENIED,
-                            "No permission to open camera \"%s\"", cameraId.string());
+                            "No permission to open camera \"%s\"", cameraId.c_str());
                 case -EACCES:
                     return STATUS_ERROR_FMT(ERROR_DISABLED,
-                            "Camera \"%s\" disabled by policy", cameraId.string());
+                            "Camera \"%s\" disabled by policy", cameraId.c_str());
                 case -ENODEV:
                 default:
                     return STATUS_ERROR_FMT(ERROR_INVALID_OPERATION,
-                            "Failed to initialize camera \"%s\": %s (%d)", cameraId.string(),
+                            "Failed to initialize camera \"%s\": %s (%d)", cameraId.c_str(),
                             strerror(-err), err);
             }
         }
@@ -2080,7 +2157,7 @@
                 cameraState->setShimParams(params);
             } else {
                 ALOGE("%s: Cannot update shim parameters for camera %s, no such device exists.",
-                        __FUNCTION__, cameraId.string());
+                        __FUNCTION__, cameraId.c_str());
             }
         }
 
@@ -2122,32 +2199,38 @@
                     clientPackageName));
         }
 
-        // Set camera muting behavior
-        bool isCameraPrivacyEnabled =
-                mSensorPrivacyPolicy->isCameraPrivacyEnabled();
-        if (client->supportsCameraMute()) {
-            client->setCameraMute(
-                    mOverrideCameraMuteMode || isCameraPrivacyEnabled);
-        } else if (isCameraPrivacyEnabled) {
-            // no camera mute supported, but privacy is on! => disconnect
-            ALOGI("Camera mute not supported for package: %s, camera id: %s",
-                    String8(client->getPackageName()).string(), cameraId.string());
-            // Do not hold mServiceLock while disconnecting clients, but
-            // retain the condition blocking other clients from connecting
-            // in mServiceLockWrapper if held.
-            mServiceLock.unlock();
-            // Clear caller identity temporarily so client disconnect PID
-            // checks work correctly
-            int64_t token = CameraThreadState::clearCallingIdentity();
-            // Note AppOp to trigger the "Unblock" dialog
-            client->noteAppOp();
-            client->disconnect();
-            CameraThreadState::restoreCallingIdentity(token);
-            // Reacquire mServiceLock
-            mServiceLock.lock();
+        // Automotive privileged client AID_AUTOMOTIVE_EVS using exterior system camera for use
+        // cases such as rear view and surround view cannot be disabled and are exempt from camera
+        // privacy policy.
+        if ((!isAutomotivePrivilegedClient(packageUid) ||
+                !isAutomotiveExteriorSystemCamera(cameraId))) {
+            // Set camera muting behavior.
+            bool isCameraPrivacyEnabled =
+                    mSensorPrivacyPolicy->isCameraPrivacyEnabled();
+            if (client->supportsCameraMute()) {
+                client->setCameraMute(
+                        mOverrideCameraMuteMode || isCameraPrivacyEnabled);
+            } else if (isCameraPrivacyEnabled) {
+                // no camera mute supported, but privacy is on! => disconnect
+                ALOGI("Camera mute not supported for package: %s, camera id: %s",
+                        client->getPackageName().c_str(), cameraId.c_str());
+                // Do not hold mServiceLock while disconnecting clients, but
+                // retain the condition blocking other clients from connecting
+                // in mServiceLockWrapper if held.
+                mServiceLock.unlock();
+                // Clear caller identity temporarily so client disconnect PID
+                // checks work correctly
+                int64_t token = CameraThreadState::clearCallingIdentity();
+                // Note AppOp to trigger the "Unblock" dialog
+                client->noteAppOp();
+                client->disconnect();
+                CameraThreadState::restoreCallingIdentity(token);
+                // Reacquire mServiceLock
+                mServiceLock.lock();
 
-            return STATUS_ERROR_FMT(ERROR_DISABLED,
-                    "Camera \"%s\" disabled due to camera mute", cameraId.string());
+                return STATUS_ERROR_FMT(ERROR_DISABLED,
+                        "Camera \"%s\" disabled due to camera mute", cameraId.c_str());
+            }
         }
 
         if (shimUpdateOnly) {
@@ -2185,7 +2268,7 @@
                 if(res != OK) {
                     return STATUS_ERROR_FMT(ERROR_DISCONNECTED,
                             "No camera device with ID \"%s\" currently available",
-                            mInjectionExternalCamId.string());
+                            mInjectionExternalCamId.c_str());
                 }
                 res = clientSp->injectCamera(mInjectionExternalCamId, mCameraProviderManager);
                 if (res != OK) {
@@ -2193,7 +2276,7 @@
                 }
             } else {
                 ALOGE("%s: Internal camera ID = %s 's client does not exist!",
-                        __FUNCTION__, mInjectionInternalCamId.string());
+                        __FUNCTION__, mInjectionInternalCamId.c_str());
                 res = NO_INIT;
                 mInjectionStatusListener->notifyInjectionError(mInjectionExternalCamId, res);
             }
@@ -2203,7 +2286,8 @@
     return ret;
 }
 
-status_t CameraService::addOfflineClient(String8 cameraId, sp<BasicClient> offlineClient) {
+status_t CameraService::addOfflineClient(const std::string &cameraId,
+        sp<BasicClient> offlineClient) {
     if (offlineClient.get() == nullptr) {
         return BAD_VALUE;
     }
@@ -2232,7 +2316,7 @@
         const auto& onlinePriority = onlineClientDesc->getPriority();
         auto offlineClientDesc = CameraClientManager::makeClientDescriptor(
                 kOfflineDevice + onlineClientDesc->getKey(), offlineClient, /*cost*/ 0,
-                /*conflictingKeys*/ std::set<String8>(), onlinePriority.getScore(),
+                /*conflictingKeys*/ std::set<std::string>(), onlinePriority.getScore(),
                 onlineClientDesc->getOwnerId(), onlinePriority.getState(),
                 // native clients don't have offline processing support.
                 /*ommScoreOffset*/ 0, /*systemNativeClient*/false);
@@ -2248,7 +2332,8 @@
             return BAD_VALUE;
         }
 
-        String8 monitorTags = isClientWatched(offlineClient.get()) ? mMonitorTags : String8("");
+        std::string monitorTags = isClientWatched(offlineClient.get())
+                ? mMonitorTags : std::string();
         auto err = offlineClient->initialize(mCameraProviderManager, monitorTags);
         if (err != OK) {
             ALOGE("%s: Could not initialize offline client.", __FUNCTION__);
@@ -2259,7 +2344,7 @@
         if (evicted.size() > 0) {
             for (auto& i : evicted) {
                 ALOGE("%s: Invalid state: Offline client for camera %s was not removed ",
-                        __FUNCTION__, i->getKey().string());
+                        __FUNCTION__, i->getKey().c_str());
             }
 
             LOG_ALWAYS_FATAL("%s: Invalid state for CameraService, offline clients not evicted "
@@ -2270,7 +2355,7 @@
 
         logConnectedOffline(offlineClientDesc->getKey(),
                 static_cast<int>(offlineClientDesc->getOwnerId()),
-                String8(offlineClient->getPackageName()));
+                offlineClient->getPackageName());
 
         sp<IBinder> remoteCallback = offlineClient->getRemote();
         if (remoteCallback != nullptr) {
@@ -2281,8 +2366,8 @@
     return OK;
 }
 
-Status CameraService::turnOnTorchWithStrengthLevel(const String16& cameraId, int32_t torchStrength,
-        const sp<IBinder>& clientBinder) {
+Status CameraService::turnOnTorchWithStrengthLevel(const std::string& cameraId,
+        int32_t torchStrength, const sp<IBinder>& clientBinder) {
     Mutex::Autolock lock(mServiceLock);
 
     ATRACE_CALL();
@@ -2292,60 +2377,59 @@
                 "Torch client binder in null.");
     }
 
-    String8 id = String8(cameraId.string());
     int uid = CameraThreadState::getCallingUid();
 
-    if (shouldRejectSystemCameraConnection(id)) {
+    if (shouldRejectSystemCameraConnection(cameraId)) {
         return STATUS_ERROR_FMT(ERROR_ILLEGAL_ARGUMENT, "Unable to change the strength level"
-                "for system only device %s: ", id.string());
+                "for system only device %s: ", cameraId.c_str());
     }
 
     // verify id is valid
-    auto state = getCameraState(id);
+    auto state = getCameraState(cameraId);
     if (state == nullptr) {
-        ALOGE("%s: camera id is invalid %s", __FUNCTION__, id.string());
+        ALOGE("%s: camera id is invalid %s", __FUNCTION__, cameraId.c_str());
         return STATUS_ERROR_FMT(ERROR_ILLEGAL_ARGUMENT,
-            "Camera ID \"%s\" is a not valid camera ID", id.string());
+            "Camera ID \"%s\" is a not valid camera ID", cameraId.c_str());
     }
 
     StatusInternal cameraStatus = state->getStatus();
     if (cameraStatus != StatusInternal::NOT_AVAILABLE &&
             cameraStatus != StatusInternal::PRESENT) {
-        ALOGE("%s: camera id is invalid %s, status %d", __FUNCTION__, id.string(),
+        ALOGE("%s: camera id is invalid %s, status %d", __FUNCTION__, cameraId.c_str(),
             (int)cameraStatus);
         return STATUS_ERROR_FMT(ERROR_ILLEGAL_ARGUMENT,
-                "Camera ID \"%s\" is a not valid camera ID", id.string());
+                "Camera ID \"%s\" is a not valid camera ID", cameraId.c_str());
     }
 
     {
         Mutex::Autolock al(mTorchStatusMutex);
         TorchModeStatus status;
-        status_t err = getTorchStatusLocked(id, &status);
+        status_t err = getTorchStatusLocked(cameraId, &status);
         if (err != OK) {
             if (err == NAME_NOT_FOUND) {
              return STATUS_ERROR_FMT(ERROR_ILLEGAL_ARGUMENT,
-                    "Camera \"%s\" does not have a flash unit", id.string());
+                    "Camera \"%s\" does not have a flash unit", cameraId.c_str());
             }
             ALOGE("%s: getting current torch status failed for camera %s",
-                    __FUNCTION__, id.string());
+                    __FUNCTION__, cameraId.c_str());
             return STATUS_ERROR_FMT(ERROR_INVALID_OPERATION,
                     "Error changing torch strength level for camera \"%s\": %s (%d)",
-                    id.string(), strerror(-err), err);
+                    cameraId.c_str(), strerror(-err), err);
         }
 
         if (status == TorchModeStatus::NOT_AVAILABLE) {
             if (cameraStatus == StatusInternal::NOT_AVAILABLE) {
                 ALOGE("%s: torch mode of camera %s is not available because "
-                        "camera is in use.", __FUNCTION__, id.string());
+                        "camera is in use.", __FUNCTION__, cameraId.c_str());
                 return STATUS_ERROR_FMT(ERROR_CAMERA_IN_USE,
                         "Torch for camera \"%s\" is not available due to an existing camera user",
-                        id.string());
+                        cameraId.c_str());
             } else {
                 ALOGE("%s: torch mode of camera %s is not available due to "
-                       "insufficient resources", __FUNCTION__, id.string());
+                       "insufficient resources", __FUNCTION__, cameraId.c_str());
                 return STATUS_ERROR_FMT(ERROR_MAX_CAMERAS_IN_USE,
                         "Torch for camera \"%s\" is not available due to insufficient resources",
-                        id.string());
+                        cameraId.c_str());
             }
         }
     }
@@ -2356,44 +2440,44 @@
     }
     // Check if the current torch strength level is same as the new one.
     bool shouldSkipTorchStrengthUpdates = mCameraProviderManager->shouldSkipTorchStrengthUpdate(
-            id.string(), torchStrength);
+            cameraId, torchStrength);
 
-    status_t err = mFlashlight->turnOnTorchWithStrengthLevel(id, torchStrength);
+    status_t err = mFlashlight->turnOnTorchWithStrengthLevel(cameraId, torchStrength);
 
     if (err != OK) {
         int32_t errorCode;
-        String8 msg;
+        std::string msg;
         switch (err) {
             case -ENOSYS:
-                msg = String8::format("Camera \"%s\" has no flashlight.",
-                    id.string());
+                msg = fmt::sprintf("Camera \"%s\" has no flashlight.",
+                    cameraId.c_str());
                 errorCode = ERROR_ILLEGAL_ARGUMENT;
                 break;
             case -EBUSY:
-                msg = String8::format("Camera \"%s\" is in use",
-                    id.string());
+                msg = fmt::sprintf("Camera \"%s\" is in use",
+                    cameraId.c_str());
                 errorCode = ERROR_CAMERA_IN_USE;
                 break;
             case -EINVAL:
-                msg = String8::format("Torch strength level %d is not within the "
+                msg = fmt::sprintf("Torch strength level %d is not within the "
                         "valid range.", torchStrength);
                 errorCode = ERROR_ILLEGAL_ARGUMENT;
                 break;
             default:
-                msg = String8::format("Changing torch strength level failed.");
+                msg = "Changing torch strength level failed.";
                 errorCode = ERROR_INVALID_OPERATION;
         }
-        ALOGE("%s: %s", __FUNCTION__, msg.string());
-        return STATUS_ERROR(errorCode, msg.string());
+        ALOGE("%s: %s", __FUNCTION__, msg.c_str());
+        return STATUS_ERROR(errorCode, msg.c_str());
     }
 
     {
         // update the link to client's death
         // Store the last client that turns on each camera's torch mode.
         Mutex::Autolock al(mTorchClientMapMutex);
-        ssize_t index = mTorchClientMap.indexOfKey(id);
+        ssize_t index = mTorchClientMap.indexOfKey(cameraId);
         if (index == NAME_NOT_FOUND) {
-            mTorchClientMap.add(id, clientBinder);
+            mTorchClientMap.add(cameraId, clientBinder);
         } else {
             mTorchClientMap.valueAt(index)->unlinkToDeath(this);
             mTorchClientMap.replaceValueAt(index, clientBinder);
@@ -2402,16 +2486,15 @@
     }
 
     int clientPid = CameraThreadState::getCallingPid();
-    const char *id_cstr = id.c_str();
     ALOGI("%s: Torch strength for camera id %s changed to %d for client PID %d",
-            __FUNCTION__, id_cstr, torchStrength, clientPid);
+            __FUNCTION__, cameraId.c_str(), torchStrength, clientPid);
     if (!shouldSkipTorchStrengthUpdates) {
-        broadcastTorchStrengthLevel(id, torchStrength);
+        broadcastTorchStrengthLevel(cameraId, torchStrength);
     }
     return Status::ok();
 }
 
-Status CameraService::setTorchMode(const String16& cameraId, bool enabled,
+Status CameraService::setTorchMode(const std::string& cameraId, bool enabled,
         const sp<IBinder>& clientBinder) {
     Mutex::Autolock lock(mServiceLock);
 
@@ -2422,58 +2505,58 @@
                 "Torch client Binder is null");
     }
 
-    String8 id = String8(cameraId.string());
     int uid = CameraThreadState::getCallingUid();
 
-    if (shouldRejectSystemCameraConnection(id)) {
+    if (shouldRejectSystemCameraConnection(cameraId)) {
         return STATUS_ERROR_FMT(ERROR_ILLEGAL_ARGUMENT, "Unable to set torch mode"
-                " for system only device %s: ", id.string());
+                " for system only device %s: ", cameraId.c_str());
     }
     // verify id is valid.
-    auto state = getCameraState(id);
+    auto state = getCameraState(cameraId);
     if (state == nullptr) {
-        ALOGE("%s: camera id is invalid %s", __FUNCTION__, id.string());
+        ALOGE("%s: camera id is invalid %s", __FUNCTION__, cameraId.c_str());
         return STATUS_ERROR_FMT(ERROR_ILLEGAL_ARGUMENT,
-                "Camera ID \"%s\" is a not valid camera ID", id.string());
+                "Camera ID \"%s\" is a not valid camera ID", cameraId.c_str());
     }
 
     StatusInternal cameraStatus = state->getStatus();
     if (cameraStatus != StatusInternal::PRESENT &&
             cameraStatus != StatusInternal::NOT_AVAILABLE) {
-        ALOGE("%s: camera id is invalid %s, status %d", __FUNCTION__, id.string(), (int)cameraStatus);
+        ALOGE("%s: camera id is invalid %s, status %d", __FUNCTION__, cameraId.c_str(),
+                (int)cameraStatus);
         return STATUS_ERROR_FMT(ERROR_ILLEGAL_ARGUMENT,
-                "Camera ID \"%s\" is a not valid camera ID", id.string());
+                "Camera ID \"%s\" is a not valid camera ID", cameraId.c_str());
     }
 
     {
         Mutex::Autolock al(mTorchStatusMutex);
         TorchModeStatus status;
-        status_t err = getTorchStatusLocked(id, &status);
+        status_t err = getTorchStatusLocked(cameraId, &status);
         if (err != OK) {
             if (err == NAME_NOT_FOUND) {
                 return STATUS_ERROR_FMT(ERROR_ILLEGAL_ARGUMENT,
-                        "Camera \"%s\" does not have a flash unit", id.string());
+                        "Camera \"%s\" does not have a flash unit", cameraId.c_str());
             }
             ALOGE("%s: getting current torch status failed for camera %s",
-                    __FUNCTION__, id.string());
+                    __FUNCTION__, cameraId.c_str());
             return STATUS_ERROR_FMT(ERROR_INVALID_OPERATION,
-                    "Error updating torch status for camera \"%s\": %s (%d)", id.string(),
+                    "Error updating torch status for camera \"%s\": %s (%d)", cameraId.c_str(),
                     strerror(-err), err);
         }
 
         if (status == TorchModeStatus::NOT_AVAILABLE) {
             if (cameraStatus == StatusInternal::NOT_AVAILABLE) {
                 ALOGE("%s: torch mode of camera %s is not available because "
-                        "camera is in use", __FUNCTION__, id.string());
+                        "camera is in use", __FUNCTION__, cameraId.c_str());
                 return STATUS_ERROR_FMT(ERROR_CAMERA_IN_USE,
                         "Torch for camera \"%s\" is not available due to an existing camera user",
-                        id.string());
+                        cameraId.c_str());
             } else {
                 ALOGE("%s: torch mode of camera %s is not available due to "
-                        "insufficient resources", __FUNCTION__, id.string());
+                        "insufficient resources", __FUNCTION__, cameraId.c_str());
                 return STATUS_ERROR_FMT(ERROR_MAX_CAMERAS_IN_USE,
                         "Torch for camera \"%s\" is not available due to insufficient resources",
-                        id.string());
+                        cameraId.c_str());
             }
         }
     }
@@ -2485,40 +2568,40 @@
         updateTorchUidMapLocked(cameraId, uid);
     }
 
-    status_t err = mFlashlight->setTorchMode(id, enabled);
+    status_t err = mFlashlight->setTorchMode(cameraId, enabled);
 
     if (err != OK) {
         int32_t errorCode;
-        String8 msg;
+        std::string msg;
         switch (err) {
             case -ENOSYS:
-                msg = String8::format("Camera \"%s\" has no flashlight",
-                    id.string());
+                msg = fmt::sprintf("Camera \"%s\" has no flashlight",
+                    cameraId.c_str());
                 errorCode = ERROR_ILLEGAL_ARGUMENT;
                 break;
             case -EBUSY:
-                msg = String8::format("Camera \"%s\" is in use",
-                    id.string());
+                msg = fmt::sprintf("Camera \"%s\" is in use",
+                    cameraId.c_str());
                 errorCode = ERROR_CAMERA_IN_USE;
                 break;
             default:
-                msg = String8::format(
+                msg = fmt::sprintf(
                     "Setting torch mode of camera \"%s\" to %d failed: %s (%d)",
-                    id.string(), enabled, strerror(-err), err);
+                    cameraId.c_str(), enabled, strerror(-err), err);
                 errorCode = ERROR_INVALID_OPERATION;
         }
-        ALOGE("%s: %s", __FUNCTION__, msg.string());
-        logServiceError(msg,errorCode);
-        return STATUS_ERROR(errorCode, msg.string());
+        ALOGE("%s: %s", __FUNCTION__, msg.c_str());
+        logServiceError(msg, errorCode);
+        return STATUS_ERROR(errorCode, msg.c_str());
     }
 
     {
         // update the link to client's death
         Mutex::Autolock al(mTorchClientMapMutex);
-        ssize_t index = mTorchClientMap.indexOfKey(id);
+        ssize_t index = mTorchClientMap.indexOfKey(cameraId);
         if (enabled) {
             if (index == NAME_NOT_FOUND) {
-                mTorchClientMap.add(id, clientBinder);
+                mTorchClientMap.add(cameraId, clientBinder);
             } else {
                 mTorchClientMap.valueAt(index)->unlinkToDeath(this);
                 mTorchClientMap.replaceValueAt(index, clientBinder);
@@ -2530,21 +2613,20 @@
     }
 
     int clientPid = CameraThreadState::getCallingPid();
-    const char *id_cstr = id.c_str();
-    const char *torchState = enabled ? "on" : "off";
-    ALOGI("Torch for camera id %s turned %s for client PID %d", id_cstr, torchState, clientPid);
-    logTorchEvent(id_cstr, torchState , clientPid);
+    std::string torchState = enabled ? "on" : "off";
+    ALOGI("Torch for camera id %s turned %s for client PID %d", cameraId.c_str(),
+            torchState.c_str(), clientPid);
+    logTorchEvent(cameraId, torchState, clientPid);
     return Status::ok();
 }
 
-void CameraService::updateTorchUidMapLocked(const String16& cameraId, int uid) {
-    String8 id = String8(cameraId.string());
-    if (mTorchUidMap.find(id) == mTorchUidMap.end()) {
-        mTorchUidMap[id].first = uid;
-        mTorchUidMap[id].second = uid;
+void CameraService::updateTorchUidMapLocked(const std::string& cameraId, int uid) {
+    if (mTorchUidMap.find(cameraId) == mTorchUidMap.end()) {
+        mTorchUidMap[cameraId].first = uid;
+        mTorchUidMap[cameraId].second = uid;
     } else {
         // Set the pending UID
-        mTorchUidMap[id].first = uid;
+        mTorchUidMap[cameraId].first = uid;
     }
 }
 
@@ -2557,7 +2639,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(sCameraSendSystemEventsPermission)) {
+        if (!checkCallingPermission(toString16(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);
@@ -2631,7 +2713,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(sCameraSendSystemEventsPermission)) {
+        if (!checkCallingPermission(toString16(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);
@@ -2662,7 +2744,7 @@
     if (callingPid != selfPid) {
         // Ensure we're being called by system_server, or similar process with
         // permissions to notify the camera service about system events
-        if (!checkCallingPermission(sCameraSendSystemEventsPermission)) {
+        if (!checkCallingPermission(toString16(sCameraSendSystemEventsPermission))) {
             const int uid = CameraThreadState::getCallingUid();
             ALOGE("Permission Denial: cannot send updates to camera service about orientation"
                     " changes from pid=%d, uid=%d", callingPid, uid);
@@ -2704,7 +2786,7 @@
 
     if (!mInitialized) {
         ALOGE("%s: Camera HAL couldn't be initialized", __FUNCTION__);
-        logServiceError(String8::format("Camera subsystem is not available"),ERROR_DISCONNECTED);
+        logServiceError("Camera subsystem is not available", ERROR_DISCONNECTED);
         return STATUS_ERROR(ERROR_DISCONNECTED,
                 "Camera subsystem is not available");
     }
@@ -2716,8 +2798,7 @@
         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);
+            auto state = getCameraState(cameraId);
             if (state == nullptr) {
                 ALOGW("%s: camera id %s does not exist", __FUNCTION__, cameraId.c_str());
                 continue;
@@ -2726,7 +2807,7 @@
             if (status == StatusInternal::NOT_PRESENT || status == StatusInternal::ENUMERATING) {
                 continue;
             }
-            if (shouldRejectSystemCameraConnection(cameraIdStr)) {
+            if (shouldRejectSystemCameraConnection(cameraId)) {
                 continue;
             }
             validCombination.push_back(cameraId);
@@ -2755,13 +2836,11 @@
     // Check for camera permissions
     int callingPid = CameraThreadState::getCallingPid();
     int callingUid = CameraThreadState::getCallingUid();
-    permission::PermissionChecker permissionChecker;
     AttributionSourceState attributionSource{};
     attributionSource.pid = callingPid;
     attributionSource.uid = callingUid;
-    bool checkPermissionForCamera = permissionChecker.checkPermissionForPreflight(
-                sCameraPermission, attributionSource, String16(), AppOpsManager::OP_NONE)
-                != permission::PermissionChecker::PERMISSION_HARD_DENIED;
+    bool checkPermissionForCamera = checkPermission(std::string(),
+                sCameraPermission, attributionSource, std::string(), AppOpsManager::OP_NONE);
     if ((callingPid != getpid()) && !checkPermissionForCamera) {
         ALOGE("%s: pid %d doesn't have camera permissions", __FUNCTION__, callingPid);
         return STATUS_ERROR(ERROR_PERMISSION_DENIED,
@@ -2774,7 +2853,7 @@
                     cameraIdsAndSessionConfigurations, mPerfClassPrimaryCameraIds,
                     targetSdkVersion, isSupported);
     if (res != OK) {
-        logServiceError(String8::format("Unable to query session configuration support"),
+        logServiceError("Unable to query session configuration support",
             ERROR_INVALID_OPERATION);
         return STATUS_ERROR_FMT(ERROR_INVALID_OPERATION, "Unable to query session configuration "
                 "support %s (%d)", strerror(-res), res);
@@ -2809,13 +2888,13 @@
 
     auto clientUid = CameraThreadState::getCallingUid();
     auto clientPid = CameraThreadState::getCallingPid();
-    permission::PermissionChecker permissionChecker;
     AttributionSourceState attributionSource{};
     attributionSource.uid = clientUid;
     attributionSource.pid = clientPid;
-    bool openCloseCallbackAllowed = permissionChecker.checkPermissionForPreflight(
-            sCameraOpenCloseListenerPermission, attributionSource, String16(),
-            AppOpsManager::OP_NONE) != permission::PermissionChecker::PERMISSION_HARD_DENIED;
+
+   bool openCloseCallbackAllowed = checkPermission(std::string(),
+            sCameraOpenCloseListenerPermission, attributionSource, std::string(),
+            AppOpsManager::OP_NONE);
 
     Mutex::Autolock lock(mServiceLock);
 
@@ -2834,11 +2913,11 @@
                         openCloseCallbackAllowed);
         auto ret = serviceListener->initialize(isProcessLocalTest);
         if (ret != NO_ERROR) {
-            String8 msg = String8::format("Failed to initialize service listener: %s (%d)",
+            std::string msg = fmt::sprintf("Failed to initialize service listener: %s (%d)",
                     strerror(-ret), ret);
-            logServiceError(msg,ERROR_ILLEGAL_ARGUMENT);
-            ALOGE("%s: %s", __FUNCTION__, msg.string());
-            return STATUS_ERROR(ERROR_ILLEGAL_ARGUMENT, msg.string());
+            logServiceError(msg, ERROR_ILLEGAL_ARGUMENT);
+            ALOGE("%s: %s", __FUNCTION__, msg.c_str());
+            return STATUS_ERROR(ERROR_ILLEGAL_ARGUMENT, msg.c_str());
         }
         // 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
@@ -2853,7 +2932,7 @@
         for (auto& i : mCameraStates) {
             cameraStatuses->emplace_back(i.first,
                     mapToInterface(i.second->getStatus()), i.second->getUnavailablePhysicalIds(),
-                    openCloseCallbackAllowed ? i.second->getClientPackage() : String8::empty());
+                    openCloseCallbackAllowed ? i.second->getClientPackage() : std::string());
         }
     }
     // Remove the camera statuses that should be hidden from the client, we do
@@ -2872,9 +2951,9 @@
                             clientUid);}), cameraStatuses->end());
 
     //cameraStatuses will have non-eligible camera ids removed.
-    std::set<String16> idsChosenForCallback;
+    std::set<std::string> idsChosenForCallback;
     for (const auto &s : *cameraStatuses) {
-        idsChosenForCallback.insert(String16(s.cameraId));
+        idsChosenForCallback.insert(s.cameraId);
     }
 
     /*
@@ -2884,7 +2963,7 @@
     {
         Mutex::Autolock al(mTorchStatusMutex);
         for (size_t i = 0; i < mTorchStatusMap.size(); i++ ) {
-            String16 id = String16(mTorchStatusMap.keyAt(i).string());
+            const std::string &id = mTorchStatusMap.keyAt(i);
             // The camera id is visible to the client. Fine to send torch
             // callback.
             if (idsChosenForCallback.find(id) != idsChosenForCallback.end()) {
@@ -2926,7 +3005,7 @@
     return STATUS_ERROR(ERROR_ILLEGAL_ARGUMENT, "Unregistered listener given to removeListener");
 }
 
-Status CameraService::getLegacyParameters(int cameraId, /*out*/String16* parameters) {
+Status CameraService::getLegacyParameters(int cameraId, /*out*/std::string* parameters) {
 
     ATRACE_CALL();
     ALOGV("%s: for camera ID = %d", __FUNCTION__, cameraId);
@@ -2945,37 +3024,34 @@
     }
 
     String8 shimParamsString8 = shimParams.flatten();
-    String16 shimParamsString16 = String16(shimParamsString8);
 
-    *parameters = shimParamsString16;
+    *parameters = toStdString(shimParamsString8);
 
     return ret;
 }
 
-Status CameraService::supportsCameraApi(const String16& cameraId, int apiVersion,
+Status CameraService::supportsCameraApi(const std::string& cameraId, int apiVersion,
         /*out*/ bool *isSupported) {
     ATRACE_CALL();
 
-    const String8 id = String8(cameraId);
-
-    ALOGV("%s: for camera ID = %s", __FUNCTION__, id.string());
+    ALOGV("%s: for camera ID = %s", __FUNCTION__, cameraId.c_str());
 
     switch (apiVersion) {
         case API_VERSION_1:
         case API_VERSION_2:
             break;
         default:
-            String8 msg = String8::format("Unknown API version %d", apiVersion);
-            ALOGE("%s: %s", __FUNCTION__, msg.string());
-            return STATUS_ERROR(ERROR_ILLEGAL_ARGUMENT, msg.string());
+            std::string msg = fmt::sprintf("Unknown API version %d", apiVersion);
+            ALOGE("%s: %s", __FUNCTION__, msg.c_str());
+            return STATUS_ERROR(ERROR_ILLEGAL_ARGUMENT, msg.c_str());
     }
 
     int portraitRotation;
-    auto deviceVersionAndTransport = getDeviceVersion(id, false, &portraitRotation);
+    auto deviceVersionAndTransport = getDeviceVersion(cameraId, false, &portraitRotation);
     if (deviceVersionAndTransport.first == -1) {
-        String8 msg = String8::format("Unknown camera ID %s", id.string());
-        ALOGE("%s: %s", __FUNCTION__, msg.string());
-        return STATUS_ERROR(ERROR_ILLEGAL_ARGUMENT, msg.string());
+        std::string msg = fmt::sprintf("Unknown camera ID %s", cameraId.c_str());
+        ALOGE("%s: %s", __FUNCTION__, msg.c_str());
+        return STATUS_ERROR(ERROR_ILLEGAL_ARGUMENT, msg.c_str());
     }
     if (deviceVersionAndTransport.second == IPCTransport::HIDL) {
         int deviceVersion = deviceVersionAndTransport.first;
@@ -2985,11 +3061,11 @@
             case CAMERA_DEVICE_API_VERSION_3_1:
                 if (apiVersion == API_VERSION_2) {
                     ALOGV("%s: Camera id %s uses HAL version %d <3.2, doesn't support api2 without "
-                            "shim", __FUNCTION__, id.string(), deviceVersion);
+                            "shim", __FUNCTION__, cameraId.c_str(), deviceVersion);
                     *isSupported = false;
                 } else { // if (apiVersion == API_VERSION_1) {
                     ALOGV("%s: Camera id %s uses older HAL before 3.2, but api1 is always "
-                            "supported", __FUNCTION__, id.string());
+                            "supported", __FUNCTION__, cameraId.c_str());
                     *isSupported = true;
                 }
                 break;
@@ -3000,14 +3076,14 @@
             case CAMERA_DEVICE_API_VERSION_3_6:
             case CAMERA_DEVICE_API_VERSION_3_7:
                 ALOGV("%s: Camera id %s uses HAL3.2 or newer, supports api1/api2 directly",
-                        __FUNCTION__, id.string());
+                        __FUNCTION__, cameraId.c_str());
                 *isSupported = true;
                 break;
             default: {
-                String8 msg = String8::format("Unknown device version %x for device %s",
-                        deviceVersion, id.string());
-                ALOGE("%s: %s", __FUNCTION__, msg.string());
-                return STATUS_ERROR(ERROR_INVALID_OPERATION, msg.string());
+                std::string msg = fmt::sprintf("Unknown device version %x for device %s",
+                        deviceVersion, cameraId.c_str());
+                ALOGE("%s: %s", __FUNCTION__, msg.c_str());
+                return STATUS_ERROR(ERROR_INVALID_OPERATION, msg.c_str());
             }
         }
     } else {
@@ -3016,27 +3092,25 @@
     return Status::ok();
 }
 
-Status CameraService::isHiddenPhysicalCamera(const String16& cameraId,
+Status CameraService::isHiddenPhysicalCamera(const std::string& cameraId,
         /*out*/ bool *isSupported) {
     ATRACE_CALL();
 
-    const String8 id = String8(cameraId);
-
-    ALOGV("%s: for camera ID = %s", __FUNCTION__, id.string());
-    *isSupported = mCameraProviderManager->isHiddenPhysicalCamera(id.string());
+    ALOGV("%s: for camera ID = %s", __FUNCTION__, cameraId.c_str());
+    *isSupported = mCameraProviderManager->isHiddenPhysicalCamera(cameraId);
 
     return Status::ok();
 }
 
 Status CameraService::injectCamera(
-        const String16& packageName, const String16& internalCamId,
-        const String16& externalCamId,
+        const std::string& packageName, const std::string& internalCamId,
+        const std::string& externalCamId,
         const sp<ICameraInjectionCallback>& callback,
         /*out*/
         sp<ICameraInjectionSession>* cameraInjectionSession) {
     ATRACE_CALL();
 
-    if (!checkCallingPermission(sCameraInjectExternalCameraPermission)) {
+    if (!checkCallingPermission(toString16(sCameraInjectExternalCameraPermission))) {
         const int pid = CameraThreadState::getCallingPid();
         const int uid = CameraThreadState::getCallingUid();
         ALOGE("Permission Denial: can't inject camera pid=%d, uid=%d", pid, uid);
@@ -3047,13 +3121,13 @@
     ALOGV(
         "%s: Package name = %s, Internal camera ID = %s, External camera ID = "
         "%s",
-        __FUNCTION__, String8(packageName).string(),
-        String8(internalCamId).string(), String8(externalCamId).string());
+        __FUNCTION__, packageName.c_str(),
+        internalCamId.c_str(), externalCamId.c_str());
 
     {
         Mutex::Autolock lock(mInjectionParametersLock);
-        mInjectionInternalCamId = String8(internalCamId);
-        mInjectionExternalCamId = String8(externalCamId);
+        mInjectionInternalCamId = internalCamId;
+        mInjectionExternalCamId = externalCamId;
         mInjectionStatusListener->addListener(callback);
         *cameraInjectionSession = new CameraInjectionSession(this);
         status_t res = NO_ERROR;
@@ -3068,7 +3142,7 @@
             if(res != OK) {
                 return STATUS_ERROR_FMT(ERROR_DISCONNECTED,
                         "No camera device with ID \"%s\" currently available",
-                        mInjectionExternalCamId.string());
+                        mInjectionExternalCamId.c_str());
             }
             res = clientSp->injectCamera(mInjectionExternalCamId, mCameraProviderManager);
             if(res != OK) {
@@ -3083,7 +3157,7 @@
 }
 
 Status CameraService::reportExtensionSessionStats(
-        const hardware::CameraExtensionSessionStats& stats, String16* sessionKey /*out*/) {
+        const hardware::CameraExtensionSessionStats& stats, std::string* sessionKey /*out*/) {
     ALOGV("%s: reported %s", __FUNCTION__, stats.toString().c_str());
     *sessionKey = mCameraServiceProxyWrapper->updateExtensionStats(stats);
     return Status::ok();
@@ -3150,7 +3224,7 @@
 }
 
 std::shared_ptr<CameraService::CameraState> CameraService::getCameraState(
-        const String8& cameraId) const {
+        const std::string& cameraId) const {
     std::shared_ptr<CameraState> state;
     {
         Mutex::Autolock lock(mCameraStatesLock);
@@ -3162,12 +3236,12 @@
     return state;
 }
 
-sp<CameraService::BasicClient> CameraService::removeClientLocked(const String8& cameraId) {
+sp<CameraService::BasicClient> CameraService::removeClientLocked(const std::string& cameraId) {
     // Remove from active clients list
     auto clientDescriptorPtr = mActiveClientManager.remove(cameraId);
     if (clientDescriptorPtr == nullptr) {
         ALOGW("%s: Could not evict client, no client for camera ID %s", __FUNCTION__,
-                cameraId.string());
+                cameraId.c_str());
         return sp<BasicClient>{nullptr};
     }
 
@@ -3222,16 +3296,14 @@
 
         evicted.push_back(clientSp);
 
-        String8 curTime = getFormattedCurrentTime();
-
         ALOGE("Evicting conflicting client for camera ID %s due to user change",
-                i->getKey().string());
+                i->getKey().c_str());
 
         // Log the clients evicted
-        logEvent(String8::format("EVICT device %s client held by package %s (PID %"
+        logEvent(fmt::sprintf("EVICT device %s client held by package %s (PID %"
                 PRId32 ", score %" PRId32 ", state %" PRId32 ")\n   - Evicted due"
-                " to user switch.", i->getKey().string(),
-                String8{clientSp->getPackageName()}.string(),
+                " to user switch.", i->getKey().c_str(),
+                clientSp->getPackageName().c_str(),
                 i->getOwnerId(), i->getPriority().getScore(),
                 i->getPriority().getState()));
 
@@ -3254,12 +3326,12 @@
     mServiceLock.lock();
 }
 
-void CameraService::logEvent(const char* event) {
-    String8 curTime = getFormattedCurrentTime();
+void CameraService::logEvent(const std::string &event) {
+    std::string curTime = getFormattedCurrentTime();
     Mutex::Autolock l(mLogLock);
-    String8 msg = String8::format("%s : %s", curTime.string(), event);
+    std::string msg = curTime + " : " + event;
     // For service error events, print the msg only once.
-    if(!msg.contains("SERVICE ERROR")) {
+    if (msg.find("SERVICE ERROR") != std::string::npos) {
         mEventLog.add(msg);
     } else if(sServiceErrorEventSet.find(msg) == sServiceErrorEventSet.end()) {
         // Error event not added to the dumpsys log before
@@ -3268,77 +3340,78 @@
     }
 }
 
-void CameraService::logDisconnected(const char* cameraId, int clientPid,
-        const char* clientPackage) {
+void CameraService::logDisconnected(const std::string &cameraId, int clientPid,
+        const std::string &clientPackage) {
     // Log the clients evicted
-    logEvent(String8::format("DISCONNECT device %s client for package %s (PID %d)", cameraId,
-            clientPackage, clientPid));
+    logEvent(fmt::sprintf("DISCONNECT device %s client for package %s (PID %d)", cameraId.c_str(),
+            clientPackage.c_str(), clientPid));
 }
 
-void CameraService::logDisconnectedOffline(const char* cameraId, int clientPid,
-        const char* clientPackage) {
+void CameraService::logDisconnectedOffline(const std::string &cameraId, int clientPid,
+        const std::string &clientPackage) {
     // Log the clients evicted
-    logEvent(String8::format("DISCONNECT offline device %s client for package %s (PID %d)",
-                cameraId, clientPackage, clientPid));
+    logEvent(fmt::sprintf("DISCONNECT offline device %s client for package %s (PID %d)",
+            cameraId.c_str(), clientPackage.c_str(), clientPid));
 }
 
-void CameraService::logConnected(const char* cameraId, int clientPid,
-        const char* clientPackage) {
+void CameraService::logConnected(const std::string &cameraId, int clientPid,
+        const std::string &clientPackage) {
     // Log the clients evicted
-    logEvent(String8::format("CONNECT device %s client for package %s (PID %d)", cameraId,
-            clientPackage, clientPid));
+    logEvent(fmt::sprintf("CONNECT device %s client for package %s (PID %d)", cameraId.c_str(),
+            clientPackage.c_str(), clientPid));
 }
 
-void CameraService::logConnectedOffline(const char* cameraId, int clientPid,
-        const char* clientPackage) {
+void CameraService::logConnectedOffline(const std::string &cameraId, int clientPid,
+        const std::string &clientPackage) {
     // Log the clients evicted
-    logEvent(String8::format("CONNECT offline device %s client for package %s (PID %d)", cameraId,
-            clientPackage, clientPid));
+    logEvent(fmt::sprintf("CONNECT offline device %s client for package %s (PID %d)",
+            cameraId.c_str(), clientPackage.c_str(), clientPid));
 }
 
-void CameraService::logRejected(const char* cameraId, int clientPid,
-        const char* clientPackage, const char* reason) {
+void CameraService::logRejected(const std::string &cameraId, int clientPid,
+        const std::string &clientPackage, const std::string &reason) {
     // Log the client rejected
-    logEvent(String8::format("REJECT device %s client for package %s (PID %d), reason: (%s)",
-            cameraId, clientPackage, clientPid, reason));
+    logEvent(fmt::sprintf("REJECT device %s client for package %s (PID %d), reason: (%s)",
+            cameraId.c_str(), clientPackage.c_str(), clientPid, reason.c_str()));
 }
 
-void CameraService::logTorchEvent(const char* cameraId, const char *torchState, int clientPid) {
+void CameraService::logTorchEvent(const std::string &cameraId, const std::string &torchState,
+        int clientPid) {
     // Log torch event
-    logEvent(String8::format("Torch for camera id %s turned %s for client PID %d", cameraId,
-            torchState, clientPid));
+    logEvent(fmt::sprintf("Torch for camera id %s turned %s for client PID %d", cameraId.c_str(),
+            torchState.c_str(), clientPid));
 }
 
 void CameraService::logUserSwitch(const std::set<userid_t>& oldUserIds,
         const std::set<userid_t>& newUserIds) {
-    String8 newUsers = toString(newUserIds);
-    String8 oldUsers = toString(oldUserIds);
+    std::string newUsers = toString(newUserIds);
+    std::string oldUsers = toString(oldUserIds);
     if (oldUsers.size() == 0) {
         oldUsers = "<None>";
     }
     // Log the new and old users
-    logEvent(String8::format("USER_SWITCH previous allowed user IDs: %s, current allowed user IDs: %s",
-            oldUsers.string(), newUsers.string()));
+    logEvent(fmt::sprintf("USER_SWITCH previous allowed user IDs: %s, current allowed user IDs: %s",
+            oldUsers.c_str(), newUsers.c_str()));
 }
 
-void CameraService::logDeviceRemoved(const char* cameraId, const char* reason) {
+void CameraService::logDeviceRemoved(const std::string &cameraId, const std::string &reason) {
     // Log the device removal
-    logEvent(String8::format("REMOVE device %s, reason: (%s)", cameraId, reason));
+    logEvent(fmt::sprintf("REMOVE device %s, reason: (%s)", cameraId.c_str(), reason.c_str()));
 }
 
-void CameraService::logDeviceAdded(const char* cameraId, const char* reason) {
+void CameraService::logDeviceAdded(const std::string &cameraId, const std::string &reason) {
     // Log the device removal
-    logEvent(String8::format("ADD device %s, reason: (%s)", cameraId, reason));
+    logEvent(fmt::sprintf("ADD device %s, reason: (%s)", cameraId.c_str(), reason.c_str()));
 }
 
-void CameraService::logClientDied(int clientPid, const char* reason) {
+void CameraService::logClientDied(int clientPid, const std::string &reason) {
     // Log the device removal
-    logEvent(String8::format("DIED client(s) with PID %d, reason: (%s)", clientPid, reason));
+    logEvent(fmt::sprintf("DIED client(s) with PID %d, reason: (%s)", clientPid, reason.c_str()));
 }
 
-void CameraService::logServiceError(const char* msg, int errorCode) {
-    String8 curTime = getFormattedCurrentTime();
-    logEvent(String8::format("SERVICE ERROR: %s : %d (%s)", msg, errorCode, strerror(-errorCode)));
+void CameraService::logServiceError(const std::string &msg, int errorCode) {
+    logEvent(fmt::sprintf("SERVICE ERROR: %s : %d (%s)", msg.c_str(), errorCode,
+            strerror(-errorCode)));
 }
 
 status_t CameraService::onTransact(uint32_t code, const Parcel& data, Parcel* reply,
@@ -3458,9 +3531,9 @@
 
 CameraService::Client::Client(const sp<CameraService>& cameraService,
         const sp<ICameraClient>& cameraClient,
-        const String16& clientPackageName, bool systemNativeClient,
-        const std::optional<String16>& clientFeatureId,
-        const String8& cameraIdStr,
+        const std::string& clientPackageName, bool systemNativeClient,
+        const std::optional<std::string>& clientFeatureId,
+        const std::string& cameraIdStr,
         int api1CameraId, int cameraFacing, int sensorOrientation,
         int clientPid, uid_t clientUid,
         int servicePid, bool overrideToPortrait) :
@@ -3496,8 +3569,8 @@
 
 CameraService::BasicClient::BasicClient(const sp<CameraService>& cameraService,
         const sp<IBinder>& remoteCallback,
-        const String16& clientPackageName, bool nativeClient,
-        const std::optional<String16>& clientFeatureId, const String8& cameraIdStr,
+        const std::string& clientPackageName, bool nativeClient,
+        const std::optional<std::string>& clientFeatureId, const std::string& cameraIdStr,
         int cameraFacing, int sensorOrientation, int clientPid, uid_t clientUid,
         int servicePid, bool overrideToPortrait):
         mDestructionStarted(false),
@@ -3548,9 +3621,9 @@
     mDisconnected = true;
 
     sCameraService->removeByClient(this);
-    sCameraService->logDisconnected(mCameraIdStr, mClientPid, String8(mClientPackageName));
+    sCameraService->logDisconnected(mCameraIdStr, mClientPid, mClientPackageName);
     sCameraService->mCameraProviderManager->removeRef(CameraProviderManager::DeviceMode::CAMERA,
-            mCameraIdStr.c_str());
+            mCameraIdStr);
 
     sp<IBinder> remote = getRemote();
     if (remote != nullptr) {
@@ -3560,7 +3633,7 @@
     finishCameraOps();
     // Notify flashlight that a camera device is closed.
     sCameraService->mFlashlight->deviceClosed(mCameraIdStr);
-    ALOGI("%s: Disconnected client for camera %s for PID %d", __FUNCTION__, mCameraIdStr.string(),
+    ALOGI("%s: Disconnected client for camera %s for PID %d", __FUNCTION__, mCameraIdStr.c_str(),
             mClientPid);
 
     // client shouldn't be able to call into us anymore
@@ -3584,7 +3657,7 @@
     return OK;
 }
 
-status_t CameraService::BasicClient::startWatchingTags(const String8&, int) {
+status_t CameraService::BasicClient::startWatchingTags(const std::string&, int) {
     // Can't watch tags directly, must go through CameraService::startWatchingTags
     return OK;
 }
@@ -3599,7 +3672,7 @@
     return OK;
 }
 
-String16 CameraService::BasicClient::getPackageName() const {
+std::string CameraService::BasicClient::getPackageName() const {
     return mClientPackageName;
 }
 
@@ -3656,7 +3729,7 @@
 status_t CameraService::BasicClient::handleAppOpMode(int32_t mode) {
     if (mode == AppOpsManager::MODE_ERRORED) {
         ALOGI("Camera %s: Access for \"%s\" has been revoked",
-                mCameraIdStr.string(), String8(mClientPackageName).string());
+                mCameraIdStr.c_str(), mClientPackageName.c_str());
         return PERMISSION_DENIED;
     } else if (!mUidIsTrusted && mode == AppOpsManager::MODE_IGNORED) {
         // If the calling Uid is trusted (a native service), the AppOpsManager could
@@ -3672,7 +3745,7 @@
         // capabilities are unknown.
         if (!isUidActive || !isCameraPrivacyEnabled) {
             ALOGI("Camera %s: Access for \"%s\" has been restricted",
-                    mCameraIdStr.string(), String8(mClientPackageName).string());
+                    mCameraIdStr.c_str(), mClientPackageName.c_str());
             // Return the same error as for device policy manager rejection
             return -EACCES;
         }
@@ -3685,18 +3758,18 @@
 
     {
         ALOGV("%s: Start camera ops, package name = %s, client UID = %d",
-              __FUNCTION__, String8(mClientPackageName).string(), mClientUid);
+              __FUNCTION__, mClientPackageName.c_str(), mClientUid);
     }
     if (mAppOpsManager != nullptr) {
         // Notify app ops that the camera is not available
         mOpsCallback = new OpsCallback(this);
         mAppOpsManager->startWatchingMode(AppOpsManager::OP_CAMERA,
-                mClientPackageName, mOpsCallback);
+                toString16(mClientPackageName), mOpsCallback);
 
         // Just check for camera acccess here on open - delay startOp until
         // camera frames start streaming in startCameraStreamingOps
         int32_t mode = mAppOpsManager->checkOp(AppOpsManager::OP_CAMERA, mClientUid,
-                mClientPackageName);
+                toString16(mClientPackageName));
         status_t res = handleAppOpMode(mode);
         if (res != OK) {
             return res;
@@ -3729,12 +3802,13 @@
     }
 
     ALOGV("%s: Start camera streaming ops, package name = %s, client UID = %d",
-            __FUNCTION__, String8(mClientPackageName).string(), mClientUid);
+            __FUNCTION__, mClientPackageName.c_str(), mClientUid);
 
     if (mAppOpsManager != nullptr) {
         int32_t mode = mAppOpsManager->startOpNoThrow(AppOpsManager::OP_CAMERA, mClientUid,
-                mClientPackageName, /*startIfModeDefault*/ false, mClientFeatureId,
-                String16("start camera ") + String16(mCameraIdStr));
+                toString16(mClientPackageName), /*startIfModeDefault*/ false,
+                toString16(mClientFeatureId),
+                toString16("start camera ") + toString16(mCameraIdStr));
         status_t res = handleAppOpMode(mode);
         if (res != OK) {
             return res;
@@ -3750,14 +3824,14 @@
     ATRACE_CALL();
 
     ALOGV("%s: Start camera noteAppOp, package name = %s, client UID = %d",
-            __FUNCTION__, String8(mClientPackageName).string(), mClientUid);
+            __FUNCTION__, mClientPackageName.c_str(), mClientUid);
 
     // noteAppOp is only used for when camera mute is not supported, in order
     // to trigger the sensor privacy "Unblock" dialog
     if (mAppOpsManager != nullptr) {
         int32_t mode = mAppOpsManager->noteOp(AppOpsManager::OP_CAMERA, mClientUid,
-                mClientPackageName, mClientFeatureId,
-                String16("start camera ") + String16(mCameraIdStr));
+                toString16(mClientPackageName), toString16(mClientFeatureId),
+                toString16("start camera ") + toString16(mCameraIdStr));
         status_t res = handleAppOpMode(mode);
         if (res != OK) {
             return res;
@@ -3781,7 +3855,7 @@
 
     if (mAppOpsManager != nullptr) {
         mAppOpsManager->finishOp(AppOpsManager::OP_CAMERA, mClientUid,
-                mClientPackageName, mClientFeatureId);
+                toString16(mClientPackageName), toString16(mClientFeatureId));
         mOpsStreaming = false;
     }
 
@@ -3837,7 +3911,7 @@
 
     int32_t res;
     res = mAppOpsManager->checkOp(AppOpsManager::OP_CAMERA,
-            mClientUid, mClientPackageName);
+            mClientUid, toString16(mClientPackageName));
     ALOGV("checkOp returns: %d, %s ", res,
             res == AppOpsManager::MODE_ALLOWED ? "ALLOWED" :
             res == AppOpsManager::MODE_IGNORED ? "IGNORED" :
@@ -3845,15 +3919,15 @@
             "UNKNOWN");
 
     if (res == AppOpsManager::MODE_ERRORED) {
-        ALOGI("Camera %s: Access for \"%s\" revoked", mCameraIdStr.string(),
-              String8(mClientPackageName).string());
+        ALOGI("Camera %s: Access for \"%s\" revoked", mCameraIdStr.c_str(),
+              mClientPackageName.c_str());
         block();
     } else if (res == AppOpsManager::MODE_IGNORED) {
         bool isUidActive = sCameraService->mUidPolicy->isUidActive(mClientUid, mClientPackageName);
         bool isCameraPrivacyEnabled =
                 sCameraService->mSensorPrivacyPolicy->isCameraPrivacyEnabled();
         ALOGI("Camera %s: Access for \"%s\" has been restricted, isUidTrusted %d, isUidActive %d",
-                mCameraIdStr.string(), String8(mClientPackageName).string(),
+                mCameraIdStr.c_str(), mClientPackageName.c_str(),
                 mUidIsTrusted, isUidActive);
         // If the calling Uid is trusted (a native service), or the client Uid is active (WAR for
         // b/175320666), the AppOpsManager could return MODE_IGNORED. Do not treat such cases as
@@ -3934,7 +4008,7 @@
             | ActivityManager::UID_OBSERVER_ACTIVE | ActivityManager::UID_OBSERVER_PROCSTATE
             | ActivityManager::UID_OBSERVER_PROC_OOM_ADJ,
             ActivityManager::PROCESS_STATE_UNKNOWN,
-            String16("cameraserver"), emptyUidArray, 0, mObserverToken);
+            toString16(kServiceName), emptyUidArray, 0, mObserverToken);
     if (res == OK) {
         mRegistered = true;
         ALOGV("UidPolicy: Registered with ActivityManager");
@@ -3944,7 +4018,7 @@
 }
 
 void CameraService::UidPolicy::onServiceRegistration(const String16& name, const sp<IBinder>&) {
-    if (name != String16(kActivityServiceName)) {
+    if (name != toString16(kActivityServiceName)) {
         return;
     }
 
@@ -3956,9 +4030,9 @@
     // If not available then register for notifications, instead of blocking
     // till the service is ready
     sp<IServiceManager> sm = defaultServiceManager();
-    sp<IBinder> binder = sm->checkService(String16(kActivityServiceName));
+    sp<IBinder> binder = sm->checkService(toString16(kActivityServiceName));
     if (!binder) {
-        sm->registerForNotifications(String16(kActivityServiceName), this);
+        sm->registerForNotifications(toString16(kActivityServiceName), this);
     } else {
         registerWithActivityManager();
     }
@@ -4077,7 +4151,7 @@
         monitoredUid.procAdj = resource_policy::UNKNOWN_ADJ;
         monitoredUid.refCount = 1;
         it = mMonitoredUids.emplace(std::pair<uid_t, MonitoredUid>(uid, monitoredUid)).first;
-        status_t res = mAm.addUidToObserver(mObserverToken, String16("cameraserver"), uid);
+        status_t res = mAm.addUidToObserver(mObserverToken, toString16(kServiceName), uid);
         if (res != OK) {
             ALOGE("UidPolicy: Failed to add uid to observer: 0x%08x", res);
         }
@@ -4098,7 +4172,7 @@
         it->second.refCount--;
         if (it->second.refCount == 0) {
             mMonitoredUids.erase(it);
-            status_t res = mAm.removeUidFromObserver(mObserverToken, String16("cameraserver"), uid);
+            status_t res = mAm.removeUidFromObserver(mObserverToken, toString16(kServiceName), uid);
             if (res != OK) {
                 ALOGE("UidPolicy: Failed to remove uid from observer: 0x%08x", res);
             }
@@ -4110,7 +4184,7 @@
     }
 }
 
-bool CameraService::UidPolicy::isUidActive(uid_t uid, String16 callingPackage) {
+bool CameraService::UidPolicy::isUidActive(uid_t uid, const std::string &callingPackage) {
     Mutex::Autolock _l(mUidLock);
     return isUidActiveLocked(uid, callingPackage);
 }
@@ -4118,7 +4192,7 @@
 static const int64_t kPollUidActiveTimeoutTotalMillis = 300;
 static const int64_t kPollUidActiveTimeoutMillis = 50;
 
-bool CameraService::UidPolicy::isUidActiveLocked(uid_t uid, String16 callingPackage) {
+bool CameraService::UidPolicy::isUidActiveLocked(uid_t uid, const std::string &callingPackage) {
     // Non-app UIDs are considered always active
     // If activity manager is unreachable, assume everything is active
     if (uid < FIRST_APPLICATION_UID || !mRegistered) {
@@ -4145,7 +4219,7 @@
             // some polling which should happen pretty rarely anyway as the race is hard
             // to hit.
             active = mActiveUids.find(uid) != mActiveUids.end();
-            if (!active) active = am.isUidActive(uid, callingPackage);
+            if (!active) active = am.isUidActive(uid, toString16(callingPackage));
             if (active) {
                 break;
             }
@@ -4185,12 +4259,12 @@
     return procState;
 }
 
-void CameraService::UidPolicy::UidPolicy::addOverrideUid(uid_t uid,
-        String16 callingPackage, bool active) {
+void CameraService::UidPolicy::addOverrideUid(uid_t uid,
+        const std::string &callingPackage, bool active) {
     updateOverrideUid(uid, callingPackage, active, true);
 }
 
-void CameraService::UidPolicy::removeOverrideUid(uid_t uid, String16 callingPackage) {
+void CameraService::UidPolicy::removeOverrideUid(uid_t uid, const std::string &callingPackage) {
     updateOverrideUid(uid, callingPackage, false, false);
 }
 
@@ -4201,7 +4275,7 @@
     mActiveUids.clear();
 }
 
-void CameraService::UidPolicy::updateOverrideUid(uid_t uid, String16 callingPackage,
+void CameraService::UidPolicy::updateOverrideUid(uid_t uid, const std::string &callingPackage,
         bool active, bool insert) {
     bool wasActive = false;
     bool isActive = false;
@@ -4244,7 +4318,7 @@
 
 void CameraService::SensorPrivacyPolicy::onServiceRegistration(const String16& name,
                                                                const sp<IBinder>&) {
-    if (name != String16(kSensorPrivacyServiceName)) {
+    if (name != toString16(kSensorPrivacyServiceName)) {
         return;
     }
 
@@ -4255,9 +4329,9 @@
     // Use checkservice to see if the sensor_privacy service is available
     // If service is not available then register for notification
     sp<IServiceManager> sm = defaultServiceManager();
-    sp<IBinder> binder = sm->checkService(String16(kSensorPrivacyServiceName));
+    sp<IBinder> binder = sm->checkService(toString16(kSensorPrivacyServiceName));
     if (!binder) {
-        sm->registerForNotifications(String16(kSensorPrivacyServiceName),this);
+        sm->registerForNotifications(toString16(kSensorPrivacyServiceName),this);
     } else {
         registerWithSensorPrivacyManager();
     }
@@ -4321,8 +4395,8 @@
 //                  CameraState
 // ----------------------------------------------------------------------------
 
-CameraService::CameraState::CameraState(const String8& id, int cost,
-        const std::set<String8>& conflicting, SystemCameraKind systemCameraKind,
+CameraService::CameraState::CameraState(const std::string& id, int cost,
+        const std::set<std::string>& conflicting, SystemCameraKind systemCameraKind,
         const std::vector<std::string>& physicalCameras) : mId(id),
         mStatus(StatusInternal::NOT_PRESENT), mCost(cost), mConflicting(conflicting),
         mSystemCameraKind(systemCameraKind), mPhysicalCameras(physicalCameras) {}
@@ -4334,9 +4408,9 @@
     return mStatus;
 }
 
-std::vector<String8> CameraService::CameraState::getUnavailablePhysicalIds() const {
+std::vector<std::string> CameraService::CameraState::getUnavailablePhysicalIds() const {
     Mutex::Autolock lock(mStatusLock);
-    std::vector<String8> res(mUnavailablePhysicalIds.begin(), mUnavailablePhysicalIds.end());
+    std::vector<std::string> res(mUnavailablePhysicalIds.begin(), mUnavailablePhysicalIds.end());
     return res;
 }
 
@@ -4352,14 +4426,10 @@
     return mCost;
 }
 
-std::set<String8> CameraService::CameraState::getConflicting() const {
+std::set<std::string> CameraService::CameraState::getConflicting() const {
     return mConflicting;
 }
 
-String8 CameraService::CameraState::getId() const {
-    return mId;
-}
-
 SystemCameraKind CameraService::CameraState::getSystemCameraKind() const {
     return mSystemCameraKind;
 }
@@ -4369,24 +4439,24 @@
             != mPhysicalCameras.end();
 }
 
-bool CameraService::CameraState::addUnavailablePhysicalId(const String8& physicalId) {
+bool CameraService::CameraState::addUnavailablePhysicalId(const std::string& physicalId) {
     Mutex::Autolock lock(mStatusLock);
     auto result = mUnavailablePhysicalIds.insert(physicalId);
     return result.second;
 }
 
-bool CameraService::CameraState::removeUnavailablePhysicalId(const String8& physicalId) {
+bool CameraService::CameraState::removeUnavailablePhysicalId(const std::string& physicalId) {
     Mutex::Autolock lock(mStatusLock);
     auto count = mUnavailablePhysicalIds.erase(physicalId);
     return count > 0;
 }
 
-void CameraService::CameraState::setClientPackage(const String8& clientPackage) {
+void CameraService::CameraState::setClientPackage(const std::string& clientPackage) {
     Mutex::Autolock lock(mStatusLock);
     mClientPackage = clientPackage;
 }
 
-String8 CameraService::CameraState::getClientPackage() const {
+std::string CameraService::CameraState::getClientPackage() const {
     Mutex::Autolock lock(mStatusLock);
     return mClientPackage;
 }
@@ -4396,23 +4466,23 @@
 // ----------------------------------------------------------------------------
 
 void CameraService::ClientEventListener::onClientAdded(
-        const resource_policy::ClientDescriptor<String8,
+        const resource_policy::ClientDescriptor<std::string,
         sp<CameraService::BasicClient>>& descriptor) {
     const auto& basicClient = descriptor.getValue();
     if (basicClient.get() != nullptr) {
         BatteryNotifier& notifier(BatteryNotifier::getInstance());
-        notifier.noteStartCamera(descriptor.getKey(),
+        notifier.noteStartCamera(toString8(descriptor.getKey()),
                 static_cast<int>(basicClient->getClientUid()));
     }
 }
 
 void CameraService::ClientEventListener::onClientRemoved(
-        const resource_policy::ClientDescriptor<String8,
+        const resource_policy::ClientDescriptor<std::string,
         sp<CameraService::BasicClient>>& descriptor) {
     const auto& basicClient = descriptor.getValue();
     if (basicClient.get() != nullptr) {
         BatteryNotifier& notifier(BatteryNotifier::getInstance());
-        notifier.noteStopCamera(descriptor.getKey(),
+        notifier.noteStopCamera(toString8(descriptor.getKey()),
                 static_cast<int>(basicClient->getClientUid()));
     }
 }
@@ -4429,7 +4499,7 @@
 CameraService::CameraClientManager::~CameraClientManager() {}
 
 sp<CameraService::BasicClient> CameraService::CameraClientManager::getCameraClient(
-        const String8& id) const {
+        const std::string& id) const {
     auto descriptor = get(id);
     if (descriptor == nullptr) {
         return sp<BasicClient>{nullptr};
@@ -4437,56 +4507,57 @@
     return descriptor->getValue();
 }
 
-String8 CameraService::CameraClientManager::toString() const {
+std::string CameraService::CameraClientManager::toString() const {
     auto all = getAll();
-    String8 ret("[");
+    std::ostringstream ret;
+    ret << "[";
     bool hasAny = false;
     for (auto& i : all) {
         hasAny = true;
-        String8 key = i->getKey();
+        std::string key = i->getKey();
         int32_t cost = i->getCost();
         int32_t pid = i->getOwnerId();
         int32_t score = i->getPriority().getScore();
         int32_t state = i->getPriority().getState();
         auto conflicting = i->getConflicting();
         auto clientSp = i->getValue();
-        String8 packageName;
+        std::string packageName;
         userid_t clientUserId = 0;
         if (clientSp.get() != nullptr) {
-            packageName = String8{clientSp->getPackageName()};
+            packageName = clientSp->getPackageName();
             uid_t clientUid = clientSp->getClientUid();
             clientUserId = multiuser_get_user_id(clientUid);
         }
-        ret.appendFormat("\n(Camera ID: %s, Cost: %" PRId32 ", PID: %" PRId32 ", Score: %"
-                PRId32 ", State: %" PRId32, key.string(), cost, pid, score, state);
+        ret << fmt::sprintf("\n(Camera ID: %s, Cost: %" PRId32 ", PID: %" PRId32 ", Score: %"
+                PRId32 ", State: %" PRId32, key.c_str(), cost, pid, score, state);
 
         if (clientSp.get() != nullptr) {
-            ret.appendFormat("User Id: %d, ", clientUserId);
+            ret << fmt::sprintf("User Id: %d, ", clientUserId);
         }
         if (packageName.size() != 0) {
-            ret.appendFormat("Client Package Name: %s", packageName.string());
+            ret << fmt::sprintf("Client Package Name: %s", packageName.c_str());
         }
 
-        ret.append(", Conflicting Client Devices: {");
+        ret << ", Conflicting Client Devices: {";
         for (auto& j : conflicting) {
-            ret.appendFormat("%s, ", j.string());
+            ret << fmt::sprintf("%s, ", j.c_str());
         }
-        ret.append("})");
+        ret << "})";
     }
-    if (hasAny) ret.append("\n");
-    ret.append("]\n");
-    return ret;
+    if (hasAny) ret << "\n";
+    ret << "]\n";
+    return std::move(ret.str());
 }
 
 CameraService::DescriptorPtr CameraService::CameraClientManager::makeClientDescriptor(
-        const String8& key, const sp<BasicClient>& value, int32_t cost,
-        const std::set<String8>& conflictingKeys, int32_t score, int32_t ownerId,
+        const std::string& key, const sp<BasicClient>& value, int32_t cost,
+        const std::set<std::string>& conflictingKeys, int32_t score, int32_t ownerId,
         int32_t state, int32_t oomScoreOffset, bool systemNativeClient) {
 
     int32_t score_adj = systemNativeClient ? kSystemNativeClientScore : score;
-    int32_t state_adj = systemNativeClient ? kSystemNativeClientState: state;
+    int32_t state_adj = systemNativeClient ? kSystemNativeClientState : state;
 
-    return std::make_shared<resource_policy::ClientDescriptor<String8, sp<BasicClient>>>(
+    return std::make_shared<resource_policy::ClientDescriptor<std::string, sp<BasicClient>>>(
             key, value, cost, conflictingKeys, score_adj, ownerId, state_adj,
             systemNativeClient, oomScoreOffset);
 }
@@ -4525,7 +4596,7 @@
 }
 
 void CameraService::InjectionStatusListener::notifyInjectionError(
-        String8 injectedCamId, status_t err) {
+        const std::string &injectedCamId, status_t err) {
     if (mCameraInjectionCallback == nullptr) {
         ALOGW("InjectionStatusListener: mCameraInjectionCallback == nullptr");
         return;
@@ -4536,37 +4607,37 @@
             mCameraInjectionCallback->onInjectionError(
                     ICameraInjectionCallback::ERROR_INJECTION_SESSION);
             ALOGE("No camera device with ID \"%s\" currently available!",
-                    injectedCamId.string());
+                    injectedCamId.c_str());
             break;
         case -EBUSY:
             mCameraInjectionCallback->onInjectionError(
                     ICameraInjectionCallback::ERROR_INJECTION_SESSION);
             ALOGE("Higher-priority client using camera, ID \"%s\" currently unavailable!",
-                    injectedCamId.string());
+                    injectedCamId.c_str());
             break;
         case DEAD_OBJECT:
             mCameraInjectionCallback->onInjectionError(
                     ICameraInjectionCallback::ERROR_INJECTION_SESSION);
             ALOGE("Camera ID \"%s\" object is dead!",
-                    injectedCamId.string());
+                    injectedCamId.c_str());
             break;
         case INVALID_OPERATION:
             mCameraInjectionCallback->onInjectionError(
                     ICameraInjectionCallback::ERROR_INJECTION_SESSION);
             ALOGE("Camera ID \"%s\" encountered an operating or internal error!",
-                    injectedCamId.string());
+                    injectedCamId.c_str());
             break;
         case UNKNOWN_TRANSACTION:
             mCameraInjectionCallback->onInjectionError(
                     ICameraInjectionCallback::ERROR_INJECTION_UNSUPPORTED);
             ALOGE("Camera ID \"%s\" method doesn't support!",
-                    injectedCamId.string());
+                    injectedCamId.c_str());
             break;
         default:
             mCameraInjectionCallback->onInjectionError(
                     ICameraInjectionCallback::ERROR_INJECTION_INVALID_ERROR);
             ALOGE("Unexpected error %s (%d) opening camera \"%s\"!",
-                    strerror(-err), err, injectedCamId.string());
+                    strerror(-err), err, injectedCamId.c_str());
     }
 }
 
@@ -4642,10 +4713,10 @@
         Mutex::Autolock l(mCameraStatesLock);
         // Start collecting the info for open sessions and store it in temp file.
         for (const auto& state : mCameraStates) {
-            String8 cameraId = state.first;
+            std::string cameraId = state.first;
             auto clientDescriptor = mActiveClientManager.get(cameraId);
             if (clientDescriptor != nullptr) {
-                dprintf(mMemFd, "== Camera device %s dynamic info: ==\n", cameraId.string());
+                dprintf(mMemFd, "== Camera device %s dynamic info: ==\n", cameraId.c_str());
                 // Log the current open session info before device is disconnected.
                 dumpOpenSessionClientLogs(mMemFd, args, cameraId);
             }
@@ -4656,7 +4727,7 @@
 status_t CameraService::dump(int fd, const Vector<String16>& args) {
     ATRACE_CALL();
 
-    if (checkCallingPermission(sDumpPermission) == false) {
+    if (checkCallingPermission(toString16(sDumpPermission)) == false) {
         dprintf(fd, "Permission Denial: can't dump CameraService from pid=%d, uid=%d\n",
                 CameraThreadState::getCallingPid(),
                 CameraThreadState::getCallingUid());
@@ -4685,9 +4756,9 @@
     for (size_t i = 0; i < mNormalDeviceIds.size(); i++) {
         dprintf(fd, "    Device %zu maps to \"%s\"\n", i, mNormalDeviceIds[i].c_str());
     }
-    String8 activeClientString = mActiveClientManager.toString();
-    dprintf(fd, "Active Camera Clients:\n%s", activeClientString.string());
-    dprintf(fd, "Allowed user IDs: %s\n", toString(mAllowedUsers).string());
+    std::string activeClientString = mActiveClientManager.toString();
+    dprintf(fd, "Active Camera Clients:\n%s", activeClientString.c_str());
+    dprintf(fd, "Allowed user IDs: %s\n", toString(mAllowedUsers).c_str());
     if (mStreamUseCaseOverrides.size() > 0) {
         dprintf(fd, "Active stream use case overrides:");
         for (int64_t useCaseOverride : mStreamUseCaseOverrides) {
@@ -4705,18 +4776,18 @@
 
     int argSize = args.size();
     for (int i = 0; i < argSize; i++) {
-        if (args[i] == TagMonitor::kMonitorOption) {
+        if (args[i] == toString16(TagMonitor::kMonitorOption)) {
             if (i + 1 < argSize) {
-                mMonitorTags = String8(args[i + 1]);
+                mMonitorTags = toStdString(args[i + 1]);
             }
             break;
         }
     }
 
     for (auto& state : mCameraStates) {
-        String8 cameraId = state.first;
+        const std::string &cameraId = state.first;
 
-        dprintf(fd, "== Camera device %s dynamic info: ==\n", cameraId.string());
+        dprintf(fd, "== Camera device %s dynamic info: ==\n", cameraId.c_str());
 
         CameraParameters p = state.second->getShimParams();
         if (!p.isEmpty()) {
@@ -4767,8 +4838,8 @@
         if (args[i] == verboseOption) {
             // change logging level
             if (i + 1 >= n) continue;
-            String8 levelStr(args[i+1]);
-            int level = atoi(levelStr.string());
+            std::string levelStr = toStdString(args[i+1]);
+            int level = atoi(levelStr.c_str());
             dprintf(fd, "\nSetting log level to %d.\n", level);
             setLogLevel(level);
         } else if (args[i] == unreachableOption) {
@@ -4814,11 +4885,11 @@
 }
 
 void CameraService::dumpOpenSessionClientLogs(int fd,
-        const Vector<String16>& args, const String8& cameraId) {
+        const Vector<String16>& args, const std::string& cameraId) {
     auto clientDescriptor = mActiveClientManager.get(cameraId);
     dprintf(fd, "  %s : Device %s is open. Client instance dump:\n",
-            getFormattedCurrentTime().string(),
-            cameraId.string());
+            getFormattedCurrentTime().c_str(),
+            cameraId.c_str());
     dprintf(fd, "    Client priority score: %d state: %d\n",
         clientDescriptor->getPriority().getScore(),
         clientDescriptor->getPriority().getState());
@@ -4826,14 +4897,14 @@
 
     auto client = clientDescriptor->getValue();
     dprintf(fd, "    Client package: %s\n",
-        String8(client->getPackageName()).string());
+        client->getPackageName().c_str());
 
     client->dumpClient(fd, args);
 }
 
-void CameraService::dumpClosedSessionClientLogs(int fd, const String8& cameraId) {
+void CameraService::dumpClosedSessionClientLogs(int fd, const std::string& cameraId) {
     dprintf(fd, "  Device %s is closed, no client instance\n",
-                    cameraId.string());
+                    cameraId.c_str());
 }
 
 void CameraService::dumpEventLog(int fd) {
@@ -4841,7 +4912,7 @@
 
     Mutex::Autolock l(mLogLock);
     for (const auto& msg : mEventLog) {
-        dprintf(fd, "  %s\n", msg.string());
+        dprintf(fd, "  %s\n", msg.c_str());
     }
 
     if (mEventLog.size() == DEFAULT_EVENT_LOG_LENGTH) {
@@ -4852,7 +4923,7 @@
     dprintf(fd, "\n");
 }
 
-void CameraService::cacheClientTagDumpIfNeeded(const char *cameraId, BasicClient* client) {
+void CameraService::cacheClientTagDumpIfNeeded(const std::string &cameraId, BasicClient* client) {
     Mutex::Autolock lock(mLogLock);
     if (!isClientWatchedLocked(client)) { return; }
 
@@ -4861,34 +4932,26 @@
 
     if (dumpVector.empty()) { return; }
 
-    std::string dumpString;
+    std::ostringstream dumpString;
 
-    String8 currentTime = getFormattedCurrentTime();
-    dumpString += "Cached @ ";
-    dumpString += currentTime.string();
-    dumpString += "\n"; // First line is the timestamp of when client is cached.
-
-
-    const String16 &packageName = client->getPackageName();
-
-    String8 packageName8 = String8(packageName);
-    const char *printablePackageName = packageName8.lockBuffer(packageName.size());
-
+    std::string currentTime = getFormattedCurrentTime();
+    dumpString << "Cached @ ";
+    dumpString << currentTime;
+    dumpString << "\n"; // First line is the timestamp of when client is cached.
 
     size_t i = dumpVector.size();
 
     // Store the string in reverse order (latest last)
     while (i > 0) {
          i--;
-         dumpString += cameraId;
-         dumpString += ":";
-         dumpString += printablePackageName;
-         dumpString += "  ";
-         dumpString += dumpVector[i]; // implicitly ends with '\n'
+         dumpString << cameraId;
+         dumpString << ":";
+         dumpString << client->getPackageName();
+         dumpString << "  ";
+         dumpString << dumpVector[i]; // implicitly ends with '\n'
     }
 
-    packageName8.unlockBuffer();
-    mWatchedClientsDumpCache[packageName] = dumpString;
+    mWatchedClientsDumpCache[client->getPackageName()] = dumpString.str();
 }
 
 void CameraService::handleTorchClientBinderDied(const wp<IBinder> &who) {
@@ -4896,7 +4959,7 @@
     for (size_t i = 0; i < mTorchClientMap.size(); i++) {
         if (mTorchClientMap[i] == who) {
             // turn off the torch mode that was turned on by dead client
-            String8 cameraId = mTorchClientMap.keyAt(i);
+            std::string cameraId = mTorchClientMap.keyAt(i);
             status_t res = mFlashlight->setTorchMode(cameraId, false);
             if (res) {
                 ALOGE("%s: torch client died but couldn't turn off torch: "
@@ -4916,7 +4979,7 @@
       * binder driver
       */
     // PID here is approximate and can be wrong.
-    logClientDied(CameraThreadState::getCallingPid(), String8("Binder died unexpectedly"));
+    logClientDied(CameraThreadState::getCallingPid(), "Binder died unexpectedly");
 
     // check torch client
     handleTorchClientBinderDied(who);
@@ -4931,11 +4994,11 @@
             __FUNCTION__);
 }
 
-void CameraService::updateStatus(StatusInternal status, const String8& cameraId) {
+void CameraService::updateStatus(StatusInternal status, const std::string& cameraId) {
     updateStatus(status, cameraId, {});
 }
 
-void CameraService::updateStatus(StatusInternal status, const String8& cameraId,
+void CameraService::updateStatus(StatusInternal status, const std::string& cameraId,
         std::initializer_list<StatusInternal> rejectSourceStates) {
     // Do not lock mServiceLock here or can get into a deadlock from
     // connect() -> disconnect -> updateStatus
@@ -4944,14 +5007,14 @@
 
     if (state == nullptr) {
         ALOGW("%s: Could not update the status for %s, no such device exists", __FUNCTION__,
-                cameraId.string());
+                cameraId.c_str());
         return;
     }
 
     // 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());
+        ALOGE("%s: Invalid camera id %s, skipping", __FUNCTION__, cameraId.c_str());
         return;
     }
 
@@ -4962,7 +5025,7 @@
     // of the listeners with both the mStatusLock and mStatusListenerLock held
     state->updateStatus(status, cameraId, rejectSourceStates, [this, &deviceKind,
                         &logicalCameraIds]
-            (const String8& cameraId, StatusInternal status) {
+            (const std::string& cameraId, StatusInternal status) {
 
             if (status != StatusInternal::ENUMERATING) {
                 // Update torch status if it has a flash unit.
@@ -4981,7 +5044,7 @@
             }
 
             Mutex::Autolock lock(mStatusListenerLock);
-            notifyPhysicalCameraStatusLocked(mapToInterface(status), String16(cameraId),
+            notifyPhysicalCameraStatusLocked(mapToInterface(status), cameraId,
                     logicalCameraIds, deviceKind);
 
             for (auto& listener : mListenerList) {
@@ -4994,7 +5057,7 @@
                     continue;
                 }
                 auto ret = listener->getListener()->onStatusChanged(mapToInterface(status),
-                        String16(cameraId));
+                        cameraId);
                 listener->handleBinderStatus(ret,
                         "%s: Failed to trigger onStatusChanged callback for %d:%d: %d",
                         __FUNCTION__, listener->getListenerUid(), listener->getListenerPid(),
@@ -5003,18 +5066,18 @@
         });
 }
 
-void CameraService::updateOpenCloseStatus(const String8& cameraId, bool open,
-        const String16& clientPackageName) {
+void CameraService::updateOpenCloseStatus(const std::string& cameraId, bool open,
+        const std::string& clientPackageName) {
     auto state = getCameraState(cameraId);
     if (state == nullptr) {
         ALOGW("%s: Could not update the status for %s, no such device exists", __FUNCTION__,
-                cameraId.string());
+                cameraId.c_str());
         return;
     }
     if (open) {
-        state->setClientPackage(String8(clientPackageName));
+        state->setClientPackage(clientPackageName);
     } else {
-        state->setClientPackage(String8::empty());
+        state->setClientPackage(std::string());
     }
 
     Mutex::Autolock lock(mStatusListenerLock);
@@ -5025,11 +5088,10 @@
         }
 
         binder::Status ret;
-        String16 cameraId64(cameraId);
         if (open) {
-            ret = it->getListener()->onCameraOpened(cameraId64, clientPackageName);
+            ret = it->getListener()->onCameraOpened(cameraId, clientPackageName);
         } else {
-            ret = it->getListener()->onCameraClosed(cameraId64);
+            ret = it->getListener()->onCameraClosed(cameraId);
         }
 
         it->handleBinderStatus(ret,
@@ -5040,7 +5102,7 @@
 
 template<class Func>
 void CameraService::CameraState::updateStatus(StatusInternal status,
-        const String8& cameraId,
+        const std::string& cameraId,
         std::initializer_list<StatusInternal> rejectSourceStates,
         Func onStatusUpdatedLocked) {
     Mutex::Autolock lock(mStatusLock);
@@ -5052,7 +5114,7 @@
     }
 
     ALOGV("%s: Status has changed for camera ID %s from %#x to %#x", __FUNCTION__,
-            cameraId.string(), oldStatus, status);
+            cameraId.c_str(), oldStatus, status);
 
     if (oldStatus == StatusInternal::NOT_PRESENT &&
             (status != StatusInternal::PRESENT &&
@@ -5072,7 +5134,7 @@
     for (auto& rejectStatus : rejectSourceStates) {
         if (oldStatus == rejectStatus) {
             ALOGV("%s: Rejecting status transition for Camera ID %s,  since the source "
-                    "state was was in one of the bad states.", __FUNCTION__, cameraId.string());
+                    "state was was in one of the bad states.", __FUNCTION__, cameraId.c_str());
             mStatus = oldStatus;
             return;
         }
@@ -5082,7 +5144,7 @@
 }
 
 status_t CameraService::getTorchStatusLocked(
-        const String8& cameraId,
+        const std::string& cameraId,
         TorchModeStatus *status) const {
     if (!status) {
         return BAD_VALUE;
@@ -5097,7 +5159,7 @@
     return OK;
 }
 
-status_t CameraService::setTorchStatusLocked(const String8& cameraId,
+status_t CameraService::setTorchStatusLocked(const std::string& cameraId,
         TorchModeStatus status) {
     ssize_t index = mTorchStatusMap.indexOfKey(cameraId);
     if (index == NAME_NOT_FOUND) {
@@ -5108,20 +5170,20 @@
     return OK;
 }
 
-std::list<String16> CameraService::getLogicalCameras(
-        const String8& physicalCameraId) {
-    std::list<String16> retList;
+std::list<std::string> CameraService::getLogicalCameras(
+        const std::string& physicalCameraId) {
+    std::list<std::string> retList;
     Mutex::Autolock lock(mCameraStatesLock);
     for (const auto& state : mCameraStates) {
-        if (state.second->containsPhysicalCamera(physicalCameraId.c_str())) {
-            retList.emplace_back(String16(state.first));
+        if (state.second->containsPhysicalCamera(physicalCameraId)) {
+            retList.emplace_back(state.first);
         }
     }
     return retList;
 }
 
 void CameraService::notifyPhysicalCameraStatusLocked(int32_t status,
-        const String16& physicalCameraId, const std::list<String16>& logicalCameraIds,
+        const std::string& physicalCameraId, const std::list<std::string>& logicalCameraIds,
         SystemCameraKind deviceKind) {
     // mStatusListenerLock is expected to be locked
     for (const auto& logicalCameraId : logicalCameraIds) {
@@ -5132,7 +5194,7 @@
             if (shouldSkipStatusUpdates(deviceKind, listener->isVendorListener(),
                     listener->getListenerPid(), listener->getListenerUid())) {
                 ALOGV("Skipping discovery callback for system-only camera device %s",
-                        String8(physicalCameraId).c_str());
+                        physicalCameraId.c_str());
                 continue;
             }
             auto ret = listener->getListener()->onPhysicalCameraStatusChanged(status,
@@ -5172,44 +5234,44 @@
 
 // NOTE: This is a remote API - make sure all args are validated
 status_t CameraService::shellCommand(int in, int out, int err, const Vector<String16>& args) {
-    if (!checkCallingPermission(sManageCameraPermission, nullptr, nullptr)) {
+    if (!checkCallingPermission(toString16(sManageCameraPermission), nullptr, nullptr)) {
         return PERMISSION_DENIED;
     }
     if (in == BAD_TYPE || out == BAD_TYPE || err == BAD_TYPE) {
         return BAD_VALUE;
     }
-    if (args.size() >= 3 && args[0] == String16("set-uid-state")) {
+    if (args.size() >= 3 && args[0] == toString16("set-uid-state")) {
         return handleSetUidState(args, err);
-    } else if (args.size() >= 2 && args[0] == String16("reset-uid-state")) {
+    } else if (args.size() >= 2 && args[0] == toString16("reset-uid-state")) {
         return handleResetUidState(args, err);
-    } else if (args.size() >= 2 && args[0] == String16("get-uid-state")) {
+    } else if (args.size() >= 2 && args[0] == toString16("get-uid-state")) {
         return handleGetUidState(args, out, err);
-    } else if (args.size() >= 2 && args[0] == String16("set-rotate-and-crop")) {
+    } else if (args.size() >= 2 && args[0] == toString16("set-rotate-and-crop")) {
         return handleSetRotateAndCrop(args);
-    } else if (args.size() >= 1 && args[0] == String16("get-rotate-and-crop")) {
+    } else if (args.size() >= 1 && args[0] == toString16("get-rotate-and-crop")) {
         return handleGetRotateAndCrop(out);
-    } else if (args.size() >= 2 && args[0] == String16("set-autoframing")) {
+    } else if (args.size() >= 2 && args[0] == toString16("set-autoframing")) {
         return handleSetAutoframing(args);
-    } else if (args.size() >= 1 && args[0] == String16("get-autoframing")) {
+    } else if (args.size() >= 1 && args[0] == toString16("get-autoframing")) {
         return handleGetAutoframing(out);
-    } else if (args.size() >= 2 && args[0] == String16("set-image-dump-mask")) {
+    } else if (args.size() >= 2 && args[0] == toString16("set-image-dump-mask")) {
         return handleSetImageDumpMask(args);
-    } else if (args.size() >= 1 && args[0] == String16("get-image-dump-mask")) {
+    } else if (args.size() >= 1 && args[0] == toString16("get-image-dump-mask")) {
         return handleGetImageDumpMask(out);
-    } else if (args.size() >= 2 && args[0] == String16("set-camera-mute")) {
+    } else if (args.size() >= 2 && args[0] == toString16("set-camera-mute")) {
         return handleSetCameraMute(args);
-    } else if (args.size() >= 2 && args[0] == String16("set-stream-use-case-override")) {
+    } else if (args.size() >= 2 && args[0] == toString16("set-stream-use-case-override")) {
         return handleSetStreamUseCaseOverrides(args);
-    } else if (args.size() >= 1 && args[0] == String16("clear-stream-use-case-override")) {
+    } else if (args.size() >= 1 && args[0] == toString16("clear-stream-use-case-override")) {
         handleClearStreamUseCaseOverrides();
         return OK;
-    } else if (args.size() >= 1 && args[0] == String16("set-zoom-override")) {
+    } else if (args.size() >= 1 && args[0] == toString16("set-zoom-override")) {
         return handleSetZoomOverride(args);
-    } else if (args.size() >= 2 && args[0] == String16("watch")) {
+    } else if (args.size() >= 2 && args[0] == toString16("watch")) {
         return handleWatchCommand(args, in, out);
-    } else if (args.size() >= 2 && args[0] == String16("set-watchdog")) {
+    } else if (args.size() >= 2 && args[0] == toString16("set-watchdog")) {
         return handleSetCameraServiceWatchdog(args);
-    } else if (args.size() == 1 && args[0] == String16("help")) {
+    } else if (args.size() == 1 && args[0] == toString16("help")) {
         printHelp(out);
         return OK;
     }
@@ -5218,19 +5280,19 @@
 }
 
 status_t CameraService::handleSetUidState(const Vector<String16>& args, int err) {
-    String16 packageName = args[1];
+    std::string packageName = toStdString(args[1]);
 
     bool active = false;
-    if (args[2] == String16("active")) {
+    if (args[2] == toString16("active")) {
         active = true;
-    } else if ((args[2] != String16("idle"))) {
-        ALOGE("Expected active or idle but got: '%s'", String8(args[2]).string());
+    } else if ((args[2] != toString16("idle"))) {
+        ALOGE("Expected active or idle but got: '%s'", toStdString(args[2]).c_str());
         return BAD_VALUE;
     }
 
     int userId = 0;
-    if (args.size() >= 5 && args[3] == String16("--user")) {
-        userId = atoi(String8(args[4]));
+    if (args.size() >= 5 && args[3] == toString16("--user")) {
+        userId = atoi(toStdString(args[4]).c_str());
     }
 
     uid_t uid;
@@ -5243,11 +5305,11 @@
 }
 
 status_t CameraService::handleResetUidState(const Vector<String16>& args, int err) {
-    String16 packageName = args[1];
+    std::string packageName = toStdString(args[1]);
 
     int userId = 0;
-    if (args.size() >= 4 && args[2] == String16("--user")) {
-        userId = atoi(String8(args[3]));
+    if (args.size() >= 4 && args[2] == toString16("--user")) {
+        userId = atoi(toStdString(args[3]).c_str());
     }
 
     uid_t uid;
@@ -5260,11 +5322,11 @@
 }
 
 status_t CameraService::handleGetUidState(const Vector<String16>& args, int out, int err) {
-    String16 packageName = args[1];
+    std::string packageName = toStdString(args[1]);
 
     int userId = 0;
-    if (args.size() >= 4 && args[2] == String16("--user")) {
-        userId = atoi(String8(args[3]));
+    if (args.size() >= 4 && args[2] == toString16("--user")) {
+        userId = atoi(toStdString(args[3]).c_str());
     }
 
     uid_t uid;
@@ -5280,7 +5342,7 @@
 }
 
 status_t CameraService::handleSetRotateAndCrop(const Vector<String16>& args) {
-    int rotateValue = atoi(String8(args[1]));
+    int rotateValue = atoi(toStdString(args[1]).c_str());
     if (rotateValue < ANDROID_SCALER_ROTATE_AND_CROP_NONE ||
             rotateValue > ANDROID_SCALER_ROTATE_AND_CROP_AUTO) return BAD_VALUE;
     Mutex::Autolock lock(mServiceLock);
@@ -5304,7 +5366,7 @@
 
 status_t CameraService::handleSetAutoframing(const Vector<String16>& args) {
     char* end;
-    int autoframingValue = (int) strtol(String8(args[1]), &end, /*base=*/10);
+    int autoframingValue = (int) strtol(toStdString(args[1]).c_str(), &end, /*base=*/10);
     if ((*end != '\0') ||
             (autoframingValue != ANDROID_CONTROL_AUTOFRAMING_OFF &&
              autoframingValue != ANDROID_CONTROL_AUTOFRAMING_ON &&
@@ -5331,7 +5393,7 @@
 }
 
 status_t CameraService::handleSetCameraServiceWatchdog(const Vector<String16>& args) {
-    int enableWatchdog = atoi(String8(args[1]));
+    int enableWatchdog = atoi(toStdString(args[1]).c_str());
 
     if (enableWatchdog < 0 || enableWatchdog > 1) return BAD_VALUE;
 
@@ -5367,11 +5429,11 @@
 status_t CameraService::handleSetImageDumpMask(const Vector<String16>& args) {
     char *endPtr;
     errno = 0;
-    String8 maskString8 = String8(args[1]);
-    long maskValue = strtol(maskString8.c_str(), &endPtr, 10);
+    std::string maskString = toStdString(args[1]);
+    long maskValue = strtol(maskString.c_str(), &endPtr, 10);
 
     if (errno != 0) return BAD_VALUE;
-    if (endPtr != maskString8.c_str() + maskString8.size()) return BAD_VALUE;
+    if (endPtr != maskString.c_str() + maskString.size()) return BAD_VALUE;
     if (maskValue < 0 || maskValue > 1) return BAD_VALUE;
 
     Mutex::Autolock lock(mServiceLock);
@@ -5388,7 +5450,7 @@
 }
 
 status_t CameraService::handleSetCameraMute(const Vector<String16>& args) {
-    int muteValue = strtol(String8(args[1]), nullptr, 10);
+    int muteValue = strtol(toStdString(args[1]).c_str(), nullptr, 10);
     if (errno != 0) return BAD_VALUE;
 
     if (muteValue < 0 || muteValue > 1) return BAD_VALUE;
@@ -5415,23 +5477,23 @@
     std::vector<int64_t> useCasesOverride;
     for (size_t i = 1; i < args.size(); i++) {
         int64_t useCase = ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_DEFAULT;
-        String8 arg8 = String8(args[i]);
-        if (arg8 == "DEFAULT") {
+        std::string arg = toStdString(args[i]);
+        if (arg == "DEFAULT") {
             useCase = ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_DEFAULT;
-        } else if (arg8 == "PREVIEW") {
+        } else if (arg == "PREVIEW") {
             useCase = ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_PREVIEW;
-        } else if (arg8 == "STILL_CAPTURE") {
+        } else if (arg == "STILL_CAPTURE") {
             useCase = ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_STILL_CAPTURE;
-        } else if (arg8 == "VIDEO_RECORD") {
+        } else if (arg == "VIDEO_RECORD") {
             useCase = ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_VIDEO_RECORD;
-        } else if (arg8 == "PREVIEW_VIDEO_STILL") {
+        } else if (arg == "PREVIEW_VIDEO_STILL") {
             useCase = ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_PREVIEW_VIDEO_STILL;
-        } else if (arg8 == "VIDEO_CALL") {
+        } else if (arg == "VIDEO_CALL") {
             useCase = ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_VIDEO_CALL;
-        } else if (arg8 == "CROPPED_RAW") {
+        } else if (arg == "CROPPED_RAW") {
             useCase = ANDROID_SCALER_AVAILABLE_STREAM_USE_CASES_CROPPED_RAW;
         } else {
-            ALOGE("%s: Invalid stream use case %s", __FUNCTION__, arg8.c_str());
+            ALOGE("%s: Invalid stream use case %s", __FUNCTION__, arg.c_str());
             return BAD_VALUE;
         }
         useCasesOverride.push_back(useCase);
@@ -5450,7 +5512,7 @@
 
 status_t CameraService::handleSetZoomOverride(const Vector<String16>& args) {
     char* end;
-    int zoomOverrideValue = strtol(String8(args[1]), &end, /*base=*/10);
+    int zoomOverrideValue = strtol(toStdString(args[1]).c_str(), &end, /*base=*/10);
     if ((*end != '\0') ||
             (zoomOverrideValue != -1 &&
              zoomOverrideValue != ANDROID_CONTROL_SETTINGS_OVERRIDE_OFF &&
@@ -5477,15 +5539,15 @@
 }
 
 status_t CameraService::handleWatchCommand(const Vector<String16>& args, int inFd, int outFd) {
-    if (args.size() >= 3 && args[1] == String16("start")) {
+    if (args.size() >= 3 && args[1] == toString16("start")) {
         return startWatchingTags(args, outFd);
-    } else if (args.size() == 2 && args[1] == String16("stop")) {
+    } else if (args.size() == 2 && args[1] == toString16("stop")) {
         return stopWatchingTags(outFd);
-    } else if (args.size() == 2 && args[1] == String16("dump")) {
+    } else if (args.size() == 2 && args[1] == toString16("dump")) {
         return printWatchedTags(outFd);
-    } else if (args.size() >= 2 && args[1] == String16("live")) {
+    } else if (args.size() >= 2 && args[1] == toString16("live")) {
         return printWatchedTagsUntilInterrupt(args, inFd, outFd);
-    } else if (args.size() == 2 && args[1] == String16("clear")) {
+    } else if (args.size() == 2 && args[1] == toString16("clear")) {
         return clearCachedMonitoredTagDumps(outFd);
     }
     dprintf(outFd, "Camera service watch commands:\n"
@@ -5506,7 +5568,7 @@
     Mutex::Autolock lock(mLogLock);
     size_t tagsIdx; // index of '-m'
     String16 tags("");
-    for (tagsIdx = 2; tagsIdx < args.size() && args[tagsIdx] != String16("-m"); tagsIdx++);
+    for (tagsIdx = 2; tagsIdx < args.size() && args[tagsIdx] != toString16("-m"); tagsIdx++);
     if (tagsIdx < args.size() - 1) {
         tags = args[tagsIdx + 1];
     } else {
@@ -5515,16 +5577,17 @@
     }
 
     size_t clientsIdx; // index of '-c'
-    String16 clients = kWatchAllClientsFlag; // watch all clients if no clients are provided
-    for (clientsIdx = 2; clientsIdx < args.size() && args[clientsIdx] != String16("-c");
+    // watch all clients if no clients are provided
+    String16 clients = toString16(kWatchAllClientsFlag);
+    for (clientsIdx = 2; clientsIdx < args.size() && args[clientsIdx] != toString16("-c");
          clientsIdx++);
     if (clientsIdx < args.size() - 1) {
         clients = args[clientsIdx + 1];
     }
-    parseClientsToWatchLocked(String8(clients));
+    parseClientsToWatchLocked(toStdString(clients));
 
     // track tags to initialize future clients with the monitoring information
-    mMonitorTags = String8(tags);
+    mMonitorTags = toStdString(tags);
 
     bool serviceLock = tryLock(mServiceLock);
     int numWatchedClients = 0;
@@ -5548,7 +5611,7 @@
 status_t CameraService::stopWatchingTags(int outFd) {
     // clear mMonitorTags to prevent new clients from monitoring tags at initialization
     Mutex::Autolock lock(mLogLock);
-    mMonitorTags = String8::empty();
+    mMonitorTags = "";
 
     mWatchedClientPackages.clear();
     mWatchedClientsDumpCache.clear();
@@ -5576,7 +5639,7 @@
 
 status_t CameraService::printWatchedTags(int outFd) {
     Mutex::Autolock logLock(mLogLock);
-    std::set<String16> connectedMonitoredClients;
+    std::set<std::string> connectedMonitoredClients;
 
     bool printedSomething = false; // tracks if any monitoring information was printed
                                    // (from either cached or active clients)
@@ -5599,17 +5662,14 @@
         }
 
         // Print tag dumps for active client
-        const String8 &cameraId = clientDescriptor->getKey();
-        String8 packageName8 = String8(client->getPackageName());
-        const char *printablePackageName = packageName8.lockBuffer(packageName8.size());
-        dprintf(outFd, "Client: %s (active)\n", printablePackageName);
+        const std::string &cameraId = clientDescriptor->getKey();
+        dprintf(outFd, "Client: %s (active)\n", client->getPackageName().c_str());
         while(printIdx > 0) {
             printIdx--;
-            dprintf(outFd, "%s:%s  %s", cameraId.string(), printablePackageName,
+            dprintf(outFd, "%s:%s  %s", cameraId.c_str(), client->getPackageName().c_str(),
                     dumpVector[printIdx].c_str());
         }
         dprintf(outFd, "\n");
-        packageName8.unlockBuffer();
         printedSomething = true;
 
         connectedMonitoredClients.emplace(client->getPackageName());
@@ -5618,12 +5678,12 @@
 
     // Print entries in mWatchedClientsDumpCache for clients that are not connected
     for (const auto &kv: mWatchedClientsDumpCache) {
-        const String16 &package = kv.first;
+        const std::string &package = kv.first;
         if (connectedMonitoredClients.find(package) != connectedMonitoredClients.end()) {
             continue;
         }
 
-        dprintf(outFd, "Client: %s (cached)\n", String8(package).string());
+        dprintf(outFd, "Client: %s (cached)\n", package.c_str());
         dprintf(outFd, "%s\n", kv.second.c_str());
         printedSomething = true;
     }
@@ -5637,8 +5697,8 @@
 
 // Print all events in vector `events' that came after lastPrintedEvent
 void printNewWatchedEvents(int outFd,
-                           const char *cameraId,
-                           const String16 &packageName,
+                           const std::string &cameraId,
+                           const std::string &packageName,
                            const std::vector<std::string> &events,
                            const std::string &lastPrintedEvent) {
     if (events.empty()) { return; }
@@ -5652,17 +5712,13 @@
 
     if (lastPrintedIdx == 0) { return; } // early exit if no new event in `events`
 
-    String8 packageName8(packageName);
-    const char *printablePackageName = packageName8.lockBuffer(packageName8.size());
-
     // print events in chronological order (latest event last)
     size_t idxToPrint = lastPrintedIdx;
     do {
         idxToPrint--;
-        dprintf(outFd, "%s:%s  %s", cameraId, printablePackageName, events[idxToPrint].c_str());
+        dprintf(outFd, "%s:%s  %s", cameraId.c_str(), packageName.c_str(),
+                events[idxToPrint].c_str());
     } while (idxToPrint != 0);
-
-    packageName8.unlockBuffer();
 }
 
 // Returns true if adb shell cmd watch should be interrupted based on data in inFd. The watch
@@ -5739,12 +5795,12 @@
     long refreshTimeoutMs = 1000L; // refresh every 1s by default
     if (args.size() > 2) {
         size_t intervalIdx; // index of '-n'
-        for (intervalIdx = 2; intervalIdx < args.size() && String16("-n") != args[intervalIdx];
+        for (intervalIdx = 2; intervalIdx < args.size() && toString16("-n") != args[intervalIdx];
              intervalIdx++);
 
         size_t intervalValIdx = intervalIdx + 1;
         if (intervalValIdx < args.size()) {
-            refreshTimeoutMs = strtol(String8(args[intervalValIdx].string()), nullptr, 10);
+            refreshTimeoutMs = strtol(toStdString(args[intervalValIdx]).c_str(), nullptr, 10);
             if (errno) { return BAD_VALUE; }
         }
     }
@@ -5753,7 +5809,7 @@
     refreshTimeoutMs = refreshTimeoutMs < 10 ? 10 : refreshTimeoutMs;
 
     dprintf(outFd, "Press return to exit...\n\n");
-    std::map<String16, std::string> packageNameToLastEvent;
+    std::map<std::string, std::string> packageNameToLastEvent;
 
     while (true) {
         bool serviceLock = tryLock(mServiceLock);
@@ -5768,7 +5824,7 @@
             if (client.get() == nullptr) { continue; }
             if (!isClientWatchedLocked(client.get())) { continue; }
 
-            const String16 &packageName = client->getPackageName();
+            const std::string &packageName = client->getPackageName();
             // This also initializes the map entries with an empty string
             const std::string& lastPrintedEvent = packageNameToLastEvent[packageName];
 
@@ -5776,15 +5832,12 @@
             client->dumpWatchedEventsToVector(latestEvents);
 
             if (!latestEvents.empty()) {
-                String8 cameraId = clientDescriptor->getKey();
-                const char *printableCameraId = cameraId.lockBuffer(cameraId.size());
                 printNewWatchedEvents(outFd,
-                                      printableCameraId,
+                                      clientDescriptor->getKey(),
                                       packageName,
                                       latestEvents,
                                       lastPrintedEvent);
                 packageNameToLastEvent[packageName] = latestEvents[0];
-                cameraId.unlockBuffer();
             }
         }
         if (shouldInterruptWatchCommand(inFd, outFd, refreshTimeoutMs)) {
@@ -5794,17 +5847,14 @@
     return OK;
 }
 
-void CameraService::parseClientsToWatchLocked(String8 clients) {
+void CameraService::parseClientsToWatchLocked(const std::string &clients) {
     mWatchedClientPackages.clear();
 
-    const char *allSentinel = String8(kWatchAllClientsFlag).string();
+    std::istringstream iss(clients);
+    std::string nextClient;
 
-    char *tokenized = clients.lockBuffer(clients.size());
-    char *savePtr;
-    char *nextClient = strtok_r(tokenized, ",", &savePtr);
-
-    while (nextClient != nullptr) {
-        if (strcmp(nextClient, allSentinel) == 0) {
+    while (std::getline(iss, nextClient, ',')) {
+        if (nextClient == kWatchAllClientsFlag) {
             // Don't need to track any other package if 'all' is present
             mWatchedClientPackages.clear();
             mWatchedClientPackages.emplace(kWatchAllClientsFlag);
@@ -5813,9 +5863,7 @@
 
         // track package names
         mWatchedClientPackages.emplace(nextClient);
-        nextClient = strtok_r(nullptr, ",", &savePtr);
     }
-    clients.unlockBuffer();
 }
 
 status_t CameraService::printHelp(int out) {
@@ -5879,13 +5927,13 @@
     return mode;
 }
 
-status_t CameraService::checkIfInjectionCameraIsPresent(const String8& externalCamId,
+status_t CameraService::checkIfInjectionCameraIsPresent(const std::string& externalCamId,
         sp<BasicClient> clientSp) {
     std::unique_ptr<AutoConditionLock> lock =
             AutoConditionLock::waitAndAcquire(mServiceLockWrapper);
     status_t res = NO_ERROR;
     if ((res = checkIfDeviceIsUsable(externalCamId)) != NO_ERROR) {
-        ALOGW("Device %s is not usable!", externalCamId.string());
+        ALOGW("Device %s is not usable!", externalCamId.c_str());
         mInjectionStatusListener->notifyInjectionError(
                 externalCamId, UNKNOWN_TRANSACTION);
         clientSp->notifyError(
diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h
index 3214d4c..b1ff6a5 100644
--- a/services/camera/libcameraservice/CameraService.h
+++ b/services/camera/libcameraservice/CameraService.h
@@ -17,6 +17,7 @@
 #ifndef ANDROID_SERVERS_CAMERA_CAMERASERVICE_H
 #define ANDROID_SERVERS_CAMERA_CAMERASERVICE_H
 
+#include <android/content/AttributionSourceState.h>
 #include <android/hardware/BnCameraService.h>
 #include <android/hardware/BnSensorPrivacyListener.h>
 #include <android/hardware/ICameraServiceListener.h>
@@ -119,19 +120,19 @@
     /////////////////////////////////////////////////////////////////////
     // HAL Callbacks - implements CameraProviderManager::StatusListener
 
-    virtual void        onDeviceStatusChanged(const String8 &cameraId,
+    virtual void        onDeviceStatusChanged(const std::string &cameraId,
             CameraDeviceStatus newHalStatus) override;
-    virtual void        onDeviceStatusChanged(const String8 &cameraId,
-            const String8 &physicalCameraId,
+    virtual void        onDeviceStatusChanged(const std::string &cameraId,
+            const std::string &physicalCameraId,
             CameraDeviceStatus newHalStatus) override;
     // This method may hold CameraProviderManager::mInterfaceMutex as a part
     // of calling getSystemCameraKind() internally. Care should be taken not to
     // directly / indirectly call this from callers who also hold
     // mInterfaceMutex.
-    virtual void        onTorchStatusChanged(const String8& cameraId,
+    virtual void        onTorchStatusChanged(const std::string& cameraId,
             TorchModeStatus newStatus) override;
     // Does not hold CameraProviderManager::mInterfaceMutex.
-    virtual void        onTorchStatusChanged(const String8& cameraId,
+    virtual void        onTorchStatusChanged(const std::string& cameraId,
             TorchModeStatus newStatus,
             SystemCameraKind kind) override;
     virtual void        onNewProviderRegistered() override;
@@ -142,7 +143,7 @@
 
     virtual binder::Status     getCameraInfo(int cameraId, bool overrideToPortrait,
             hardware::CameraInfo* cameraInfo) override;
-    virtual binder::Status     getCameraCharacteristics(const String16& cameraId,
+    virtual binder::Status     getCameraCharacteristics(const std::string& cameraId,
             int targetSdkVersion, bool overrideToPortrait, CameraMetadata* cameraInfo) override;
     virtual binder::Status     getCameraVendorTagDescriptor(
             /*out*/
@@ -152,15 +153,16 @@
             hardware::camera2::params::VendorTagDescriptorCache* cache);
 
     virtual binder::Status     connect(const sp<hardware::ICameraClient>& cameraClient,
-            int32_t cameraId, const String16& clientPackageName,
+            int32_t cameraId, const std::string& clientPackageName,
             int32_t clientUid, int clientPid, int targetSdkVersion,
             bool overrideToPortrait, bool forceSlowJpegMode,
             /*out*/
             sp<hardware::ICamera>* device) override;
 
     virtual binder::Status     connectDevice(
-            const sp<hardware::camera2::ICameraDeviceCallbacks>& cameraCb, const String16& cameraId,
-            const String16& clientPackageName, const std::optional<String16>& clientFeatureId,
+            const sp<hardware::camera2::ICameraDeviceCallbacks>& cameraCb,
+            const std::string& cameraId,
+            const std::string& clientPackageName, const std::optional<std::string>& clientFeatureId,
             int32_t clientUid, int scoreOffset, int targetSdkVersion, bool overrideToPortrait,
             /*out*/
             sp<hardware::camera2::ICameraDeviceUser>* device);
@@ -182,15 +184,15 @@
     virtual binder::Status    getLegacyParameters(
             int32_t cameraId,
             /*out*/
-            String16* parameters);
+            std::string* parameters);
 
-    virtual binder::Status    setTorchMode(const String16& cameraId, bool enabled,
+    virtual binder::Status    setTorchMode(const std::string& cameraId, bool enabled,
             const sp<IBinder>& clientBinder);
 
-    virtual binder::Status    turnOnTorchWithStrengthLevel(const String16& cameraId,
+    virtual binder::Status    turnOnTorchWithStrengthLevel(const std::string& cameraId,
             int32_t torchStrength, const sp<IBinder>& clientBinder);
 
-    virtual binder::Status    getTorchStrengthLevel(const String16& cameraId,
+    virtual binder::Status    getTorchStrengthLevel(const std::string& cameraId,
             int32_t* torchStrength);
 
     virtual binder::Status    notifySystemEvent(int32_t eventId,
@@ -202,24 +204,24 @@
 
     // OK = supports api of that version, -EOPNOTSUPP = does not support
     virtual binder::Status    supportsCameraApi(
-            const String16& cameraId, int32_t apiVersion,
+            const std::string& cameraId, int32_t apiVersion,
             /*out*/
             bool *isSupported);
 
     virtual binder::Status    isHiddenPhysicalCamera(
-            const String16& cameraId,
+            const std::string& cameraId,
             /*out*/
             bool *isSupported);
 
     virtual binder::Status injectCamera(
-            const String16& packageName, const String16& internalCamId,
-            const String16& externalCamId,
+            const std::string& packageName, const std::string& internalCamId,
+            const std::string& externalCamId,
             const sp<hardware::camera2::ICameraInjectionCallback>& callback,
             /*out*/
             sp<hardware::camera2::ICameraInjectionSession>* cameraInjectionSession);
 
     virtual binder::Status reportExtensionSessionStats(
-            const hardware::CameraExtensionSessionStats& stats, String16* sessionKey /*out*/);
+            const hardware::CameraExtensionSessionStats& stats, std::string* sessionKey /*out*/);
 
     // Extra permissions checks
     virtual status_t    onTransact(uint32_t code, const Parcel& data,
@@ -242,7 +244,7 @@
     void cacheDump();
 
     // Register an offline client for a given active camera id
-    status_t addOfflineClient(String8 cameraId, sp<BasicClient> offlineClient);
+    status_t addOfflineClient(const std::string &cameraId, sp<BasicClient> offlineClient);
 
     /////////////////////////////////////////////////////////////////////
     // Client functionality
@@ -261,7 +263,7 @@
 
     /////////////////////////////////////////////////////////////////////
     // CameraDeviceFactory functionality
-    std::pair<int, IPCTransport>    getDeviceVersion(const String8& cameraId,
+    std::pair<int, IPCTransport>    getDeviceVersion(const std::string& cameraId,
             bool overrideToPortrait, int* portraitRotation,
             int* facing = nullptr, int* orientation = nullptr);
 
@@ -289,7 +291,7 @@
     friend class CameraService;
     public:
         virtual status_t       initialize(sp<CameraProviderManager> manager,
-                const String8& monitorTags) = 0;
+                const std::string& monitorTags) = 0;
         virtual binder::Status disconnect();
 
         // because we can't virtually inherit IInterface, which breaks
@@ -310,12 +312,12 @@
         // Internal dump method to be called by CameraService
         virtual status_t dumpClient(int fd, const Vector<String16>& args) = 0;
 
-        virtual status_t startWatchingTags(const String8 &tags, int outFd);
+        virtual status_t startWatchingTags(const std::string &tags, int outFd);
         virtual status_t stopWatchingTags(int outFd);
         virtual status_t dumpWatchedEventsToVector(std::vector<std::string> &out);
 
         // Return the package name for this client
-        virtual String16 getPackageName() const;
+        virtual std::string getPackageName() const;
 
         // Return the camera facing for this client
         virtual int getCameraFacing() const;
@@ -383,7 +385,7 @@
 
         // The injection camera session to replace the internal camera
         // session.
-        virtual status_t injectCamera(const String8& injectedCamId,
+        virtual status_t injectCamera(const std::string& injectedCamId,
                 sp<CameraProviderManager> manager) = 0;
 
         // Stop the injection camera and restore to internal camera session.
@@ -392,10 +394,10 @@
     protected:
         BasicClient(const sp<CameraService>& cameraService,
                 const sp<IBinder>& remoteCallback,
-                const String16& clientPackageName,
+                const std::string& clientPackageName,
                 bool nativeClient,
-                const std::optional<String16>& clientFeatureId,
-                const String8& cameraIdStr,
+                const std::optional<std::string>& clientFeatureId,
+                const std::string& cameraIdStr,
                 int cameraFacing,
                 int sensorOrientation,
                 int clientPid,
@@ -413,12 +415,12 @@
 
         // these are initialized in the constructor.
         static sp<CameraService>        sCameraService;
-        const String8                   mCameraIdStr;
+        const std::string               mCameraIdStr;
         const int                       mCameraFacing;
         const int                       mOrientation;
-        String16                        mClientPackageName;
+        std::string                     mClientPackageName;
         bool                            mSystemNativeClient;
-        std::optional<String16>         mClientFeatureId;
+        std::optional<std::string>      mClientFeatureId;
         pid_t                           mClientPid;
         const uid_t                     mClientUid;
         const pid_t                     mServicePid;
@@ -505,10 +507,10 @@
         // Interface used by CameraService
         Client(const sp<CameraService>& cameraService,
                 const sp<hardware::ICameraClient>& cameraClient,
-                const String16& clientPackageName,
+                const std::string& clientPackageName,
                 bool systemNativeClient,
-                const std::optional<String16>& clientFeatureId,
-                const String8& cameraIdStr,
+                const std::optional<std::string>& clientFeatureId,
+                const std::string& cameraIdStr,
                 int api1CameraId,
                 int cameraFacing,
                 int sensorOrientation,
@@ -552,13 +554,13 @@
      */
     class ClientEventListener {
     public:
-        void onClientAdded(const resource_policy::ClientDescriptor<String8,
+        void onClientAdded(const resource_policy::ClientDescriptor<std::string,
                 sp<CameraService::BasicClient>>& descriptor);
-        void onClientRemoved(const resource_policy::ClientDescriptor<String8,
+        void onClientRemoved(const resource_policy::ClientDescriptor<std::string,
                 sp<CameraService::BasicClient>>& descriptor);
     }; // class ClientEventListener
 
-    typedef std::shared_ptr<resource_policy::ClientDescriptor<String8,
+    typedef std::shared_ptr<resource_policy::ClientDescriptor<std::string,
             sp<CameraService::BasicClient>>> DescriptorPtr;
 
     /**
@@ -569,7 +571,7 @@
      * This class manages the eviction behavior for the camera clients.  See the parent class
      * implementation in utils/ClientManager for the specifics of this behavior.
      */
-    class CameraClientManager : public resource_policy::ClientManager<String8,
+    class CameraClientManager : public resource_policy::ClientManager<std::string,
             sp<CameraService::BasicClient>, ClientEventListener> {
     public:
         CameraClientManager();
@@ -579,18 +581,19 @@
          * Return a strong pointer to the active BasicClient for this camera ID, or an empty
          * if none exists.
          */
-        sp<CameraService::BasicClient> getCameraClient(const String8& id) const;
+        sp<CameraService::BasicClient> getCameraClient(const std::string& id) const;
 
         /**
          * Return a string describing the current state.
          */
-        String8 toString() const;
+        std::string toString() const;
 
         /**
          * Make a ClientDescriptor object wrapping the given BasicClient strong pointer.
          */
-        static DescriptorPtr makeClientDescriptor(const String8& key, const sp<BasicClient>& value,
-                int32_t cost, const std::set<String8>& conflictingKeys, int32_t score,
+        static DescriptorPtr makeClientDescriptor(const std::string& key,
+                const sp<BasicClient>& value, int32_t cost,
+                const std::set<std::string>& conflictingKeys, int32_t score,
                 int32_t ownerId, int32_t state, int oomScoreOffset, bool systemNativeClient);
 
         /**
@@ -607,6 +610,13 @@
     int32_t updateAudioRestrictionLocked();
 
 private:
+    /**
+     * Returns true if the device is an automotive device and cameraId is system
+     * only camera which has characteristic AUTOMOTIVE_LOCATION value as either
+     * AUTOMOTIVE_LOCATION_EXTERIOR_LEFT,AUTOMOTIVE_LOCATION_EXTERIOR_RIGHT,
+     * AUTOMOTIVE_LOCATION_EXTERIOR_FRONT or AUTOMOTIVE_LOCATION_EXTERIOR_REAR.
+     */
+    bool isAutomotiveExteriorSystemCamera(const std::string& cameraId) const;
 
     // TODO: b/263304156 update this to make use of a death callback for more
     // robust/fault tolerant logging
@@ -623,6 +633,22 @@
     }
 
     /**
+     * Pre-grants the permission if the attribution source uid is for an automotive
+     * privileged client. Otherwise uses system service permission checker to check
+     * for the appropriate permission. If this function is called for accessing a specific
+     * camera,then the cameraID must not be empty. CameraId is used only in case of automotive
+     * privileged client so that permission is pre-granted only to access system camera device
+     * which is located outside of the vehicle body frame because camera located inside the vehicle
+     * cabin would need user permission.
+     */
+    bool checkPermission(const std::string& cameraId, const std::string& permission,
+            const content::AttributionSourceState& attributionSource, const std::string& message,
+            int32_t attributedOpCode) const;
+
+    bool hasPermissionsForSystemCamera(const std::string& cameraId, int callingPid, int callingUid)
+            const;
+
+   /**
      * Typesafe version of device status, containing both the HAL-layer and the service interface-
      * layer values.
      */
@@ -650,7 +676,7 @@
          * Make a new CameraState and set the ID, cost, and conflicting devices using the values
          * returned in the HAL's camera_info struct for each device.
          */
-        CameraState(const String8& id, int cost, const std::set<String8>& conflicting,
+        CameraState(const std::string& id, int cost, const std::set<std::string>& conflicting,
                 SystemCameraKind deviceKind, const std::vector<std::string>& physicalCameras);
         virtual ~CameraState();
 
@@ -664,7 +690,7 @@
         /**
          * This function updates the status for this camera device, unless the given status
          * is in the given list of rejected status states, and execute the function passed in
-         * with a signature onStatusUpdateLocked(const String8&, int32_t)
+         * with a signature onStatusUpdateLocked(const std::string&, int32_t)
          * if the status has changed.
          *
          * This method is idempotent, and will not result in the function passed to
@@ -673,7 +699,7 @@
          */
         template<class Func>
         void updateStatus(StatusInternal status,
-                const String8& cameraId,
+                const std::string& cameraId,
                 std::initializer_list<StatusInternal> rejectSourceStates,
                 Func onStatusUpdatedLocked);
 
@@ -696,12 +722,7 @@
         /**
          * Return a set of the IDs of conflicting devices advertised by the HAL for this device.
          */
-        std::set<String8> getConflicting() const;
-
-        /**
-         * Return the ID of this camera device.
-         */
-        String8 getId() const;
+        std::set<std::string> getConflicting() const;
 
         /**
          * Return the kind (SystemCameraKind) of this camera device.
@@ -717,28 +738,28 @@
         /**
          * Add/Remove the unavailable physical camera ID.
          */
-        bool addUnavailablePhysicalId(const String8& physicalId);
-        bool removeUnavailablePhysicalId(const String8& physicalId);
+        bool addUnavailablePhysicalId(const std::string& physicalId);
+        bool removeUnavailablePhysicalId(const std::string& physicalId);
 
         /**
          * Set and get client package name.
          */
-        void setClientPackage(const String8& clientPackage);
-        String8 getClientPackage() const;
+        void setClientPackage(const std::string& clientPackage);
+        std::string getClientPackage() const;
 
         /**
          * Return the unavailable physical ids for this device.
          *
          * This method acquires mStatusLock.
          */
-        std::vector<String8> getUnavailablePhysicalIds() const;
+        std::vector<std::string> getUnavailablePhysicalIds() const;
     private:
-        const String8 mId;
+        const std::string mId;
         StatusInternal mStatus; // protected by mStatusLock
         const int mCost;
-        std::set<String8> mConflicting;
-        std::set<String8> mUnavailablePhysicalIds;
-        String8 mClientPackage;
+        std::set<std::string> mConflicting;
+        std::set<std::string> mUnavailablePhysicalIds;
+        std::string mClientPackage;
         mutable Mutex mStatusLock;
         CameraParameters mShimParams;
         const SystemCameraKind mSystemCameraKind;
@@ -758,7 +779,7 @@
         void registerSelf();
         void unregisterSelf();
 
-        bool isUidActive(uid_t uid, String16 callingPackage);
+        bool isUidActive(uid_t uid, const std::string &callingPackage);
         int32_t getProcState(uid_t uid);
 
         // IUidObserver
@@ -769,8 +790,8 @@
                 int32_t capability) override;
         void onUidProcAdjChanged(uid_t uid, int adj) override;
 
-        void addOverrideUid(uid_t uid, String16 callingPackage, bool active);
-        void removeOverrideUid(uid_t uid, String16 callingPackage);
+        void addOverrideUid(uid_t uid, const std::string &callingPackage, bool active);
+        void removeOverrideUid(uid_t uid, const std::string &callingPackage);
 
         void registerMonitorUid(uid_t uid, bool openCamera);
         void unregisterMonitorUid(uid_t uid, bool closeCamera);
@@ -781,9 +802,10 @@
         // IBinder::DeathRecipient implementation
         virtual void binderDied(const wp<IBinder> &who);
     private:
-        bool isUidActiveLocked(uid_t uid, String16 callingPackage);
+        bool isUidActiveLocked(uid_t uid, const std::string &callingPackage);
         int32_t getProcStateLocked(uid_t uid);
-        void updateOverrideUid(uid_t uid, String16 callingPackage, bool active, bool insert);
+        void updateOverrideUid(uid_t uid, const std::string &callingPackage, bool active,
+                bool insert);
         void registerWithActivityManager();
 
         struct MonitoredUid {
@@ -853,8 +875,8 @@
 
     // Add/remove a new camera to camera and torch state lists or remove an unplugged one
     // Caller must not hold mServiceLock
-    void addStates(const String8 id);
-    void removeStates(const String8 id);
+    void addStates(const std::string& id);
+    void removeStates(const std::string& id);
 
     // Check if we can connect, before we acquire the service lock.
     // The returned originalClientPid is the PID of the original process that wants to connect to
@@ -863,36 +885,37 @@
     // originalClientPid and clientPid are usually the same except when the application uses
     // mediaserver to connect to camera (using MediaRecorder to connect to camera). In that case,
     // clientPid is the PID of mediaserver and originalClientPid is the PID of the application.
-    binder::Status validateConnectLocked(const String8& cameraId, const String8& clientName8,
+    binder::Status validateConnectLocked(const std::string& cameraId, const std::string& clientName,
             /*inout*/int& clientUid, /*inout*/int& clientPid, /*out*/int& originalClientPid) const;
-    binder::Status validateClientPermissionsLocked(const String8& cameraId, const String8& clientName8,
-            /*inout*/int& clientUid, /*inout*/int& clientPid, /*out*/int& originalClientPid) const;
+    binder::Status validateClientPermissionsLocked(const std::string& cameraId,
+            const std::string& clientName, /*inout*/int& clientUid, /*inout*/int& clientPid,
+            /*out*/int& originalClientPid) const;
 
     // Handle active client evictions, and update service state.
     // Only call with with mServiceLock held.
-    status_t handleEvictionsLocked(const String8& cameraId, int clientPid,
-        apiLevel effectiveApiLevel, const sp<IBinder>& remoteCallback, const String8& packageName,
-        int scoreOffset, bool systemNativeClient,
+    status_t handleEvictionsLocked(const std::string& cameraId, int clientPid,
+        apiLevel effectiveApiLevel, const sp<IBinder>& remoteCallback,
+        const std::string& packageName, int scoreOffset, bool systemNativeClient,
         /*out*/
         sp<BasicClient>* client,
-        std::shared_ptr<resource_policy::ClientDescriptor<String8, sp<BasicClient>>>* partial);
+        std::shared_ptr<resource_policy::ClientDescriptor<std::string, sp<BasicClient>>>* partial);
 
     // 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 shouldRejectSystemCameraConnection(const std::string& cameraId) const;
 
     // 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,
+    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;
+    status_t getSystemCameraKind(const std::string& 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
@@ -908,13 +931,13 @@
     // as for legacy apps we will toggle the app op for all packages in the UID.
     // The caveat is that the operation may be attributed to the wrong package and
     // stats based on app ops may be slightly off.
-    String16 getPackageNameFromUid(int clientUid);
+    std::string getPackageNameFromUid(int clientUid);
 
     // 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, const String16& clientPackageNameMaybe, bool systemNativeClient,
-            const std::optional<String16>& clientFeatureId, int clientUid, int clientPid,
+    binder::Status connectHelper(const sp<CALLBACK>& cameraCb, const std::string& cameraId,
+            int api1CameraId, const std::string& clientPackageNameMaybe, bool systemNativeClient,
+            const std::optional<std::string>& clientFeatureId, int clientUid, int clientPid,
             apiLevel effectiveApiLevel, bool shimUpdateOnly, int scoreOffset, int targetSdkVersion,
             bool overrideToPortrait, bool forceSlowJpegMode,
             /*out*/sp<CLIENT>& device);
@@ -926,37 +949,38 @@
     std::shared_ptr<WaitableMutexWrapper> mServiceLockWrapper;
 
     // Return NO_ERROR if the device with a give ID can be connected to
-    status_t checkIfDeviceIsUsable(const String8& cameraId) const;
+    status_t checkIfDeviceIsUsable(const std::string& cameraId) const;
 
     // Container for managing currently active application-layer clients
     CameraClientManager mActiveClientManager;
 
     // Adds client logs during open session to the file pointed by fd.
-    void dumpOpenSessionClientLogs(int fd, const Vector<String16>& args, const String8& cameraId);
+    void dumpOpenSessionClientLogs(int fd, const Vector<String16>& args,
+            const std::string& cameraId);
 
     // Adds client logs during closed session to the file pointed by fd.
-    void dumpClosedSessionClientLogs(int fd, const String8& cameraId);
+    void dumpClosedSessionClientLogs(int fd, const std::string& cameraId);
 
     // Mapping from camera ID -> state for each device, map is protected by mCameraStatesLock
-    std::map<String8, std::shared_ptr<CameraState>> mCameraStates;
+    std::map<std::string, std::shared_ptr<CameraState>> mCameraStates;
 
     // Mutex guarding mCameraStates map
     mutable Mutex mCameraStatesLock;
 
     // Circular buffer for storing event logging for dumps
-    RingBuffer<String8> mEventLog;
+    RingBuffer<std::string> mEventLog;
     Mutex mLogLock;
 
     // set of client package names to watch. if this set contains 'all', then all clients will
     // be watched. Access should be guarded by mLogLock
-    std::set<String16> mWatchedClientPackages;
+    std::set<std::string> mWatchedClientPackages;
     // cache of last monitored tags dump immediately before the client disconnects. If a client
     // re-connects, its entry is not updated until it disconnects again. Access should be guarded
     // by mLogLock
-    std::map<String16, std::string> mWatchedClientsDumpCache;
+    std::map<std::string, std::string> mWatchedClientsDumpCache;
 
     // The last monitored tags set by client
-    String8 mMonitorTags;
+    std::string mMonitorTags;
 
     // Currently allowed user IDs
     std::set<userid_t> mAllowedUsers;
@@ -966,7 +990,7 @@
      *
      * This acquires mCameraStatesLock.
      */
-    std::shared_ptr<CameraService::CameraState> getCameraState(const String8& cameraId) const;
+    std::shared_ptr<CameraService::CameraState> getCameraState(const std::string& cameraId) const;
 
     /**
      * Evict client who's remote binder has died.  Returns true if this client was in the active
@@ -997,7 +1021,7 @@
      * Returns the underlying camera Id string mapped to a camera id int
      * Empty string is returned when the cameraIdInt is invalid.
      */
-    String8 cameraIdIntToStr(int cameraIdInt);
+    std::string cameraIdIntToStr(int cameraIdInt);
 
     /**
      * Returns the underlying camera Id string mapped to a camera id int
@@ -1011,7 +1035,7 @@
      *
      * This method must be called with mServiceLock held.
      */
-    sp<CameraService::BasicClient> removeClientLocked(const String8& cameraId);
+    sp<CameraService::BasicClient> removeClientLocked(const std::string& cameraId);
 
     /**
      * Handle a notification that the current device user has changed.
@@ -1021,39 +1045,41 @@
     /**
      * Add an event log message.
      */
-    void logEvent(const char* event);
+    void logEvent(const std::string &event);
 
     /**
      * Add an event log message that a client has been disconnected.
      */
-    void logDisconnected(const char* cameraId, int clientPid, const char* clientPackage);
+    void logDisconnected(const std::string &cameraId, int clientPid,
+            const std::string &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);
+    void logDisconnectedOffline(const std::string &cameraId, int clientPid,
+            const std::string &clientPackage);
 
     /**
      * Add an event log message that an offline client has been connected.
      */
-    void logConnectedOffline(const char* cameraId, int clientPid,
-            const char* clientPackage);
+    void logConnectedOffline(const std::string &cameraId, int clientPid,
+            const std::string &clientPackage);
 
     /**
      * Add an event log message that a client has been connected.
      */
-    void logConnected(const char* cameraId, int clientPid, const char* clientPackage);
+    void logConnected(const std::string &cameraId, int clientPid, const std::string &clientPackage);
 
     /**
      * Add an event log message that a client's connect attempt has been rejected.
      */
-    void logRejected(const char* cameraId, int clientPid, const char* clientPackage,
-            const char* reason);
+    void logRejected(const std::string &cameraId, int clientPid, const std::string &clientPackage,
+            const std::string &reason);
 
     /**
      * Add an event log message when a client calls setTorchMode succesfully.
      */
-    void logTorchEvent(const char* cameraId, const char *torchState, int clientPid);
+    void logTorchEvent(const std::string &cameraId, const std::string &torchState, int clientPid);
 
     /**
      * Add an event log message that the current device user has been switched.
@@ -1064,30 +1090,30 @@
     /**
      * Add an event log message that a device has been removed by the HAL
      */
-    void logDeviceRemoved(const char* cameraId, const char* reason);
+    void logDeviceRemoved(const std::string &cameraId, const std::string &reason);
 
     /**
      * Add an event log message that a device has been added by the HAL
      */
-    void logDeviceAdded(const char* cameraId, const char* reason);
+    void logDeviceAdded(const std::string &cameraId, const std::string &reason);
 
     /**
      * Add an event log message that a client has unexpectedly died.
      */
-    void logClientDied(int clientPid, const char* reason);
+    void logClientDied(int clientPid, const std::string &reason);
 
     /**
      * Add a event log message that a serious service-level error has occured
      * The errorCode should be one of the Android Errors
      */
-    void logServiceError(const char* msg, int errorCode);
+    void logServiceError(const std::string &msg, int errorCode);
 
     /**
      * Dump the event log to an FD
      */
     void dumpEventLog(int fd);
 
-    void cacheClientTagDumpIfNeeded(const char *cameraId, BasicClient *client);
+    void cacheClientTagDumpIfNeeded(const std::string &cameraId, BasicClient *client);
 
     /**
      * This method will acquire mServiceLock
@@ -1203,18 +1229,19 @@
      * This method acquires mStatusLock and mStatusListenerLock.
      */
     void updateStatus(StatusInternal status,
-            const String8& cameraId,
+            const std::string& cameraId,
             std::initializer_list<StatusInternal>
                 rejectedSourceStates);
     void updateStatus(StatusInternal status,
-            const String8& cameraId);
+            const std::string& cameraId);
 
     /**
      * Update the opened/closed status of the given camera id.
      *
      * This method acqiures mStatusListenerLock.
      */
-    void updateOpenCloseStatus(const String8& cameraId, bool open, const String16& packageName);
+    void updateOpenCloseStatus(const std::string& cameraId, bool open,
+            const std::string& packageName);
 
     // flashlight control
     sp<CameraFlashlight> mFlashlight;
@@ -1225,38 +1252,38 @@
     // guard mTorchUidMap
     Mutex                mTorchUidMapMutex;
     // camera id -> torch status
-    KeyedVector<String8, TorchModeStatus>
+    KeyedVector<std::string, TorchModeStatus>
             mTorchStatusMap;
     // camera id -> torch client binder
     // only store the last client that turns on each camera's torch mode
-    KeyedVector<String8, sp<IBinder>> mTorchClientMap;
+    KeyedVector<std::string, sp<IBinder>> mTorchClientMap;
     // camera id -> [incoming uid, current uid] pair
-    std::map<String8, std::pair<int, int>> mTorchUidMap;
+    std::map<std::string, std::pair<int, int>> mTorchUidMap;
 
     // check and handle if torch client's process has died
     void handleTorchClientBinderDied(const wp<IBinder> &who);
 
     // handle torch mode status change and invoke callbacks. mTorchStatusMutex
     // should be locked.
-    void onTorchStatusChangedLocked(const String8& cameraId,
+    void onTorchStatusChangedLocked(const std::string& cameraId,
             TorchModeStatus newStatus,
             SystemCameraKind systemCameraKind);
 
     // get a camera's torch status. mTorchStatusMutex should be locked.
-    status_t getTorchStatusLocked(const String8 &cameraId,
+    status_t getTorchStatusLocked(const std::string &cameraId,
              TorchModeStatus *status) const;
 
     // set a camera's torch status. mTorchStatusMutex should be locked.
-    status_t setTorchStatusLocked(const String8 &cameraId,
+    status_t setTorchStatusLocked(const std::string &cameraId,
             TorchModeStatus status);
 
     // notify physical camera status when the physical camera is public.
     // Expects mStatusListenerLock to be locked.
-    void notifyPhysicalCameraStatusLocked(int32_t status, const String16& physicalCameraId,
-            const std::list<String16>& logicalCameraIds, SystemCameraKind deviceKind);
+    void notifyPhysicalCameraStatusLocked(int32_t status, const std::string& physicalCameraId,
+            const std::list<std::string>& logicalCameraIds, SystemCameraKind deviceKind);
 
     // get list of logical cameras which are backed by physicalCameraId
-    std::list<String16> getLogicalCameras(const String8& physicalCameraId);
+    std::list<std::string> getLogicalCameras(const std::string& physicalCameraId);
 
 
     // IBinder::DeathRecipient implementation
@@ -1348,7 +1375,7 @@
     // Parses comma separated clients list and adds them to mWatchedClientPackages.
     // Does not acquire mLogLock before modifying mWatchedClientPackages. It is the caller's
     // responsibility to acquire mLogLock before calling this function.
-    void parseClientsToWatchLocked(String8 clients);
+    void parseClientsToWatchLocked(const std::string &clients);
 
     // Prints the shell command help
     status_t printHelp(int out);
@@ -1365,39 +1392,37 @@
     /**
      * Get the current system time as a formatted string.
      */
-    static String8 getFormattedCurrentTime();
+    static std::string getFormattedCurrentTime();
 
     static binder::Status makeClient(const sp<CameraService>& cameraService,
-            const sp<IInterface>& cameraCb, const String16& packageName,
-            bool systemNativeClient, const std::optional<String16>& featureId,
-            const String8& cameraId, int api1CameraId, int facing, int sensorOrientation,
+            const sp<IInterface>& cameraCb, const std::string& packageName,
+            bool systemNativeClient, const std::optional<std::string>& featureId,
+            const std::string& cameraId, int api1CameraId, int facing, int sensorOrientation,
             int clientPid, uid_t clientUid, int servicePid,
             std::pair<int, IPCTransport> deviceVersionAndIPCTransport, apiLevel effectiveApiLevel,
             bool overrideForPerfClass, bool overrideToPortrait, bool forceSlowJpegMode,
             /*out*/sp<BasicClient>* client);
 
-    status_t checkCameraAccess(const String16& opPackageName);
-
-    static String8 toString(std::set<userid_t> intSet);
+    static std::string toString(std::set<userid_t> intSet);
     static int32_t mapToInterface(TorchModeStatus status);
     static StatusInternal mapToInternal(CameraDeviceStatus status);
     static int32_t mapToInterface(StatusInternal status);
 
 
-    void broadcastTorchModeStatus(const String8& cameraId,
+    void broadcastTorchModeStatus(const std::string& cameraId,
             TorchModeStatus status, SystemCameraKind systemCameraKind);
 
-    void broadcastTorchStrengthLevel(const String8& cameraId, int32_t newTorchStrengthLevel);
+    void broadcastTorchStrengthLevel(const std::string& cameraId, int32_t newTorchStrengthLevel);
 
-    void disconnectClient(const String8& id, sp<BasicClient> clientToDisconnect);
+    void disconnectClient(const std::string& 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;
+    static const std::string kOfflineDevice;
 
     // Sentinel value to be stored in `mWatchedClientsPackages` to indicate that all clients should
     // be watched.
-    static const String16 kWatchAllClientsFlag;
+    static const std::string kWatchAllClientsFlag;
 
     // TODO: right now each BasicClient holds one AppOpsManager instance.
     // We can refactor the code so all of clients share this instance
@@ -1438,7 +1463,7 @@
 
             void addListener(const sp<hardware::camera2::ICameraInjectionCallback>& callback);
             void removeListener();
-            void notifyInjectionError(String8 injectedCamId, status_t err);
+            void notifyInjectionError(const std::string &injectedCamId, status_t err);
 
             // IBinder::DeathRecipient implementation
             virtual void binderDied(const wp<IBinder>& who);
@@ -1467,15 +1492,15 @@
 
     // When injecting the camera, it will check whether the injecting camera status is unavailable.
     // If it is, the disconnect function will be called to to prevent camera access on the device.
-    status_t checkIfInjectionCameraIsPresent(const String8& externalCamId,
+    status_t checkIfInjectionCameraIsPresent(const std::string& externalCamId,
             sp<BasicClient> clientSp);
 
     void clearInjectionParameters();
 
     // This is the existing camera id being replaced.
-    String8 mInjectionInternalCamId;
+    std::string mInjectionInternalCamId;
     // This is the external camera Id replacing the internalId.
-    String8 mInjectionExternalCamId;
+    std::string mInjectionExternalCamId;
     bool mInjectionInitPending = false;
     // Guard mInjectionInternalCamId and mInjectionInitPending.
     Mutex mInjectionParametersLock;
@@ -1483,7 +1508,7 @@
     // Track the folded/unfoled device state. 0 == UNFOLDED, 4 == FOLDED
     int64_t mDeviceState;
 
-    void updateTorchUidMapLocked(const String16& cameraId, int uid);
+    void updateTorchUidMapLocked(const std::string& cameraId, int uid);
 };
 
 } // namespace android
diff --git a/services/camera/libcameraservice/CameraServiceWatchdog.h b/services/camera/libcameraservice/CameraServiceWatchdog.h
index de6ac9e..9f25865 100644
--- a/services/camera/libcameraservice/CameraServiceWatchdog.h
+++ b/services/camera/libcameraservice/CameraServiceWatchdog.h
@@ -32,7 +32,6 @@
 #include <chrono>
 #include <thread>
 #include <time.h>
-#include <utils/String8.h>
 #include <utils/Thread.h>
 #include <utils/Log.h>
 #include <unordered_map>
@@ -58,13 +57,13 @@
 };
 
 public:
-    explicit CameraServiceWatchdog(const String8 &cameraId,
+    explicit CameraServiceWatchdog(const std::string &cameraId,
             std::shared_ptr<CameraServiceProxyWrapper> cameraServiceProxyWrapper) :
                     mCameraId(cameraId), mPause(true), mMaxCycles(kMaxCycles),
                     mCycleLengthMs(kCycleLengthMs), mEnabled(true),
                     mCameraServiceProxyWrapper(cameraServiceProxyWrapper) {};
 
-    explicit CameraServiceWatchdog (const String8 &cameraId, size_t maxCycles,
+    explicit CameraServiceWatchdog (const std::string &cameraId, size_t maxCycles,
             uint32_t cycleLengthMs, bool enabled,
             std::shared_ptr<CameraServiceProxyWrapper> cameraServiceProxyWrapper) :
                     mCameraId(cameraId), mPause(true), mMaxCycles(maxCycles),
@@ -151,7 +150,7 @@
     Mutex           mWatchdogLock;      // Lock for condition variable
     Mutex           mEnabledLock;       // Lock for enabled status
     Condition       mWatchdogCondition; // Condition variable for stop/start
-    String8         mCameraId;          // Camera Id the watchdog belongs to
+    std::string     mCameraId;          // Camera Id the watchdog belongs to
     bool            mPause;             // True if tid map is empty
     uint32_t        mMaxCycles;         // Max cycles
     uint32_t        mCycleLengthMs;     // Length of time elapsed per cycle
diff --git a/services/camera/libcameraservice/aidl/AidlCameraService.cpp b/services/camera/libcameraservice/aidl/AidlCameraService.cpp
index 4232a81..a62f6de 100644
--- a/services/camera/libcameraservice/aidl/AidlCameraService.cpp
+++ b/services/camera/libcameraservice/aidl/AidlCameraService.cpp
@@ -86,7 +86,7 @@
     if (_aidl_return == nullptr) { return fromSStatus(SStatus::ILLEGAL_ARGUMENT); }
 
     ::android::CameraMetadata cameraMetadata;
-    UStatus ret = mCameraService->getCameraCharacteristics(String16(in_cameraId.c_str()),
+    UStatus ret = mCameraService->getCameraCharacteristics(in_cameraId,
                                                            mVndkVersion,
                                                            /* overrideToPortrait= */ false,
                                                            &cameraMetadata);
@@ -140,8 +140,8 @@
     sp<hardware::camera2::ICameraDeviceCallbacks> callbacks = hybridCallbacks;
     binder::Status serviceRet = mCameraService->connectDevice(
             callbacks,
-            String16(in_cameraId.c_str()),
-            String16(""),
+            in_cameraId,
+            std::string(),
             /* clientFeatureId= */{},
             hardware::ICameraService::USE_CALLING_UID,
             /* scoreOffset= */ 0,
@@ -249,7 +249,7 @@
             [this](const hardware::CameraStatus& s) {
                 bool supportsHAL3 = false;
                 binder::Status sRet =
-                            mCameraService->supportsCameraApi(String16(s.cameraId),
+                            mCameraService->supportsCameraApi(s.cameraId,
                                     UICameraService::API_VERSION_2, &supportsHAL3);
                 return !sRet.isOk() || !supportsHAL3;
             }), cameraStatusAndIds->end());
diff --git a/services/camera/libcameraservice/aidl/AidlCameraServiceListener.cpp b/services/camera/libcameraservice/aidl/AidlCameraServiceListener.cpp
index e183063..d7ab0d9 100644
--- a/services/camera/libcameraservice/aidl/AidlCameraServiceListener.cpp
+++ b/services/camera/libcameraservice/aidl/AidlCameraServiceListener.cpp
@@ -18,6 +18,7 @@
 #include <aidl/AidlUtils.h>
 #include <aidl/android/frameworks/cameraservice/common/Status.h>
 #include <aidl/android/frameworks/cameraservice/service/CameraStatusAndId.h>
+#include <camera/StringUtils.h>
 
 namespace android::frameworks::cameraservice::service::implementation {
 
@@ -27,34 +28,31 @@
 using SStatus = ::aidl::android::frameworks::cameraservice::common::Status;
 
 binder::Status AidlCameraServiceListener::onStatusChanged(
-        int32_t status, const ::android::String16& cameraId) {
+        int32_t status, const std::string& cameraId) {
     SCameraDeviceStatus sStatus = convertCameraStatusToAidl(status);
-    std::string sCameraId = String8(cameraId).string();
-    auto ret = mBase->onStatusChanged(sStatus, sCameraId);
+    auto ret = mBase->onStatusChanged(sStatus, cameraId);
     LOG_STATUS_ERROR_IF_NOT_OK(ret, "onStatusChanged")
     return binder::Status::ok();
 }
 
 binder::Status AidlCameraServiceListener::onPhysicalCameraStatusChanged(
-        int32_t status, const ::android::String16& cameraId,
-        const ::android::String16& physicalCameraId) {
+        int32_t status, const std::string& cameraId,
+        const std::string& physicalCameraId) {
     SCameraDeviceStatus sStatus = convertCameraStatusToAidl(status);
-    std::string sCameraId = String8(cameraId).string();
-    std::string sPhysicalCameraId = String8(physicalCameraId).string();
 
-    auto ret = mBase->onPhysicalCameraStatusChanged(sStatus, sCameraId, sPhysicalCameraId);
+    auto ret = mBase->onPhysicalCameraStatusChanged(sStatus, cameraId, physicalCameraId);
     LOG_STATUS_ERROR_IF_NOT_OK(ret, "onPhysicalCameraStatusChanged")
     return binder::Status::ok();
 }
 
 ::android::binder::Status AidlCameraServiceListener::onTorchStatusChanged(
-    int32_t, const ::android::String16&) {
+    int32_t, const std::string&) {
   // We don't implement onTorchStatusChanged
   return binder::Status::ok();
 }
 
 ::android::binder::Status AidlCameraServiceListener::onTorchStrengthLevelChanged(
-    const ::android::String16&, int32_t) {
+    const std::string&, int32_t) {
     // We don't implement onTorchStrengthLevelChanged
     return binder::Status::ok();
 }
diff --git a/services/camera/libcameraservice/aidl/AidlCameraServiceListener.h b/services/camera/libcameraservice/aidl/AidlCameraServiceListener.h
index 906dd8e..6483fe1 100644
--- a/services/camera/libcameraservice/aidl/AidlCameraServiceListener.h
+++ b/services/camera/libcameraservice/aidl/AidlCameraServiceListener.h
@@ -45,25 +45,25 @@
     ~AidlCameraServiceListener() = default;
 
     ::android::binder::Status onStatusChanged(int32_t status,
-            const ::android::String16& cameraId) override;
+            const std::string& cameraId) override;
     ::android::binder::Status onPhysicalCameraStatusChanged(int32_t status,
-            const ::android::String16& cameraId,
-            const ::android::String16& physicalCameraId) override;
+            const std::string& cameraId,
+            const std::string& physicalCameraId) override;
 
     ::android::binder::Status onTorchStatusChanged(
-            int32_t status, const ::android::String16& cameraId) override;
+            int32_t status, const std::string& cameraId) override;
     ::android::binder::Status onTorchStrengthLevelChanged(
-            const ::android::String16& cameraId, int32_t newStrengthLevel) override;
+            const std::string& cameraId, int32_t newStrengthLevel) override;
     binder::Status onCameraAccessPrioritiesChanged() override {
         // TODO: no implementation yet.
         return binder::Status::ok();
     }
-    binder::Status onCameraOpened(const ::android::String16& /*cameraId*/,
-            const ::android::String16& /*clientPackageId*/) override {
+    binder::Status onCameraOpened(const std::string& /*cameraId*/,
+            const std::string& /*clientPackageId*/) override {
         // empty implementation
         return binder::Status::ok();
     }
-    binder::Status onCameraClosed(const ::android::String16& /*cameraId*/) override {
+    binder::Status onCameraClosed(const std::string& /*cameraId*/) override {
         // empty implementation
         return binder::Status::ok();
     }
diff --git a/services/camera/libcameraservice/aidl/AidlUtils.cpp b/services/camera/libcameraservice/aidl/AidlUtils.cpp
index 1b8e53b..7291c5f 100644
--- a/services/camera/libcameraservice/aidl/AidlUtils.cpp
+++ b/services/camera/libcameraservice/aidl/AidlUtils.cpp
@@ -22,6 +22,7 @@
 #include <device3/Camera3StreamInterface.h>
 #include <gui/bufferqueue/1.0/H2BGraphicBufferProducer.h>
 #include <mediautils/AImageReaderUtils.h>
+#include <camera/StringUtils.h>
 
 namespace android::hardware::cameraservice::utils::conversion::aidl {
 
@@ -80,9 +81,8 @@
         iGBPs.push_back(new H2BGraphicBufferProducer(AImageReader_getHGBPFromHandle(nh)));
         native_handle_delete(nh);
     }
-    String16 physicalCameraId16(src.physicalCameraId.c_str());
     UOutputConfiguration outputConfiguration(
-        iGBPs, convertFromAidl(src.rotation), physicalCameraId16,
+        iGBPs, convertFromAidl(src.rotation), src.physicalCameraId,
         src.windowGroupId, OutputConfiguration::SURFACE_TYPE_UNKNOWN, 0, 0,
         (windowHandles.size() > 1));
     return outputConfiguration;
@@ -175,7 +175,7 @@
     dst.frameNumber = src.frameNumber;
     dst.partialResultCount = src.partialResultCount;
     dst.errorStreamId = src.errorStreamId;
-    dst.errorPhysicalCameraId = String8(src.errorPhysicalCameraId).string();
+    dst.errorPhysicalCameraId = src.errorPhysicalCameraId;
     return dst;
 }
 
@@ -217,7 +217,7 @@
 SPhysicalCaptureResultInfo convertToAidl(const UPhysicalCaptureResultInfo & src,
                                          std::shared_ptr<CaptureResultMetadataQueue> & fmq) {
     SPhysicalCaptureResultInfo dst;
-    dst.physicalCameraId = String8(src.mPhysicalCameraId).string();
+    dst.physicalCameraId = src.mPhysicalCameraId;
 
     const camera_metadata_t *rawMetadata = src.mPhysicalCameraMetadata.getAndLock();
     // Try using fmq at first.
@@ -242,12 +242,12 @@
     size_t i = 0;
     for (const auto &statusAndId : src) {
         auto &a = (*dst)[i++];
-        a.cameraId = statusAndId.cameraId.c_str();
+        a.cameraId = statusAndId.cameraId;
         a.deviceStatus = convertCameraStatusToAidl(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();
+            a.unavailPhysicalCameraIds[j] = statusAndId.unavailablePhysicalIds[j];
         }
     }
 }
@@ -302,4 +302,4 @@
     return OK;
 }
 
-} // namespace android::hardware::cameraservice::utils::conversion::aidl
\ No newline at end of file
+} // namespace android::hardware::cameraservice::utils::conversion::aidl
diff --git a/services/camera/libcameraservice/api1/Camera2Client.cpp b/services/camera/libcameraservice/api1/Camera2Client.cpp
index 8348cd9..4876195 100644
--- a/services/camera/libcameraservice/api1/Camera2Client.cpp
+++ b/services/camera/libcameraservice/api1/Camera2Client.cpp
@@ -18,11 +18,14 @@
 #define ATRACE_TAG ATRACE_TAG_CAMERA
 //#define LOG_NDEBUG 0
 
+#include <sstream>
+
 #include <inttypes.h>
 #include <utils/Log.h>
 #include <utils/Trace.h>
 
 #include <camera/CameraUtils.h>
+#include <camera/StringUtils.h>
 #include <cutils/properties.h>
 #include <gui/Surface.h>
 #include <android/hardware/camera2/ICameraDeviceCallbacks.h>
@@ -53,9 +56,9 @@
 Camera2Client::Camera2Client(const sp<CameraService>& cameraService,
         const sp<hardware::ICameraClient>& cameraClient,
         std::shared_ptr<CameraServiceProxyWrapper> cameraServiceProxyWrapper,
-        const String16& clientPackageName,
-        const std::optional<String16>& clientFeatureId,
-        const String8& cameraDeviceId,
+        const std::string& clientPackageName,
+        const std::optional<std::string>& clientFeatureId,
+        const std::string& cameraDeviceId,
         int api1CameraId,
         int cameraFacing,
         int sensorOrientation,
@@ -83,7 +86,8 @@
     l.mParameters.isSlowJpegModeForced = forceSlowJpegMode;
 }
 
-status_t Camera2Client::initialize(sp<CameraProviderManager> manager, const String8& monitorTags) {
+status_t Camera2Client::initialize(sp<CameraProviderManager> manager,
+        const std::string& monitorTags) {
     return initializeImpl(manager, monitorTags);
 }
 
@@ -103,7 +107,7 @@
 }
 
 template<typename TProviderPtr>
-status_t Camera2Client::initializeImpl(TProviderPtr providerPtr, const String8& monitorTags)
+status_t Camera2Client::initializeImpl(TProviderPtr providerPtr, const std::string& monitorTags)
 {
     ATRACE_CALL();
     ALOGV("%s: Initializing client for camera %d", __FUNCTION__, mCameraId);
@@ -135,16 +139,11 @@
     CameraUtils::getRotationTransform(staticInfo, OutputConfiguration::MIRROR_MODE_AUTO,
             &mRotateAndCropPreviewTransform);
 
-    String8 threadName;
-
     mStreamingProcessor = new StreamingProcessor(this);
-    threadName = String8::format("C2-%d-StreamProc",
-            mCameraId);
 
+    std::string threadName = std::string("C2-") + std::to_string(mCameraId);
     mFrameProcessor = new FrameProcessor(mDevice, this);
-    threadName = String8::format("C2-%d-FrameProc",
-            mCameraId);
-    res = mFrameProcessor->run(threadName.string());
+    res = mFrameProcessor->run((threadName + "-FrameProc").c_str());
     if (res != OK) {
         ALOGE("%s: Unable to start frame processor thread: %s (%d)",
                 __FUNCTION__, strerror(-res), res);
@@ -152,9 +151,7 @@
     }
 
     mCaptureSequencer = new CaptureSequencer(this);
-    threadName = String8::format("C2-%d-CaptureSeq",
-            mCameraId);
-    res = mCaptureSequencer->run(threadName.string());
+    res = mCaptureSequencer->run((threadName + "-CaptureSeq").c_str());
     if (res != OK) {
         ALOGE("%s: Unable to start capture sequencer thread: %s (%d)",
                 __FUNCTION__, strerror(-res), res);
@@ -162,9 +159,7 @@
     }
 
     mJpegProcessor = new JpegProcessor(this, mCaptureSequencer);
-    threadName = String8::format("C2-%d-JpegProc",
-            mCameraId);
-    res = mJpegProcessor->run(threadName.string());
+    res = mJpegProcessor->run((threadName + "-JpegProc").c_str());
     if (res != OK) {
         ALOGE("%s: Unable to start jpeg processor thread: %s (%d)",
                 __FUNCTION__, strerror(-res), res);
@@ -172,10 +167,7 @@
     }
 
     mZslProcessor = new ZslProcessor(this, mCaptureSequencer);
-
-    threadName = String8::format("C2-%d-ZslProc",
-            mCameraId);
-    res = mZslProcessor->run(threadName.string());
+    res = mZslProcessor->run((threadName + "-ZslProc").c_str());
     if (res != OK) {
         ALOGE("%s: Unable to start zsl processor thread: %s (%d)",
                 __FUNCTION__, strerror(-res), res);
@@ -183,9 +175,7 @@
     }
 
     mCallbackProcessor = new CallbackProcessor(this);
-    threadName = String8::format("C2-%d-CallbkProc",
-            mCameraId);
-    res = mCallbackProcessor->run(threadName.string());
+    res = mCallbackProcessor->run((threadName + "-CallbkProc").c_str());
     if (res != OK) {
         ALOGE("%s: Unable to start callback processor thread: %s (%d)",
                 __FUNCTION__, strerror(-res), res);
@@ -218,47 +208,47 @@
 }
 
 status_t Camera2Client::dumpClient(int fd, const Vector<String16>& args) {
-    String8 result;
-    result.appendFormat("Client2[%d] (%p) PID: %d, dump:\n", mCameraId,
+    std::ostringstream result;
+    result << fmt::sprintf("Client2[%d] (%p) PID: %d, dump:\n", mCameraId,
             (getRemoteCallback() != NULL ?
-                    (IInterface::asBinder(getRemoteCallback()).get()) : NULL),
+                    (void *) (IInterface::asBinder(getRemoteCallback()).get()) : NULL),
             mClientPid);
-    result.append("  State: ");
-#define CASE_APPEND_ENUM(x) case x: result.append(#x "\n"); break;
+    result << "  State: ";
+#define CASE_APPEND_ENUM(x) case x: result << #x "\n"; break;
 
     const Parameters& p = mParameters.unsafeAccess();
 
-    result.append(Parameters::getStateName(p.state));
+    result << Parameters::getStateName(p.state);
 
-    result.append("\n  Current parameters:\n");
-    result.appendFormat("    Preview size: %d x %d\n",
+    result << "\n  Current parameters:\n";
+    result << fmt::sprintf("    Preview size: %d x %d\n",
             p.previewWidth, p.previewHeight);
-    result.appendFormat("    Preview FPS range: %d - %d\n",
+    result << fmt::sprintf("    Preview FPS range: %d - %d\n",
             p.previewFpsRange[0], p.previewFpsRange[1]);
-    result.appendFormat("    Preview HAL pixel format: 0x%x\n",
+    result << fmt::sprintf("    Preview HAL pixel format: 0x%x\n",
             p.previewFormat);
-    result.appendFormat("    Preview transform: %x\n",
+    result << fmt::sprintf("    Preview transform: %x\n",
             p.previewTransform);
-    result.appendFormat("    Picture size: %d x %d\n",
+    result << fmt::sprintf("    Picture size: %d x %d\n",
             p.pictureWidth, p.pictureHeight);
-    result.appendFormat("    Jpeg thumbnail size: %d x %d\n",
+    result << fmt::sprintf("    Jpeg thumbnail size: %d x %d\n",
             p.jpegThumbSize[0], p.jpegThumbSize[1]);
-    result.appendFormat("    Jpeg quality: %d, thumbnail quality: %d\n",
+    result << fmt::sprintf("    Jpeg quality: %d, thumbnail quality: %d\n",
             p.jpegQuality, p.jpegThumbQuality);
-    result.appendFormat("    Jpeg rotation: %d\n", p.jpegRotation);
-    result.appendFormat("    GPS tags %s\n",
+    result << fmt::sprintf("    Jpeg rotation: %d\n", p.jpegRotation);
+    result << fmt::sprintf("    GPS tags %s\n",
             p.gpsEnabled ? "enabled" : "disabled");
     if (p.gpsEnabled) {
-        result.appendFormat("    GPS lat x long x alt: %f x %f x %f\n",
+        result << fmt::sprintf("    GPS lat x long x alt: %f x %f x %f\n",
                 p.gpsCoordinates[0], p.gpsCoordinates[1],
                 p.gpsCoordinates[2]);
-        result.appendFormat("    GPS timestamp: %" PRId64 "\n",
+        result << fmt::sprintf("    GPS timestamp: %" PRId64 "\n",
                 p.gpsTimestamp);
-        result.appendFormat("    GPS processing method: %s\n",
+        result << fmt::sprintf("    GPS processing method: %s\n",
                 p.gpsProcessingMethod.string());
     }
 
-    result.append("    White balance mode: ");
+    result << "    White balance mode: ";
     switch (p.wbMode) {
         CASE_APPEND_ENUM(ANDROID_CONTROL_AWB_MODE_AUTO)
         CASE_APPEND_ENUM(ANDROID_CONTROL_AWB_MODE_INCANDESCENT)
@@ -268,10 +258,10 @@
         CASE_APPEND_ENUM(ANDROID_CONTROL_AWB_MODE_CLOUDY_DAYLIGHT)
         CASE_APPEND_ENUM(ANDROID_CONTROL_AWB_MODE_TWILIGHT)
         CASE_APPEND_ENUM(ANDROID_CONTROL_AWB_MODE_SHADE)
-        default: result.append("UNKNOWN\n");
+        default: result << "UNKNOWN\n";
     }
 
-    result.append("    Effect mode: ");
+    result << "    Effect mode: ";
     switch (p.effectMode) {
         CASE_APPEND_ENUM(ANDROID_CONTROL_EFFECT_MODE_OFF)
         CASE_APPEND_ENUM(ANDROID_CONTROL_EFFECT_MODE_MONO)
@@ -282,22 +272,22 @@
         CASE_APPEND_ENUM(ANDROID_CONTROL_EFFECT_MODE_WHITEBOARD)
         CASE_APPEND_ENUM(ANDROID_CONTROL_EFFECT_MODE_BLACKBOARD)
         CASE_APPEND_ENUM(ANDROID_CONTROL_EFFECT_MODE_AQUA)
-        default: result.append("UNKNOWN\n");
+        default: result << "UNKNOWN\n";
     }
 
-    result.append("    Antibanding mode: ");
+    result << "    Antibanding mode: ";
     switch (p.antibandingMode) {
         CASE_APPEND_ENUM(ANDROID_CONTROL_AE_ANTIBANDING_MODE_AUTO)
         CASE_APPEND_ENUM(ANDROID_CONTROL_AE_ANTIBANDING_MODE_OFF)
         CASE_APPEND_ENUM(ANDROID_CONTROL_AE_ANTIBANDING_MODE_50HZ)
         CASE_APPEND_ENUM(ANDROID_CONTROL_AE_ANTIBANDING_MODE_60HZ)
-        default: result.append("UNKNOWN\n");
+        default: result << "UNKNOWN\n";
     }
 
-    result.append("    Scene mode: ");
+    result << "    Scene mode: ";
     switch (p.sceneMode) {
         case ANDROID_CONTROL_SCENE_MODE_DISABLED:
-            result.append("AUTO\n"); break;
+            result << "AUTO\n"; break;
         CASE_APPEND_ENUM(ANDROID_CONTROL_SCENE_MODE_FACE_PRIORITY)
         CASE_APPEND_ENUM(ANDROID_CONTROL_SCENE_MODE_ACTION)
         CASE_APPEND_ENUM(ANDROID_CONTROL_SCENE_MODE_PORTRAIT)
@@ -314,10 +304,10 @@
         CASE_APPEND_ENUM(ANDROID_CONTROL_SCENE_MODE_PARTY)
         CASE_APPEND_ENUM(ANDROID_CONTROL_SCENE_MODE_CANDLELIGHT)
         CASE_APPEND_ENUM(ANDROID_CONTROL_SCENE_MODE_BARCODE)
-        default: result.append("UNKNOWN\n");
+        default: result << "UNKNOWN\n";
     }
 
-    result.append("    Flash mode: ");
+    result << "    Flash mode: ";
     switch (p.flashMode) {
         CASE_APPEND_ENUM(Parameters::FLASH_MODE_OFF)
         CASE_APPEND_ENUM(Parameters::FLASH_MODE_AUTO)
@@ -325,10 +315,10 @@
         CASE_APPEND_ENUM(Parameters::FLASH_MODE_TORCH)
         CASE_APPEND_ENUM(Parameters::FLASH_MODE_RED_EYE)
         CASE_APPEND_ENUM(Parameters::FLASH_MODE_INVALID)
-        default: result.append("UNKNOWN\n");
+        default: result << "UNKNOWN\n";
     }
 
-    result.append("    Focus mode: ");
+    result << "    Focus mode: ";
     switch (p.focusMode) {
         CASE_APPEND_ENUM(Parameters::FOCUS_MODE_AUTO)
         CASE_APPEND_ENUM(Parameters::FOCUS_MODE_MACRO)
@@ -338,10 +328,10 @@
         CASE_APPEND_ENUM(Parameters::FOCUS_MODE_INFINITY)
         CASE_APPEND_ENUM(Parameters::FOCUS_MODE_FIXED)
         CASE_APPEND_ENUM(Parameters::FOCUS_MODE_INVALID)
-        default: result.append("UNKNOWN\n");
+        default: result << "UNKNOWN\n";
     }
 
-    result.append("   Focus state: ");
+    result << "   Focus state: ";
     switch (p.focusState) {
         CASE_APPEND_ENUM(ANDROID_CONTROL_AF_STATE_INACTIVE)
         CASE_APPEND_ENUM(ANDROID_CONTROL_AF_STATE_PASSIVE_SCAN)
@@ -350,12 +340,12 @@
         CASE_APPEND_ENUM(ANDROID_CONTROL_AF_STATE_ACTIVE_SCAN)
         CASE_APPEND_ENUM(ANDROID_CONTROL_AF_STATE_FOCUSED_LOCKED)
         CASE_APPEND_ENUM(ANDROID_CONTROL_AF_STATE_NOT_FOCUSED_LOCKED)
-        default: result.append("UNKNOWN\n");
+        default: result << "UNKNOWN\n";
     }
 
-    result.append("    Focusing areas:\n");
+    result << "    Focusing areas:\n";
     for (size_t i = 0; i < p.focusingAreas.size(); i++) {
-        result.appendFormat("      [ (%d, %d, %d, %d), weight %d ]\n",
+        result << fmt::sprintf("      [ (%d, %d, %d, %d), weight %d ]\n",
                 p.focusingAreas[i].left,
                 p.focusingAreas[i].top,
                 p.focusingAreas[i].right,
@@ -363,16 +353,16 @@
                 p.focusingAreas[i].weight);
     }
 
-    result.appendFormat("    Exposure compensation index: %d\n",
+    result << fmt::sprintf("    Exposure compensation index: %d\n",
             p.exposureCompensation);
 
-    result.appendFormat("    AE lock %s, AWB lock %s\n",
+    result << fmt::sprintf("    AE lock %s, AWB lock %s\n",
             p.autoExposureLock ? "enabled" : "disabled",
             p.autoWhiteBalanceLock ? "enabled" : "disabled" );
 
-    result.appendFormat("    Metering areas:\n");
+    result << "    Metering areas:\n";
     for (size_t i = 0; i < p.meteringAreas.size(); i++) {
-        result.appendFormat("      [ (%d, %d, %d, %d), weight %d ]\n",
+        result << fmt::sprintf("      [ (%d, %d, %d, %d), weight %d ]\n",
                 p.meteringAreas[i].left,
                 p.meteringAreas[i].top,
                 p.meteringAreas[i].right,
@@ -380,54 +370,56 @@
                 p.meteringAreas[i].weight);
     }
 
-    result.appendFormat("    Zoom index: %d\n", p.zoom);
-    result.appendFormat("    Video size: %d x %d\n", p.videoWidth,
+    result << fmt::sprintf("    Zoom index: %d\n", p.zoom);
+    result << fmt::sprintf("    Video size: %d x %d\n", p.videoWidth,
             p.videoHeight);
 
-    result.appendFormat("    Recording hint is %s\n",
+    result << fmt::sprintf("    Recording hint is %s\n",
             p.recordingHint ? "set" : "not set");
 
-    result.appendFormat("    Video stabilization is %s\n",
+    result << fmt::sprintf("    Video stabilization is %s\n",
             p.videoStabilization ? "enabled" : "disabled");
 
-    result.appendFormat("    Selected still capture FPS range: %d - %d\n",
+    result << fmt::sprintf("    Selected still capture FPS range: %d - %d\n",
             p.fastInfo.bestStillCaptureFpsRange[0],
             p.fastInfo.bestStillCaptureFpsRange[1]);
 
-    result.appendFormat("    Use zero shutter lag: %s\n",
+    result << fmt::sprintf("    Use zero shutter lag: %s\n",
             p.useZeroShutterLag() ? "yes" : "no");
 
-    result.append("  Current streams:\n");
-    result.appendFormat("    Preview stream ID: %d\n",
+    result << "  Current streams:\n";
+    result << fmt::sprintf("    Preview stream ID: %d\n",
             getPreviewStreamId());
-    result.appendFormat("    Capture stream ID: %d\n",
+    result << fmt::sprintf("    Capture stream ID: %d\n",
             getCaptureStreamId());
-    result.appendFormat("    Recording stream ID: %d\n",
+    result << fmt::sprintf("    Recording stream ID: %d\n",
             getRecordingStreamId());
 
-    result.append("  Quirks for this camera:\n");
+    result << "  Quirks for this camera:\n";
     bool haveQuirk = false;
     if (p.quirks.triggerAfWithAuto) {
-        result.appendFormat("    triggerAfWithAuto\n");
+        result << "    triggerAfWithAuto\n";
         haveQuirk = true;
     }
     if (p.quirks.useZslFormat) {
-        result.appendFormat("    useZslFormat\n");
+        result << "    useZslFormat\n";
         haveQuirk = true;
     }
     if (p.quirks.meteringCropRegion) {
-        result.appendFormat("    meteringCropRegion\n");
+        result << "    meteringCropRegion\n";
         haveQuirk = true;
     }
     if (p.quirks.partialResults) {
-        result.appendFormat("    usePartialResult\n");
+        result << "    usePartialResult\n";
         haveQuirk = true;
     }
     if (!haveQuirk) {
-        result.appendFormat("    none\n");
+        result << "    none\n";
     }
 
-    write(fd, result.string(), result.size());
+    std::string resultStr = std::move(result.str());
+
+    write(fd, resultStr.c_str(), resultStr.size());
 
     mStreamingProcessor->dump(fd, args);
 
diff --git a/services/camera/libcameraservice/api1/Camera2Client.h b/services/camera/libcameraservice/api1/Camera2Client.h
index 6bdb644..fe12690 100644
--- a/services/camera/libcameraservice/api1/Camera2Client.h
+++ b/services/camera/libcameraservice/api1/Camera2Client.h
@@ -107,9 +107,9 @@
     Camera2Client(const sp<CameraService>& cameraService,
             const sp<hardware::ICameraClient>& cameraClient,
             std::shared_ptr<CameraServiceProxyWrapper> cameraServiceProxyWrapper,
-            const String16& clientPackageName,
-            const std::optional<String16>& clientFeatureId,
-            const String8& cameraDeviceId,
+            const std::string& clientPackageName,
+            const std::optional<std::string>& clientFeatureId,
+            const std::string& cameraDeviceId,
             int api1CameraId,
             int cameraFacing,
             int sensorOrientation,
@@ -123,7 +123,7 @@
     virtual ~Camera2Client();
 
     virtual status_t initialize(sp<CameraProviderManager> manager,
-            const String8& monitorTags) override;
+            const std::string& monitorTags) override;
 
     virtual status_t dump(int fd, const Vector<String16>& args);
 
@@ -248,7 +248,7 @@
     status_t overrideVideoSnapshotSize(Parameters &params);
 
     template<typename TProviderPtr>
-    status_t initializeImpl(TProviderPtr providerPtr, const String8& monitorTags);
+    status_t initializeImpl(TProviderPtr providerPtr, const std::string& monitorTags);
 
     bool isZslEnabledInStillTemplate();
     // The current rotate & crop mode passed by camera service
diff --git a/services/camera/libcameraservice/api1/client2/CallbackProcessor.cpp b/services/camera/libcameraservice/api1/client2/CallbackProcessor.cpp
index ee764ec..17db20b 100644
--- a/services/camera/libcameraservice/api1/client2/CallbackProcessor.cpp
+++ b/services/camera/libcameraservice/api1/client2/CallbackProcessor.cpp
@@ -158,7 +158,7 @@
         res = device->createStream(mCallbackWindow,
                 params.previewWidth, params.previewHeight, callbackFormat,
                 HAL_DATASPACE_V0_JFIF, CAMERA_STREAM_ROTATION_0, &mCallbackStreamId,
-                String8(), std::unordered_set<int32_t>{ANDROID_SENSOR_PIXEL_MODE_DEFAULT});
+                std::string(), std::unordered_set<int32_t>{ANDROID_SENSOR_PIXEL_MODE_DEFAULT});
         if (res != OK) {
             ALOGE("%s: Camera %d: Can't create output stream for callbacks: "
                     "%s (%d)", __FUNCTION__, mId,
diff --git a/services/camera/libcameraservice/api1/client2/CaptureSequencer.cpp b/services/camera/libcameraservice/api1/client2/CaptureSequencer.cpp
index 4c9b7ed..0b5e03f 100644
--- a/services/camera/libcameraservice/api1/client2/CaptureSequencer.cpp
+++ b/services/camera/libcameraservice/api1/client2/CaptureSequencer.cpp
@@ -23,6 +23,7 @@
 #include <utils/Log.h>
 #include <utils/Trace.h>
 #include <utils/Vector.h>
+#include <camera/StringUtils.h>
 
 #include "api1/Camera2Client.h"
 #include "api1/client2/CaptureSequencer.h"
@@ -174,19 +175,19 @@
 
 
 void CaptureSequencer::dump(int fd, const Vector<String16>& /*args*/) {
-    String8 result;
+    std::string result;
     if (mCaptureRequest.entryCount() != 0) {
         result = "    Capture request:\n";
-        write(fd, result.string(), result.size());
+        write(fd, result.c_str(), result.size());
         mCaptureRequest.dump(fd, 2, 6);
     } else {
         result = "    Capture request: undefined\n";
-        write(fd, result.string(), result.size());
+        write(fd, result.c_str(), result.size());
     }
-    result = String8::format("    Current capture state: %s\n",
+    result = fmt::sprintf("    Current capture state: %s\n",
             kStateNames[mCaptureState]);
-    result.append("    Latest captured frame:\n");
-    write(fd, result.string(), result.size());
+    result += "    Latest captured frame:\n";
+    write(fd, result.c_str(), result.size());
     mNewFrame.dump(fd, 2, 6);
 }
 
diff --git a/services/camera/libcameraservice/api1/client2/JpegProcessor.cpp b/services/camera/libcameraservice/api1/client2/JpegProcessor.cpp
index 467108d..eb00bf8 100755
--- a/services/camera/libcameraservice/api1/client2/JpegProcessor.cpp
+++ b/services/camera/libcameraservice/api1/client2/JpegProcessor.cpp
@@ -83,7 +83,7 @@
     }
 
     // Find out buffer size for JPEG
-    ssize_t maxJpegSize = device->getJpegBufferSize(device->infoPhysical(String8("")),
+    ssize_t maxJpegSize = device->getJpegBufferSize(device->infoPhysical(""),
             params.pictureWidth, params.pictureHeight);
     if (maxJpegSize <= 0) {
         ALOGE("%s: Camera %d: Jpeg buffer size (%zu) is invalid ",
@@ -157,7 +157,7 @@
                 params.pictureWidth, params.pictureHeight,
                 HAL_PIXEL_FORMAT_BLOB, HAL_DATASPACE_V0_JFIF,
                 CAMERA_STREAM_ROTATION_0, &mCaptureStreamId,
-                String8(), std::unordered_set<int32_t>{ANDROID_SENSOR_PIXEL_MODE_DEFAULT});
+                std::string(), std::unordered_set<int32_t>{ANDROID_SENSOR_PIXEL_MODE_DEFAULT});
         if (res != OK) {
             ALOGE("%s: Camera %d: Can't create output stream for capture: "
                     "%s (%d)", __FUNCTION__, mId,
diff --git a/services/camera/libcameraservice/api1/client2/StreamingProcessor.cpp b/services/camera/libcameraservice/api1/client2/StreamingProcessor.cpp
index 2d3597c..ff71e6b 100644
--- a/services/camera/libcameraservice/api1/client2/StreamingProcessor.cpp
+++ b/services/camera/libcameraservice/api1/client2/StreamingProcessor.cpp
@@ -31,6 +31,7 @@
 #include <gui/BufferItem.h>
 #include <gui/Surface.h>
 #include <media/hardware/HardwareAPI.h>
+#include <camera/StringUtils.h>
 
 #include "common/CameraDeviceBase.h"
 #include "api1/Camera2Client.h"
@@ -198,7 +199,7 @@
         res = device->createStream(mPreviewWindow,
                 params.previewWidth, params.previewHeight,
                 CAMERA2_HAL_PIXEL_FORMAT_OPAQUE, HAL_DATASPACE_UNKNOWN,
-                CAMERA_STREAM_ROTATION_0, &mPreviewStreamId, String8(),
+                CAMERA_STREAM_ROTATION_0, &mPreviewStreamId, std::string(),
                 std::unordered_set<int32_t>{ANDROID_SENSOR_PIXEL_MODE_DEFAULT});
         if (res != OK) {
             ALOGE("%s: Camera %d: Unable to create preview stream: %s (%d)",
@@ -385,7 +386,7 @@
                 params.videoWidth, params.videoHeight,
                 params.videoFormat, params.videoDataSpace,
                 CAMERA_STREAM_ROTATION_0, &mRecordingStreamId,
-                String8(), std::unordered_set<int32_t>{ANDROID_SENSOR_PIXEL_MODE_DEFAULT});
+                std::string(), std::unordered_set<int32_t>{ANDROID_SENSOR_PIXEL_MODE_DEFAULT});
         if (res != OK) {
             ALOGE("%s: Camera %d: Can't create output stream for recording: "
                     "%s (%d)", __FUNCTION__, mId,
@@ -585,21 +586,21 @@
 }
 
 status_t StreamingProcessor::dump(int fd, const Vector<String16>& /*args*/) {
-    String8 result;
+    std::string result;
 
-    result.append("  Current requests:\n");
+    result += "  Current requests:\n";
     if (mPreviewRequest.entryCount() != 0) {
-        result.append("    Preview request:\n");
-        write(fd, result.string(), result.size());
+        result += "    Preview request:\n";
+        write(fd, result.c_str(), result.size());
         mPreviewRequest.dump(fd, 2, 6);
         result.clear();
     } else {
-        result.append("    Preview request: undefined\n");
+        result += "    Preview request: undefined\n";
     }
 
     if (mRecordingRequest.entryCount() != 0) {
         result = "    Recording request:\n";
-        write(fd, result.string(), result.size());
+        write(fd, result.c_str(), result.size());
         mRecordingRequest.dump(fd, 2, 6);
         result.clear();
     } else {
@@ -609,11 +610,11 @@
     const char* streamTypeString[] = {
         "none", "preview", "record"
     };
-    result.append(String8::format("   Active request: %s (paused: %s)\n",
-                                  streamTypeString[mActiveRequest],
-                                  mPaused ? "yes" : "no"));
+    result += fmt::sprintf("   Active request: %s (paused: %s\n",
+            streamTypeString[mActiveRequest],
+            mPaused ? "yes" : "no");
 
-    write(fd, result.string(), result.size());
+    write(fd, result.c_str(), result.size());
 
     return OK;
 }
diff --git a/services/camera/libcameraservice/api1/client2/ZslProcessor.cpp b/services/camera/libcameraservice/api1/client2/ZslProcessor.cpp
index 1321e6b..d6c2415 100644
--- a/services/camera/libcameraservice/api1/client2/ZslProcessor.cpp
+++ b/services/camera/libcameraservice/api1/client2/ZslProcessor.cpp
@@ -30,6 +30,7 @@
 #include <utils/Log.h>
 #include <utils/Trace.h>
 #include <gui/Surface.h>
+#include <camera/StringUtils.h>
 
 #include "common/CameraDeviceBase.h"
 #include "api1/Camera2Client.h"
@@ -255,13 +256,13 @@
         BufferQueue::createBufferQueue(&producer, &consumer);
         mProducer = new RingBufferConsumer(consumer, GRALLOC_USAGE_HW_CAMERA_ZSL,
             mBufferQueueDepth);
-        mProducer->setName(String8("Camera2-ZslRingBufferConsumer"));
+        mProducer->setName("Camera2-ZslRingBufferConsumer");
         sp<Surface> outSurface = new Surface(producer);
 
         res = device->createStream(outSurface, params.fastInfo.usedZslSize.width,
             params.fastInfo.usedZslSize.height, HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED,
             HAL_DATASPACE_UNKNOWN, CAMERA_STREAM_ROTATION_0, &mZslStreamId,
-            String8(), std::unordered_set<int32_t>{ANDROID_SENSOR_PIXEL_MODE_DEFAULT});
+            std::string(), std::unordered_set<int32_t>{ANDROID_SENSOR_PIXEL_MODE_DEFAULT});
         if (res != OK) {
             ALOGE("%s: Camera %d: Can't create ZSL stream: "
                     "%s (%d)", __FUNCTION__, client->getCameraId(),
@@ -680,12 +681,12 @@
 void ZslProcessor::dump(int fd, const Vector<String16>& /*args*/) const {
     Mutex::Autolock l(mInputMutex);
     if (!mLatestCapturedRequest.isEmpty()) {
-        String8 result("    Latest ZSL capture request:\n");
-        write(fd, result.string(), result.size());
+        std::string result = "    Latest ZSL capture request:\n";
+        write(fd, result.c_str(), result.size());
         mLatestCapturedRequest.dump(fd, 2, 6);
     } else {
-        String8 result("    Latest ZSL capture request: none yet\n");
-        write(fd, result.string(), result.size());
+        std::string result = "    Latest ZSL capture request: none yet\n";
+        write(fd, result.c_str(), result.size());
     }
     dumpZslQueue(fd);
 }
@@ -706,12 +707,12 @@
 }
 
 void ZslProcessor::dumpZslQueue(int fd) const {
-    String8 header("ZSL queue contents:");
-    String8 indent("    ");
-    ALOGV("%s", header.string());
+    std::string header = "ZSL queue contents:";
+    std::string indent = "    ";
+    ALOGV("%s", header.c_str());
     if (fd != -1) {
         header = indent + header + "\n";
-        write(fd, header.string(), header.size());
+        write(fd, header.c_str(), header.size());
     }
     for (size_t i = 0; i < mZslQueue.size(); i++) {
         const ZslPair &queueEntry = mZslQueue[i];
@@ -725,13 +726,13 @@
             entry = queueEntry.frame.find(ANDROID_CONTROL_AE_STATE);
             if (entry.count > 0) frameAeState = entry.data.u8[0];
         }
-        String8 result =
-                String8::format("   %zu: b: %" PRId64 "\tf: %" PRId64 ", AE state: %d", i,
+        std::string result =
+                fmt::sprintf("   %zu: b: %" PRId64 "\tf: %" PRId64 ", AE state: %d", i,
                         bufferTimestamp, frameTimestamp, frameAeState);
-        ALOGV("%s", result.string());
+        ALOGV("%s", result.c_str());
         if (fd != -1) {
             result = indent + result + "\n";
-            write(fd, result.string(), result.size());
+            write(fd, result.c_str(), result.size());
         }
 
     }
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
index 38c615d..c60f327 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
@@ -26,6 +26,7 @@
 #include <gui/Surface.h>
 #include <camera/camera2/CaptureRequest.h>
 #include <camera/CameraUtils.h>
+#include <camera/StringUtils.h>
 
 #include "common/CameraDeviceBase.h"
 #include "device3/Camera3Device.h"
@@ -42,12 +43,12 @@
 
 #define STATUS_ERROR(errorCode, errorString) \
     binder::Status::fromServiceSpecificError(errorCode, \
-            String8::format("%s:%d: %s", __FUNCTION__, __LINE__, errorString))
+            fmt::sprintf("%s:%d: %s", __FUNCTION__, __LINE__, errorString).c_str())
 
 #define STATUS_ERROR_FMT(errorCode, errorString, ...) \
     binder::Status::fromServiceSpecificError(errorCode, \
-            String8::format("%s:%d: " errorString, __FUNCTION__, __LINE__, \
-                    __VA_ARGS__))
+            fmt::sprintf("%s:%d: " errorString, __FUNCTION__, __LINE__, \
+                    __VA_ARGS__).c_str())
 
 namespace android {
 using namespace camera2;
@@ -57,10 +58,10 @@
 CameraDeviceClientBase::CameraDeviceClientBase(
         const sp<CameraService>& cameraService,
         const sp<hardware::camera2::ICameraDeviceCallbacks>& remoteCallback,
-        const String16& clientPackageName,
+        const std::string& clientPackageName,
         bool systemNativeClient,
-        const std::optional<String16>& clientFeatureId,
-        const String8& cameraId,
+        const std::optional<std::string>& clientFeatureId,
+        const std::string& cameraId,
         [[maybe_unused]] int api1CameraId,
         int cameraFacing,
         int sensorOrientation,
@@ -88,10 +89,10 @@
 CameraDeviceClient::CameraDeviceClient(const sp<CameraService>& cameraService,
         const sp<hardware::camera2::ICameraDeviceCallbacks>& remoteCallback,
         std::shared_ptr<CameraServiceProxyWrapper> cameraServiceProxyWrapper,
-        const String16& clientPackageName,
+        const std::string& clientPackageName,
         bool systemNativeClient,
-        const std::optional<String16>& clientFeatureId,
-        const String8& cameraId,
+        const std::optional<std::string>& clientFeatureId,
+        const std::string& cameraId,
         int cameraFacing,
         int sensorOrientation,
         int clientPid,
@@ -109,16 +110,17 @@
     mOverrideForPerfClass(overrideForPerfClass) {
 
     ATRACE_CALL();
-    ALOGI("CameraDeviceClient %s: Opened", cameraId.string());
+    ALOGI("CameraDeviceClient %s: Opened", cameraId.c_str());
 }
 
 status_t CameraDeviceClient::initialize(sp<CameraProviderManager> manager,
-        const String8& monitorTags) {
+        const std::string& monitorTags) {
     return initializeImpl(manager, monitorTags);
 }
 
 template<typename TProviderPtr>
-status_t CameraDeviceClient::initializeImpl(TProviderPtr providerPtr, const String8& monitorTags) {
+status_t CameraDeviceClient::initializeImpl(TProviderPtr providerPtr,
+        const std::string& monitorTags) {
     ATRACE_CALL();
     status_t res;
 
@@ -127,10 +129,9 @@
         return res;
     }
 
-    String8 threadName;
     mFrameProcessor = new FrameProcessorBase(mDevice);
-    threadName = String8::format("CDU-%s-FrameProc", mCameraIdStr.string());
-    res = mFrameProcessor->run(threadName.string());
+    std::string threadName = std::string("CDU-") + mCameraIdStr + "-FrameProc";
+    res = mFrameProcessor->run(threadName.c_str());
     if (res != OK) {
         ALOGE("%s: Unable to start frame processor thread: %s (%d)",
                 __FUNCTION__, strerror(-res), res);
@@ -188,13 +189,13 @@
     mProviderManager = providerPtr;
     // Cache physical camera ids corresponding to this device and also the high
     // resolution sensors in this device + physical camera ids
-    mProviderManager->isLogicalCamera(mCameraIdStr.string(), &mPhysicalCameraIds);
+    mProviderManager->isLogicalCamera(mCameraIdStr, &mPhysicalCameraIds);
     if (supportsUltraHighResolutionCapture(mCameraIdStr)) {
-        mHighResolutionSensors.insert(mCameraIdStr.string());
+        mHighResolutionSensors.insert(mCameraIdStr);
     }
     for (auto &physicalId : mPhysicalCameraIds) {
-        if (supportsUltraHighResolutionCapture(String8(physicalId.c_str()))) {
-            mHighResolutionSensors.insert(physicalId.c_str());
+        if (supportsUltraHighResolutionCapture(physicalId)) {
+            mHighResolutionSensors.insert(physicalId);
         }
     }
     return OK;
@@ -222,7 +223,7 @@
     if (idx == NAME_NOT_FOUND) {
         ALOGE("%s: Camera %s: Tried to submit a request with a surface that"
                 " we have not called createStream on",
-                __FUNCTION__, mCameraIdStr.string());
+                __FUNCTION__, mCameraIdStr.c_str());
         return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
                 "Request targets Surface that is not part of current capture session");
     } else if ((compositeIdx = mCompositeStreamMap.indexOfKey(IInterface::asBinder(gbp)))
@@ -239,7 +240,7 @@
     (*outSurfaceMap)[streamSurfaceId.streamId()].push_back(streamSurfaceId.surfaceId());
 
     ALOGV("%s: Camera %s: Appending output stream %d surface %d to request",
-            __FUNCTION__, mCameraIdStr.string(), streamSurfaceId.streamId(),
+            __FUNCTION__, mCameraIdStr.c_str(), streamSurfaceId.streamId(),
             streamSurfaceId.surfaceId());
 
     if (currentStreamId != nullptr) {
@@ -282,7 +283,7 @@
 
     if (requests.empty()) {
         ALOGE("%s: Camera %s: Sent null request. Rejecting request.",
-              __FUNCTION__, mCameraIdStr.string());
+              __FUNCTION__, mCameraIdStr.c_str());
         return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, "Empty request list");
     }
 
@@ -295,19 +296,19 @@
         if (request.mIsReprocess) {
             if (!mInputStream.configured) {
                 ALOGE("%s: Camera %s: no input stream is configured.", __FUNCTION__,
-                        mCameraIdStr.string());
+                        mCameraIdStr.c_str());
                 return STATUS_ERROR_FMT(CameraService::ERROR_ILLEGAL_ARGUMENT,
                         "No input configured for camera %s but request is for reprocessing",
-                        mCameraIdStr.string());
+                        mCameraIdStr.c_str());
             } else if (streaming) {
                 ALOGE("%s: Camera %s: streaming reprocess requests not supported.", __FUNCTION__,
-                        mCameraIdStr.string());
+                        mCameraIdStr.c_str());
                 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
                         "Repeating reprocess requests not supported");
             } else if (request.mPhysicalCameraSettings.size() > 1) {
                 ALOGE("%s: Camera %s: reprocess requests not supported for "
                         "multiple physical cameras.", __FUNCTION__,
-                        mCameraIdStr.string());
+                        mCameraIdStr.c_str());
                 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
                         "Reprocess requests not supported for multiple cameras");
             }
@@ -315,23 +316,23 @@
 
         if (request.mPhysicalCameraSettings.empty()) {
             ALOGE("%s: Camera %s: request doesn't contain any settings.", __FUNCTION__,
-                    mCameraIdStr.string());
+                    mCameraIdStr.c_str());
             return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
                     "Request doesn't contain any settings");
         }
 
         //The first capture settings should always match the logical camera id
-        String8 logicalId(request.mPhysicalCameraSettings.begin()->id.c_str());
+        const std::string &logicalId = request.mPhysicalCameraSettings.begin()->id;
         if (mDevice->getId() != logicalId) {
             ALOGE("%s: Camera %s: Invalid camera request settings.", __FUNCTION__,
-                    mCameraIdStr.string());
+                    mCameraIdStr.c_str());
             return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
                     "Invalid camera request settings");
         }
 
         if (request.mSurfaceList.isEmpty() && request.mStreamIdxList.size() == 0) {
             ALOGE("%s: Camera %s: Requests must have at least one surface target. "
-                    "Rejecting request.", __FUNCTION__, mCameraIdStr.string());
+                    "Rejecting request.", __FUNCTION__, mCameraIdStr.c_str());
             return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
                     "Request has no output targets");
         }
@@ -357,9 +358,9 @@
 
                 ssize_t index = mConfiguredOutputs.indexOfKey(streamId);
                 if (index >= 0) {
-                    String8 requestedPhysicalId(
-                            mConfiguredOutputs.valueAt(index).getPhysicalCameraId());
-                    requestedPhysicalIds.push_back(requestedPhysicalId.string());
+                    const std::string &requestedPhysicalId =
+                            mConfiguredOutputs.valueAt(index).getPhysicalCameraId();
+                    requestedPhysicalIds.push_back(requestedPhysicalId);
                     dynamicProfileBitmap |=
                             mConfiguredOutputs.valueAt(index).getDynamicRangeProfile();
                 } else {
@@ -375,7 +376,7 @@
                 if (index < 0) {
                     ALOGE("%s: Camera %s: Tried to submit a request with a surface that"
                             " we have not called createStream on: stream %d",
-                            __FUNCTION__, mCameraIdStr.string(), streamId);
+                            __FUNCTION__, mCameraIdStr.c_str(), streamId);
                     return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
                             "Request targets Surface that is not part of current capture session");
                 }
@@ -384,7 +385,7 @@
                 if ((size_t)surfaceIdx >= gbps.size()) {
                     ALOGE("%s: Camera %s: Tried to submit a request with a surface that"
                             " we have not called createStream on: stream %d, surfaceIdx %d",
-                            __FUNCTION__, mCameraIdStr.string(), streamId, surfaceIdx);
+                            __FUNCTION__, mCameraIdStr.c_str(), streamId, surfaceIdx);
                     return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
                             "Request targets Surface has invalid surface index");
                 }
@@ -394,9 +395,9 @@
                     return res;
                 }
 
-                String8 requestedPhysicalId(
-                        mConfiguredOutputs.valueAt(index).getPhysicalCameraId());
-                requestedPhysicalIds.push_back(requestedPhysicalId.string());
+                const std::string &requestedPhysicalId =
+                        mConfiguredOutputs.valueAt(index).getPhysicalCameraId();
+                requestedPhysicalIds.push_back(requestedPhysicalId);
                 dynamicProfileBitmap |=
                         mConfiguredOutputs.valueAt(index).getDynamicRangeProfile();
             }
@@ -418,7 +419,7 @@
                     } else {
                         ALOGE("%s: Camera %s: Tried to submit a request with a surfaces that"
                                 " reference an unsupported dynamic range profile combination"
-                                " 0x%" PRIx64 "!", __FUNCTION__, mCameraIdStr.string(),
+                                " 0x%" PRIx64 "!", __FUNCTION__, mCameraIdStr.c_str(),
                                 dynamicProfileBitmap);
                         return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
                                 "Request targets an unsupported dynamic range profile"
@@ -427,7 +428,7 @@
                 } else {
                     ALOGE("%s: Camera %s: Tried to submit a request with a surface that"
                             " references unsupported dynamic range profile 0x%x!",
-                            __FUNCTION__, mCameraIdStr.string(), i);
+                            __FUNCTION__, mCameraIdStr.c_str(), i);
                     return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
                             "Request targets 10-bit Surface with unsupported dynamic range"
                             " profile");
@@ -439,7 +440,7 @@
         for (const auto& it : request.mPhysicalCameraSettings) {
             if (it.settings.isEmpty()) {
                 ALOGE("%s: Camera %s: Sent empty metadata packet. Rejecting request.",
-                        __FUNCTION__, mCameraIdStr.string());
+                        __FUNCTION__, mCameraIdStr.c_str());
                 return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
                         "Request settings are empty");
             }
@@ -462,7 +463,7 @@
                 }
             }
 
-            String8 physicalId(it.id.c_str());
+            const std::string &physicalId = it.id;
             bool hasTestPatternModePhysicalKey = std::find(mSupportedPhysicalRequestKeys.begin(),
                     mSupportedPhysicalRequestKeys.end(), ANDROID_SENSOR_TEST_PATTERN_MODE) !=
                     mSupportedPhysicalRequestKeys.end();
@@ -474,7 +475,7 @@
                         it.id);
                 if (found == requestedPhysicalIds.end()) {
                     ALOGE("%s: Camera %s: Physical camera id: %s not part of attached outputs.",
-                            __FUNCTION__, mCameraIdStr.string(), physicalId.string());
+                            __FUNCTION__, mCameraIdStr.c_str(), physicalId.c_str());
                     return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
                             "Invalid physical camera id");
                 }
@@ -520,7 +521,7 @@
                 &(submitInfo->mRequestId), /*size*/1);
         loopCounter++; // loopCounter starts from 1
         ALOGV("%s: Camera %s: Creating request with ID %d (%d of %zu)",
-                __FUNCTION__, mCameraIdStr.string(), submitInfo->mRequestId,
+                __FUNCTION__, mCameraIdStr.c_str(), submitInfo->mRequestId,
                 loopCounter, requests.size());
 
         metadataRequestList.push_back(physicalSettingsList);
@@ -543,12 +544,12 @@
         err = mDevice->setStreamingRequestList(metadataRequestList, surfaceMapList,
                 &(submitInfo->mLastFrameNumber));
         if (err != OK) {
-            String8 msg = String8::format(
+            std::string msg = fmt::sprintf(
                 "Camera %s:  Got error %s (%d) after trying to set streaming request",
-                mCameraIdStr.string(), strerror(-err), err);
-            ALOGE("%s: %s", __FUNCTION__, msg.string());
+                mCameraIdStr.c_str(), strerror(-err), err);
+            ALOGE("%s: %s", __FUNCTION__, msg.c_str());
             res = STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION,
-                    msg.string());
+                    msg.c_str());
         } else {
             Mutex::Autolock idLock(mStreamingRequestIdLock);
             mStreamingRequestId = submitInfo->mRequestId;
@@ -557,17 +558,17 @@
         err = mDevice->captureList(metadataRequestList, surfaceMapList,
                 &(submitInfo->mLastFrameNumber));
         if (err != OK) {
-            String8 msg = String8::format(
+            std::string msg = fmt::sprintf(
                 "Camera %s: Got error %s (%d) after trying to submit capture request",
-                mCameraIdStr.string(), strerror(-err), err);
-            ALOGE("%s: %s", __FUNCTION__, msg.string());
+                mCameraIdStr.c_str(), strerror(-err), err);
+            ALOGE("%s: %s", __FUNCTION__, msg.c_str());
             res = STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION,
-                    msg.string());
+                    msg.c_str());
         }
         ALOGV("%s: requestId = %d ", __FUNCTION__, submitInfo->mRequestId);
     }
 
-    ALOGV("%s: Camera %s: End of function", __FUNCTION__, mCameraIdStr.string());
+    ALOGV("%s: Camera %s: End of function", __FUNCTION__, mCameraIdStr.c_str());
     return res;
 }
 
@@ -591,22 +592,22 @@
 
     Mutex::Autolock idLock(mStreamingRequestIdLock);
     if (mStreamingRequestId != requestId) {
-        String8 msg = String8::format("Camera %s: Canceling request ID %d doesn't match "
-                "current request ID %d", mCameraIdStr.string(), requestId, mStreamingRequestId);
-        ALOGE("%s: %s", __FUNCTION__, msg.string());
-        return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
+        std::string msg = fmt::sprintf("Camera %s: Canceling request ID %d doesn't match "
+                "current request ID %d", mCameraIdStr.c_str(), requestId, mStreamingRequestId);
+        ALOGE("%s: %s", __FUNCTION__, msg.c_str());
+        return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.c_str());
     }
 
     err = mDevice->clearStreamingRequest(lastFrameNumber);
 
     if (err == OK) {
         ALOGV("%s: Camera %s: Successfully cleared streaming request",
-                __FUNCTION__, mCameraIdStr.string());
+                __FUNCTION__, mCameraIdStr.c_str());
         mStreamingRequestId = REQUEST_ID_NONE;
     } else {
         res = STATUS_ERROR_FMT(CameraService::ERROR_INVALID_OPERATION,
                 "Camera %s: Error clearing streaming request: %s (%d)",
-                mCameraIdStr.string(), strerror(-err), err);
+                mCameraIdStr.c_str(), strerror(-err), err);
     }
 
     return res;
@@ -631,9 +632,9 @@
     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());
+        std::string msg = "Invalid offline stream ids";
+        ALOGE("%s: %s", __FUNCTION__, msg.c_str());
+        return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.c_str());
     }
 
     Mutex::Autolock icl(mBinderSerializationLock);
@@ -650,15 +651,15 @@
 
     status_t err = mDevice->configureStreams(sessionParams, operatingMode);
     if (err == BAD_VALUE) {
-        String8 msg = String8::format("Camera %s: Unsupported set of inputs/outputs provided",
-                mCameraIdStr.string());
-        ALOGE("%s: %s", __FUNCTION__, msg.string());
-        res = STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
+        std::string msg = fmt::sprintf("Camera %s: Unsupported set of inputs/outputs provided",
+                mCameraIdStr.c_str());
+        ALOGE("%s: %s", __FUNCTION__, msg.c_str());
+        res = STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.c_str());
     } else if (err != OK) {
-        String8 msg = String8::format("Camera %s: Error configuring streams: %s (%d)",
-                mCameraIdStr.string(), strerror(-err), err);
-        ALOGE("%s: %s", __FUNCTION__, msg.string());
-        res = STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION, msg.string());
+        std::string msg = fmt::sprintf("Camera %s: Error configuring streams: %s (%d)",
+                mCameraIdStr.c_str(), strerror(-err), err);
+        ALOGE("%s: %s", __FUNCTION__, msg.c_str());
+        res = STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION, msg.c_str());
     } else {
         offlineStreamIds->clear();
         mDevice->getOfflineStreamIds(offlineStreamIds);
@@ -667,10 +668,10 @@
         for (size_t i = 0; i < mCompositeStreamMap.size(); ++i) {
             err = mCompositeStreamMap.valueAt(i)->configureStream();
             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());
+                std::string msg = fmt::sprintf("Camera %s: Error configuring composite "
+                        "streams: %s (%d)", mCameraIdStr.c_str(), strerror(-err), err);
+                ALOGE("%s: %s", __FUNCTION__, msg.c_str());
+                res = STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION, msg.c_str());
                 break;
             }
 
@@ -729,35 +730,36 @@
     }
 
     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());
+        std::string msg = fmt::sprintf( "Camera %s: Invalid status!", mCameraIdStr.c_str());
+        ALOGE("%s: %s", __FUNCTION__, msg.c_str());
+        return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.c_str());
     }
 
     *status = false;
-    camera3::metadataGetter getMetadata = [this](const String8 &id, bool /*overrideForPerfClass*/) {
+    camera3::metadataGetter getMetadata = [this](const std::string &id,
+            bool /*overrideForPerfClass*/) {
           return mDevice->infoPhysical(id);};
-    ret = mProviderManager->isSessionConfigurationSupported(mCameraIdStr.string(),
+    ret = mProviderManager->isSessionConfigurationSupported(mCameraIdStr.c_str(),
             sessionConfiguration, mOverrideForPerfClass, getMetadata, status);
     switch (ret) {
         case OK:
             // Expected, do nothing.
             break;
         case INVALID_OPERATION: {
-                String8 msg = String8::format(
+                std::string msg = fmt::sprintf(
                         "Camera %s: Session configuration query not supported!",
-                        mCameraIdStr.string());
-                ALOGD("%s: %s", __FUNCTION__, msg.string());
-                res = STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION, msg.string());
+                        mCameraIdStr.c_str());
+                ALOGD("%s: %s", __FUNCTION__, msg.c_str());
+                res = STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION, msg.c_str());
             }
 
             break;
         default: {
-                String8 msg = String8::format( "Camera %s: Error: %s (%d)", mCameraIdStr.string(),
+                std::string msg = fmt::sprintf( "Camera %s: Error: %s (%d)", mCameraIdStr.c_str(),
                         strerror(-ret), ret);
-                ALOGE("%s: %s", __FUNCTION__, msg.string());
+                ALOGE("%s: %s", __FUNCTION__, msg.c_str());
                 res = STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
-                        msg.string());
+                        msg.c_str());
             }
     }
 
@@ -809,10 +811,10 @@
         }
 
         if (surfaces.empty() && dIndex == NAME_NOT_FOUND) {
-            String8 msg = String8::format("Camera %s: Invalid stream ID (%d) specified, no such"
-                    " stream created yet", mCameraIdStr.string(), streamId);
-            ALOGW("%s: %s", __FUNCTION__, msg.string());
-            return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
+            std::string msg = fmt::sprintf("Camera %s: Invalid stream ID (%d) specified, no such"
+                    " stream created yet", mCameraIdStr.c_str(), streamId);
+            ALOGW("%s: %s", __FUNCTION__, msg.c_str());
+            return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.c_str());
         }
     }
 
@@ -820,10 +822,10 @@
     status_t err = mDevice->deleteStream(streamId);
 
     if (err != OK) {
-        String8 msg = String8::format("Camera %s: Unexpected error %s (%d) when deleting stream %d",
-                mCameraIdStr.string(), strerror(-err), err, streamId);
-        ALOGE("%s: %s", __FUNCTION__, msg.string());
-        res = STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION, msg.string());
+        std::string msg = fmt::sprintf("Camera %s: Unexpected error %s (%d) when deleting stream "
+                "%d", mCameraIdStr.c_str(), strerror(-err), err, streamId);
+        ALOGE("%s: %s", __FUNCTION__, msg.c_str());
+        res = STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION, msg.c_str());
     } else {
         if (isInput) {
             mInputStream.configured = false;
@@ -843,11 +845,11 @@
                 status_t ret;
                 if ((ret = mCompositeStreamMap.valueAt(compositeIndex)->deleteStream())
                         != OK) {
-                    String8 msg = String8::format("Camera %s: Unexpected error %s (%d) when "
-                            "deleting composite stream %d", mCameraIdStr.string(), strerror(-err), err,
-                            streamId);
-                    ALOGE("%s: %s", __FUNCTION__, msg.string());
-                    res = STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION, msg.string());
+                    std::string msg = fmt::sprintf("Camera %s: Unexpected error %s (%d) when "
+                            "deleting composite stream %d", mCameraIdStr.c_str(), strerror(-err),
+                            err, streamId);
+                    ALOGE("%s: %s", __FUNCTION__, msg.c_str());
+                    res = STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION, msg.c_str());
                 }
                 mCompositeStreamMap.removeItemsAt(compositeIndex);
             }
@@ -880,7 +882,7 @@
     size_t numBufferProducers = bufferProducers.size();
     bool deferredConsumer = outputConfiguration.isDeferred();
     bool isShared = outputConfiguration.isShared();
-    String8 physicalCameraId = String8(outputConfiguration.getPhysicalCameraId());
+    const std::string &physicalCameraId = outputConfiguration.getPhysicalCameraId();
     bool deferredConsumerOnly = deferredConsumer && numBufferProducers == 0;
     bool isMultiResolution = outputConfiguration.isMultiResolution();
     int64_t dynamicRangeProfile = outputConfiguration.getDynamicRangeProfile();
@@ -923,10 +925,11 @@
         sp<IBinder> binder = IInterface::asBinder(bufferProducer);
         ssize_t index = mStreamMap.indexOfKey(binder);
         if (index != NAME_NOT_FOUND) {
-            String8 msg = String8::format("Camera %s: Surface already has a stream created for it "
-                    "(ID %zd)", mCameraIdStr.string(), index);
-            ALOGW("%s: %s", __FUNCTION__, msg.string());
-            return STATUS_ERROR(CameraService::ERROR_ALREADY_EXISTS, msg.string());
+            std::string msg = std::string("Camera ") + mCameraIdStr
+                    + ": Surface already has a stream created for it (ID "
+                    + std::to_string(index) + ")";
+            ALOGW("%s: %s", __FUNCTION__, msg.c_str());
+            return STATUS_ERROR(CameraService::ERROR_ALREADY_EXISTS, msg.c_str());
         }
 
         sp<Surface> surface;
@@ -994,7 +997,7 @@
     if (err != OK) {
         res = STATUS_ERROR_FMT(CameraService::ERROR_INVALID_OPERATION,
                 "Camera %s: Error creating output stream (%d x %d, fmt %x, dataSpace %x): %s (%d)",
-                mCameraIdStr.string(), streamInfo.width, streamInfo.height, streamInfo.format,
+                mCameraIdStr.c_str(), streamInfo.width, streamInfo.height, streamInfo.format,
                 streamInfo.dataSpace, strerror(-err), err);
     } else {
         int i = 0;
@@ -1010,20 +1013,19 @@
 
         ALOGV("%s: Camera %s: Successfully created a new stream ID %d for output surface"
                     " (%d x %d) with format 0x%x.",
-                  __FUNCTION__, mCameraIdStr.string(), streamId, streamInfo.width,
+                  __FUNCTION__, mCameraIdStr.c_str(), streamId, streamInfo.width,
                   streamInfo.height, streamInfo.format);
 
         // Set transform flags to ensure preview to be rotated correctly.
         res = setStreamTransformLocked(streamId, streamInfo.mirrorMode);
 
         // Fill in mHighResolutionCameraIdToStreamIdSet map
-        const String8 &cameraIdUsed =
+        const std::string &cameraIdUsed =
                 physicalCameraId.size() != 0 ? physicalCameraId : mCameraIdStr;
-        const char *cameraIdUsedCStr = cameraIdUsed.string();
         // Only needed for high resolution sensors
-        if (mHighResolutionSensors.find(cameraIdUsedCStr) !=
+        if (mHighResolutionSensors.find(cameraIdUsed) !=
                 mHighResolutionSensors.end()) {
-            mHighResolutionCameraIdToStreamIdSet[cameraIdUsedCStr].insert(streamId);
+            mHighResolutionCameraIdToStreamIdSet[cameraIdUsed].insert(streamId);
         }
 
         *newStreamId = streamId;
@@ -1063,8 +1065,8 @@
     int streamId = camera3::CAMERA3_STREAM_ID_INVALID;
     std::vector<sp<Surface>> noSurface;
     std::vector<int> surfaceIds;
-    String8 physicalCameraId(outputConfiguration.getPhysicalCameraId());
-    const String8 &cameraIdUsed =
+    const std::string &physicalCameraId = outputConfiguration.getPhysicalCameraId();
+    const std::string &cameraIdUsed =
             physicalCameraId.size() != 0 ? physicalCameraId : mCameraIdStr;
     // Here, we override sensor pixel modes
     std::unordered_set<int32_t> overriddenSensorPixelModesUsed;
@@ -1093,7 +1095,7 @@
     if (err != OK) {
         res = STATUS_ERROR_FMT(CameraService::ERROR_INVALID_OPERATION,
                 "Camera %s: Error creating output stream (%d x %d, fmt %x, dataSpace %x): %s (%d)",
-                mCameraIdStr.string(), width, height, format, dataSpace, strerror(-err), err);
+                mCameraIdStr.c_str(), width, height, format, dataSpace, strerror(-err), err);
     } else {
         // Can not add streamId to mStreamMap here, as the surface is deferred. Add it to
         // a separate list to track. Once the deferred surface is set, this id will be
@@ -1110,18 +1112,17 @@
 
         ALOGV("%s: Camera %s: Successfully created a new stream ID %d for a deferred surface"
                 " (%d x %d) stream with format 0x%x.",
-              __FUNCTION__, mCameraIdStr.string(), streamId, width, height, format);
+              __FUNCTION__, mCameraIdStr.c_str(), streamId, width, height, format);
 
         // Set transform flags to ensure preview to be rotated correctly.
         res = setStreamTransformLocked(streamId, outputConfiguration.getMirrorMode());
 
         *newStreamId = streamId;
         // Fill in mHighResolutionCameraIdToStreamIdSet
-        const char *cameraIdUsedCStr = cameraIdUsed.string();
         // Only needed for high resolution sensors
-        if (mHighResolutionSensors.find(cameraIdUsedCStr) !=
+        if (mHighResolutionSensors.find(cameraIdUsed) !=
                 mHighResolutionSensors.end()) {
-            mHighResolutionCameraIdToStreamIdSet[cameraIdUsed.string()].insert(streamId);
+            mHighResolutionCameraIdToStreamIdSet[cameraIdUsed].insert(streamId);
         }
     }
     return res;
@@ -1145,10 +1146,10 @@
 
     err = mDevice->setStreamTransform(streamId, transform);
     if (err != OK) {
-        String8 msg = String8::format("Failed to set stream transform (stream id %d)",
+        std::string msg = fmt::sprintf("Failed to set stream transform (stream id %d)",
                 streamId);
-        ALOGE("%s: %s", __FUNCTION__, msg.string());
-        return STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION, msg.string());
+        ALOGE("%s: %s", __FUNCTION__, msg.c_str());
+        return STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION, msg.c_str());
     }
 
     return res;
@@ -1173,10 +1174,10 @@
     }
 
     if (mInputStream.configured) {
-        String8 msg = String8::format("Camera %s: Already has an input stream "
-                "configured (ID %d)", mCameraIdStr.string(), mInputStream.id);
-        ALOGE("%s: %s", __FUNCTION__, msg.string() );
-        return STATUS_ERROR(CameraService::ERROR_ALREADY_EXISTS, msg.string());
+        std::string msg = fmt::sprintf("Camera %s: Already has an input stream "
+                "configured (ID %d)", mCameraIdStr.c_str(), mInputStream.id);
+        ALOGE("%s: %s", __FUNCTION__, msg.c_str() );
+        return STATUS_ERROR(CameraService::ERROR_ALREADY_EXISTS, msg.c_str());
     }
 
     int streamId = -1;
@@ -1189,12 +1190,12 @@
         mInputStream.id = streamId;
 
         ALOGV("%s: Camera %s: Successfully created a new input stream ID %d",
-                __FUNCTION__, mCameraIdStr.string(), streamId);
+                __FUNCTION__, mCameraIdStr.c_str(), streamId);
 
         *newStreamId = streamId;
     } else {
         res = STATUS_ERROR_FMT(CameraService::ERROR_INVALID_OPERATION,
-                "Camera %s: Error creating new input stream: %s (%d)", mCameraIdStr.string(),
+                "Camera %s: Error creating new input stream: %s (%d)", mCameraIdStr.c_str(),
                 strerror(-err), err);
     }
 
@@ -1219,9 +1220,9 @@
     if (err != OK) {
         res = STATUS_ERROR_FMT(CameraService::ERROR_INVALID_OPERATION,
                 "Camera %s: Error getting input Surface: %s (%d)",
-                mCameraIdStr.string(), strerror(-err), err);
+                mCameraIdStr.c_str(), strerror(-err), err);
     } else {
-        inputSurface->name = String16("CameraInput");
+        inputSurface->name = toString16("CameraInput");
         inputSurface->graphicBufferProducer = producer;
     }
     return res;
@@ -1242,7 +1243,7 @@
 
     const std::vector<sp<IGraphicBufferProducer> >& bufferProducers =
             outputConfiguration.getGraphicBufferProducers();
-    String8 physicalCameraId(outputConfiguration.getPhysicalCameraId());
+    const std::string &physicalCameraId = outputConfiguration.getPhysicalCameraId();
 
     auto producerCount = bufferProducers.size();
     if (producerCount == 0) {
@@ -1329,12 +1330,12 @@
             case -EBUSY:
                 res = STATUS_ERROR_FMT(CameraService::ERROR_ILLEGAL_ARGUMENT,
                         "Camera %s: Error updating stream: %s (%d)",
-                        mCameraIdStr.string(), strerror(ret), ret);
+                        mCameraIdStr.c_str(), strerror(ret), ret);
                 break;
             default:
                 res = STATUS_ERROR_FMT(CameraService::ERROR_INVALID_OPERATION,
                         "Camera %s: Error updating stream: %s (%d)",
-                        mCameraIdStr.string(), strerror(ret), ret);
+                        mCameraIdStr.c_str(), strerror(ret), ret);
                 break;
         }
     } else {
@@ -1350,7 +1351,7 @@
         mConfiguredOutputs.replaceValueFor(streamId, outputConfiguration);
 
         ALOGV("%s: Camera %s: Successful stream ID %d update",
-                  __FUNCTION__, mCameraIdStr.string(), streamId);
+                  __FUNCTION__, mCameraIdStr.c_str(), streamId);
     }
 
     return res;
@@ -1385,12 +1386,12 @@
     } else if (err == BAD_VALUE) {
         res = STATUS_ERROR_FMT(CameraService::ERROR_ILLEGAL_ARGUMENT,
                 "Camera %s: Template ID %d is invalid or not supported: %s (%d)",
-                mCameraIdStr.string(), templateId, strerror(-err), err);
+                mCameraIdStr.c_str(), templateId, strerror(-err), err);
 
     } else {
         res = STATUS_ERROR_FMT(CameraService::ERROR_INVALID_OPERATION,
                 "Camera %s: Error creating default request for template %d: %s (%d)",
-                mCameraIdStr.string(), templateId, strerror(-err), err);
+                mCameraIdStr.c_str(), templateId, strerror(-err), err);
     }
     return res;
 }
@@ -1437,17 +1438,17 @@
     // FIXME: Also need check repeating burst.
     Mutex::Autolock idLock(mStreamingRequestIdLock);
     if (mStreamingRequestId != REQUEST_ID_NONE) {
-        String8 msg = String8::format(
+        std::string msg = fmt::sprintf(
             "Camera %s: Try to waitUntilIdle when there are active streaming requests",
-            mCameraIdStr.string());
-        ALOGE("%s: %s", __FUNCTION__, msg.string());
-        return STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION, msg.string());
+            mCameraIdStr.c_str());
+        ALOGE("%s: %s", __FUNCTION__, msg.c_str());
+        return STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION, msg.c_str());
     }
     status_t err = mDevice->waitUntilDrained();
     if (err != OK) {
         res = STATUS_ERROR_FMT(CameraService::ERROR_INVALID_OPERATION,
                 "Camera %s: Error waiting to drain: %s (%d)",
-                mCameraIdStr.string(), strerror(-err), err);
+                mCameraIdStr.c_str(), strerror(-err), err);
     }
     ALOGV("%s Done", __FUNCTION__);
     return res;
@@ -1473,7 +1474,8 @@
     status_t err = mDevice->flush(lastFrameNumber);
     if (err != OK) {
         res = STATUS_ERROR_FMT(CameraService::ERROR_INVALID_OPERATION,
-                "Camera %s: Error flushing device: %s (%d)", mCameraIdStr.string(), strerror(-err), err);
+                "Camera %s: Error flushing device: %s (%d)", mCameraIdStr.c_str(), strerror(-err),
+                err);
     }
     return res;
 }
@@ -1497,10 +1499,10 @@
     }
 
     if (index == NAME_NOT_FOUND) {
-        String8 msg = String8::format("Camera %s: Invalid stream ID (%d) specified, no stream "
-              "with that ID exists", mCameraIdStr.string(), streamId);
-        ALOGW("%s: %s", __FUNCTION__, msg.string());
-        return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
+        std::string msg = fmt::sprintf("Camera %s: Invalid stream ID (%d) specified, no stream "
+              "with that ID exists", mCameraIdStr.c_str(), streamId);
+        ALOGW("%s: %s", __FUNCTION__, msg.c_str());
+        return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.c_str());
     }
 
     // Also returns BAD_VALUE if stream ID was not valid, or stream already
@@ -1509,10 +1511,10 @@
     if (err == BAD_VALUE) {
         res = STATUS_ERROR_FMT(CameraService::ERROR_ILLEGAL_ARGUMENT,
                 "Camera %s: Stream %d has already been used, and cannot be prepared",
-                mCameraIdStr.string(), streamId);
+                mCameraIdStr.c_str(), streamId);
     } else if (err != OK) {
         res = STATUS_ERROR_FMT(CameraService::ERROR_INVALID_OPERATION,
-                "Camera %s: Error preparing stream %d: %s (%d)", mCameraIdStr.string(), streamId,
+                "Camera %s: Error preparing stream %d: %s (%d)", mCameraIdStr.c_str(), streamId,
                 strerror(-err), err);
     }
     return res;
@@ -1537,17 +1539,17 @@
     }
 
     if (index == NAME_NOT_FOUND) {
-        String8 msg = String8::format("Camera %s: Invalid stream ID (%d) specified, no stream "
-              "with that ID exists", mCameraIdStr.string(), streamId);
-        ALOGW("%s: %s", __FUNCTION__, msg.string());
-        return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
+        std::string msg = fmt::sprintf("Camera %s: Invalid stream ID (%d) specified, no stream "
+              "with that ID exists", mCameraIdStr.c_str(), streamId);
+        ALOGW("%s: %s", __FUNCTION__, msg.c_str());
+        return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.c_str());
     }
 
     if (maxCount <= 0) {
-        String8 msg = String8::format("Camera %s: maxCount (%d) must be greater than 0",
-                mCameraIdStr.string(), maxCount);
-        ALOGE("%s: %s", __FUNCTION__, msg.string());
-        return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
+        std::string msg = fmt::sprintf("Camera %s: maxCount (%d) must be greater than 0",
+                mCameraIdStr.c_str(), maxCount);
+        ALOGE("%s: %s", __FUNCTION__, msg.c_str());
+        return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.c_str());
     }
 
     // Also returns BAD_VALUE if stream ID was not valid, or stream already
@@ -1556,10 +1558,10 @@
     if (err == BAD_VALUE) {
         res = STATUS_ERROR_FMT(CameraService::ERROR_ILLEGAL_ARGUMENT,
                 "Camera %s: Stream %d has already been used, and cannot be prepared",
-                mCameraIdStr.string(), streamId);
+                mCameraIdStr.c_str(), streamId);
     } else if (err != OK) {
         res = STATUS_ERROR_FMT(CameraService::ERROR_INVALID_OPERATION,
-                "Camera %s: Error preparing stream %d: %s (%d)", mCameraIdStr.string(), streamId,
+                "Camera %s: Error preparing stream %d: %s (%d)", mCameraIdStr.c_str(), streamId,
                 strerror(-err), err);
     }
 
@@ -1585,10 +1587,10 @@
     }
 
     if (index == NAME_NOT_FOUND) {
-        String8 msg = String8::format("Camera %s: Invalid stream ID (%d) specified, no stream "
-              "with that ID exists", mCameraIdStr.string(), streamId);
-        ALOGW("%s: %s", __FUNCTION__, msg.string());
-        return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
+        std::string msg = fmt::sprintf("Camera %s: Invalid stream ID (%d) specified, no stream "
+              "with that ID exists", mCameraIdStr.c_str(), streamId);
+        ALOGW("%s: %s", __FUNCTION__, msg.c_str());
+        return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.c_str());
     }
 
     // Also returns BAD_VALUE if stream ID was not valid or if the stream is in
@@ -1597,10 +1599,10 @@
     if (err == BAD_VALUE) {
         res = STATUS_ERROR_FMT(CameraService::ERROR_ILLEGAL_ARGUMENT,
                 "Camera %s: Stream %d is still in use, cannot be torn down",
-                mCameraIdStr.string(), streamId);
+                mCameraIdStr.c_str(), streamId);
     } else if (err != OK) {
         res = STATUS_ERROR_FMT(CameraService::ERROR_INVALID_OPERATION,
-                "Camera %s: Error tearing down stream %d: %s (%d)", mCameraIdStr.string(), streamId,
+                "Camera %s: Error tearing down stream %d: %s (%d)", mCameraIdStr.c_str(), streamId,
                 strerror(-err), err);
     }
 
@@ -1618,7 +1620,7 @@
 
     const std::vector<sp<IGraphicBufferProducer> >& bufferProducers =
             outputConfiguration.getGraphicBufferProducers();
-    String8 physicalId(outputConfiguration.getPhysicalCameraId());
+    const std::string &physicalId = outputConfiguration.getPhysicalCameraId();
 
     if (bufferProducers.size() == 0) {
         ALOGE("%s: bufferProducers must not be empty", __FUNCTION__);
@@ -1643,17 +1645,17 @@
 
     }
     if (deferredStreamIndex == NAME_NOT_FOUND && !streamIdConfigured) {
-        String8 msg = String8::format("Camera %s: deferred surface is set to a unknown stream"
-                "(ID %d)", mCameraIdStr.string(), streamId);
-        ALOGW("%s: %s", __FUNCTION__, msg.string());
-        return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
+        std::string msg = fmt::sprintf("Camera %s: deferred surface is set to a unknown stream"
+                "(ID %d)", mCameraIdStr.c_str(), streamId);
+        ALOGW("%s: %s", __FUNCTION__, msg.c_str());
+        return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.c_str());
     }
 
     if (mStreamInfoMap[streamId].finalized) {
-        String8 msg = String8::format("Camera %s: finalizeOutputConfigurations has been called"
-                " on stream ID %d", mCameraIdStr.string(), streamId);
-        ALOGW("%s: %s", __FUNCTION__, msg.string());
-        return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
+        std::string msg = fmt::sprintf("Camera %s: finalizeOutputConfigurations has been called"
+                " on stream ID %d", mCameraIdStr.c_str(), streamId);
+        ALOGW("%s: %s", __FUNCTION__, msg.c_str());
+        return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.c_str());
     }
 
     if (!mDevice.get()) {
@@ -1673,7 +1675,7 @@
         ssize_t index = mStreamMap.indexOfKey(IInterface::asBinder(bufferProducer));
         if (index != NAME_NOT_FOUND) {
             ALOGV("Camera %s: Surface already has a stream created "
-                    " for it (ID %zd)", mCameraIdStr.string(), index);
+                    " for it (ID %zd)", mCameraIdStr.c_str(), index);
             continue;
         }
 
@@ -1716,11 +1718,11 @@
     } else if (err == NO_INIT) {
         res = STATUS_ERROR_FMT(CameraService::ERROR_ILLEGAL_ARGUMENT,
                 "Camera %s: Deferred surface is invalid: %s (%d)",
-                mCameraIdStr.string(), strerror(-err), err);
+                mCameraIdStr.c_str(), strerror(-err), err);
     } else {
         res = STATUS_ERROR_FMT(CameraService::ERROR_INVALID_OPERATION,
                 "Camera %s: Error setting output stream deferred surface: %s (%d)",
-                mCameraIdStr.string(), strerror(-err), err);
+                mCameraIdStr.c_str(), strerror(-err), err);
     }
 
     return res;
@@ -1732,10 +1734,10 @@
     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());
+        std::string msg = fmt::sprintf("Camera %s: invalid audio restriction mode %d",
+                mCameraIdStr.c_str(), mode);
+        ALOGW("%s: %s", __FUNCTION__, msg.c_str());
+        return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.c_str());
     }
 
     Mutex::Autolock icl(mBinderSerializationLock);
@@ -1814,15 +1816,15 @@
     }
 
     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());
+        std::string msg = "Offline surfaces must not be empty";
+        ALOGE("%s: %s", __FUNCTION__, msg.c_str());
+        return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.c_str());
     }
 
     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::string msg = "Invalid offline session";
+        ALOGE("%s: %s", __FUNCTION__, msg.c_str());
+        return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.c_str());
     }
 
     std::vector<int32_t> offlineStreamIds;
@@ -1831,17 +1833,17 @@
     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",
+            std::string msg = fmt::sprintf("Offline surface with id: %d is not registered",
                     streamId);
-            ALOGE("%s: %s", __FUNCTION__, msg.string());
-            return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
+            ALOGE("%s: %s", __FUNCTION__, msg.c_str());
+            return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.c_str());
         }
 
         if (!mStreamInfoMap[streamId].supportsOffline) {
-            String8 msg = String8::format("Offline surface with id: %d doesn't support "
+            std::string msg = fmt::sprintf("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());
+            ALOGE("%s: %s", __FUNCTION__, msg.c_str());
+            return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.c_str());
         }
 
         Mutex::Autolock l(mCompositeLock);
@@ -1878,7 +1880,7 @@
     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);
+                mCameraIdStr.c_str(), strerror(ret), ret);
     }
 
     sp<CameraOfflineSessionClient> offlineClient;
@@ -1903,7 +1905,7 @@
     } else {
         // In case we failed to register the offline client, ensure that it still initialized
         // so that all failing requests can return back correctly once the object is released.
-        offlineClient->initialize(nullptr /*cameraProviderManager*/, String8()/*monitorTags*/);
+        offlineClient->initialize(nullptr /*cameraProviderManager*/, std::string()/*monitorTags*/);
 
         switch(ret) {
             case BAD_VALUE:
@@ -1930,7 +1932,7 @@
 
 status_t CameraDeviceClient::dumpClient(int fd, const Vector<String16>& args) {
     dprintf(fd, "  CameraDeviceClient[%s] (%p) dump:\n",
-            mCameraIdStr.string(),
+            mCameraIdStr.c_str(),
             (getRemoteCallback() != NULL ?
                     IInterface::asBinder(getRemoteCallback()).get() : NULL) );
     dprintf(fd, "    Current client UID %u\n", mClientUid);
@@ -1963,7 +1965,7 @@
     return dumpDevice(fd, args);
 }
 
-status_t CameraDeviceClient::startWatchingTags(const String8 &tags, int out) {
+status_t CameraDeviceClient::startWatchingTags(const std::string &tags, int out) {
     sp<CameraDeviceBase> device = mDevice;
     if (!device) {
         dprintf(out, "  Device is detached.");
@@ -2087,16 +2089,16 @@
     if (mDevice == 0) return;
 
     nsecs_t startTime = systemTime();
-    ALOGV("Camera %s: Stopping processors", mCameraIdStr.string());
+    ALOGV("Camera %s: Stopping processors", mCameraIdStr.c_str());
 
     if (mFrameProcessor.get() != nullptr) {
         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());
+        ALOGV("Camera %s: Waiting for threads", mCameraIdStr.c_str());
         mFrameProcessor->join();
-        ALOGV("Camera %s: Disconnecting device", mCameraIdStr.string());
+        ALOGV("Camera %s: Disconnecting device", mCameraIdStr.c_str());
     }
 
     // WORKAROUND: HAL refuses to disconnect while there's streams in flight
@@ -2202,7 +2204,7 @@
     entry = metadata.find(ANDROID_LED_TRANSMIT);
     if (entry.count > 0 && entry.data.u8[0] != ANDROID_LED_TRANSMIT_ON) {
         String16 permissionString =
-            String16("android.permission.CAMERA_DISABLE_TRANSMIT_LED");
+            toString16("android.permission.CAMERA_DISABLE_TRANSMIT_LED");
         if (!checkCallingPermission(permissionString)) {
             const int uid = CameraThreadState::getCallingUid();
             ALOGE("Permission Denial: "
@@ -2228,7 +2230,7 @@
 
     if (tempId == nullptr) {
         ret = STATUS_ERROR_FMT(CameraService::ERROR_ILLEGAL_ARGUMENT,
-                "Camera %s: Invalid template argument", mCameraIdStr.string());
+                "Camera %s: Invalid template argument", mCameraIdStr.c_str());
         return ret;
     }
     switch(templateId) {
@@ -2253,21 +2255,21 @@
         default:
             ret = STATUS_ERROR_FMT(CameraService::ERROR_ILLEGAL_ARGUMENT,
                     "Camera %s: Template ID %d is invalid or not supported",
-                    mCameraIdStr.string(), templateId);
+                    mCameraIdStr.c_str(), templateId);
             return ret;
     }
 
     return ret;
 }
 
-const CameraMetadata &CameraDeviceClient::getStaticInfo(const String8 &cameraId) {
+const CameraMetadata &CameraDeviceClient::getStaticInfo(const std::string &cameraId) {
     if (mDevice->getId() == cameraId) {
         return mDevice->info();
     }
     return mDevice->infoPhysical(cameraId);
 }
 
-bool CameraDeviceClient::supportsUltraHighResolutionCapture(const String8 &cameraId) {
+bool CameraDeviceClient::supportsUltraHighResolutionCapture(const std::string &cameraId) {
     const CameraMetadata &deviceInfo = getStaticInfo(cameraId);
     return SessionConfigurationUtils::supportsUltraHighResolutionCapture(deviceInfo);
 }
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.h b/services/camera/libcameraservice/api2/CameraDeviceClient.h
index 1533cf5..45c904a 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.h
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.h
@@ -50,10 +50,10 @@
 protected:
     CameraDeviceClientBase(const sp<CameraService>& cameraService,
             const sp<hardware::camera2::ICameraDeviceCallbacks>& remoteCallback,
-            const String16& clientPackageName,
+            const std::string& clientPackageName,
             bool systemNativeClient,
-            const std::optional<String16>& clientFeatureId,
-            const String8& cameraId,
+            const std::optional<std::string>& clientFeatureId,
+            const std::string& cameraId,
             int api1CameraId,
             int cameraFacing,
             int sensorOrientation,
@@ -181,10 +181,10 @@
     CameraDeviceClient(const sp<CameraService>& cameraService,
             const sp<hardware::camera2::ICameraDeviceCallbacks>& remoteCallback,
             std::shared_ptr<CameraServiceProxyWrapper> cameraServiceProxyWrapper,
-            const String16& clientPackageName,
+            const std::string& clientPackageName,
             bool clientPackageOverride,
-            const std::optional<String16>& clientFeatureId,
-            const String8& cameraId,
+            const std::optional<std::string>& clientFeatureId,
+            const std::string& cameraId,
             int cameraFacing,
             int sensorOrientation,
             int clientPid,
@@ -195,7 +195,7 @@
     virtual ~CameraDeviceClient();
 
     virtual status_t      initialize(sp<CameraProviderManager> manager,
-            const String8& monitorTags) override;
+            const std::string& monitorTags) override;
 
     virtual status_t      setRotateAndCropOverride(uint8_t rotateAndCrop) override;
 
@@ -211,7 +211,7 @@
 
     virtual status_t      dumpClient(int fd, const Vector<String16>& args);
 
-    virtual status_t      startWatchingTags(const String8 &tags, int out);
+    virtual status_t      startWatchingTags(const std::string &tags, int out);
     virtual status_t      stopWatchingTags(int out);
     virtual status_t      dumpWatchedEventsToVector(std::vector<std::string> &out);
 
@@ -245,12 +245,12 @@
     // Calculate the ANativeWindow transform from android.sensor.orientation
     status_t              getRotationTransformLocked(int mirrorMode, /*out*/int32_t* transform);
 
-    bool supportsUltraHighResolutionCapture(const String8 &cameraId);
+    bool supportsUltraHighResolutionCapture(const std::string &cameraId);
 
     bool isSensorPixelModeConsistent(const std::list<int> &streamIdList,
             const CameraMetadata &settings);
 
-    const CameraMetadata &getStaticInfo(const String8 &cameraId);
+    const CameraMetadata &getStaticInfo(const std::string &cameraId);
 
 private:
     // StreamSurfaceId encapsulates streamId + surfaceId for a particular surface.
@@ -289,7 +289,7 @@
     std::vector<int32_t> mSupportedPhysicalRequestKeys;
 
     template<typename TProviderPtr>
-    status_t      initializeImpl(TProviderPtr providerPtr, const String8& monitorTags);
+    status_t      initializeImpl(TProviderPtr providerPtr, const std::string& monitorTags);
 
     /** Utility members */
     binder::Status checkPidStatus(const char* checkLocation);
diff --git a/services/camera/libcameraservice/api2/CameraOfflineSessionClient.cpp b/services/camera/libcameraservice/api2/CameraOfflineSessionClient.cpp
index 86a0ebc..99bdb0e 100644
--- a/services/camera/libcameraservice/api2/CameraOfflineSessionClient.cpp
+++ b/services/camera/libcameraservice/api2/CameraOfflineSessionClient.cpp
@@ -21,12 +21,13 @@
 #include "CameraOfflineSessionClient.h"
 #include "utils/CameraThreadState.h"
 #include <utils/Trace.h>
+#include <camera/StringUtils.h>
 
 namespace android {
 
 using binder::Status;
 
-status_t CameraOfflineSessionClient::initialize(sp<CameraProviderManager>, const String8&) {
+status_t CameraOfflineSessionClient::initialize(sp<CameraProviderManager>, const std::string&) {
     ATRACE_CALL();
 
     if (mFrameProcessor.get() != nullptr) {
@@ -42,14 +43,13 @@
 
     if (mOfflineSession.get() == nullptr) {
         ALOGE("%s: Camera %s: No valid offline session",
-                __FUNCTION__, mCameraIdStr.string());
+                __FUNCTION__, mCameraIdStr.c_str());
         return NO_INIT;
     }
 
-    String8 threadName;
     mFrameProcessor = new camera2::FrameProcessorBase(mOfflineSession);
-    threadName = String8::format("Offline-%s-FrameProc", mCameraIdStr.string());
-    res = mFrameProcessor->run(threadName.string());
+    std::string threadName = fmt::sprintf("Offline-%s-FrameProc", mCameraIdStr.c_str());
+    res = mFrameProcessor->run(threadName.c_str());
     if (res != OK) {
         ALOGE("%s: Unable to start frame processor thread: %s (%d)",
                 __FUNCTION__, strerror(-res), res);
@@ -65,7 +65,7 @@
     res = mOfflineSession->initialize(weakThis);
     if (res != OK) {
         ALOGE("%s: Camera %s: unable to initialize device: %s (%d)",
-                __FUNCTION__, mCameraIdStr.string(), strerror(-res), res);
+                __FUNCTION__, mCameraIdStr.c_str(), strerror(-res), res);
         return res;
     }
 
@@ -119,14 +119,14 @@
 }
 
 status_t CameraOfflineSessionClient::dumpClient(int fd, const Vector<String16>& args) {
-    String8 result;
+    std::string result;
 
     result = "  Offline session dump:\n";
-    write(fd, result.string(), result.size());
+    write(fd, result.c_str(), result.size());
 
     if (mOfflineSession.get() == nullptr) {
         result = "  *** Offline session is detached\n";
-        write(fd, result.string(), result.size());
+        write(fd, result.c_str(), result.size());
         return NO_ERROR;
     }
 
@@ -134,15 +134,15 @@
 
     auto res = mOfflineSession->dump(fd);
     if (res != OK) {
-        result = String8::format("   Error dumping offline session: %s (%d)",
+        result = fmt::sprintf("   Error dumping offline session: %s (%d)",
                 strerror(-res), res);
-        write(fd, result.string(), result.size());
+        write(fd, result.c_str(), result.size());
     }
 
     return OK;
 }
 
-status_t CameraOfflineSessionClient::startWatchingTags(const String8 &tags, int outFd) {
+status_t CameraOfflineSessionClient::startWatchingTags(const std::string &tags, int outFd) {
     return BasicClient::startWatchingTags(tags, outFd);
 }
 
@@ -171,7 +171,7 @@
     mDisconnected = true;
 
     sCameraService->removeByClient(this);
-    sCameraService->logDisconnectedOffline(mCameraIdStr, mClientPid, String8(mClientPackageName));
+    sCameraService->logDisconnectedOffline(mCameraIdStr, mClientPid, mClientPackageName);
 
     sp<IBinder> remote = getRemote();
     if (remote != nullptr) {
@@ -186,7 +186,7 @@
 
     finishCameraOps();
     ALOGI("%s: Disconnected client for offline camera %s for PID %d", __FUNCTION__,
-            mCameraIdStr.string(), mClientPid);
+            mCameraIdStr.c_str(), mClientPid);
 
     // client shouldn't be able to call into us anymore
     mClientPid = 0;
@@ -231,7 +231,7 @@
     ATRACE_CALL();
     {
         ALOGV("%s: Start camera ops, package name = %s, client UID = %d",
-              __FUNCTION__, String8(mClientPackageName).string(), mClientUid);
+              __FUNCTION__, mClientPackageName.c_str(), mClientUid);
     }
 
     if (mAppOpsManager != nullptr) {
@@ -240,14 +240,14 @@
         int32_t res;
         // TODO : possibly change this to OP_OFFLINE_CAMERA_SESSION
         mAppOpsManager->startWatchingMode(AppOpsManager::OP_CAMERA,
-                mClientPackageName, mOpsCallback);
+                toString16(mClientPackageName), mOpsCallback);
         // TODO : possibly change this to OP_OFFLINE_CAMERA_SESSION
         res = mAppOpsManager->startOpNoThrow(AppOpsManager::OP_CAMERA,
-                mClientUid, mClientPackageName, /*startIfModeDefault*/ false);
+                mClientUid, toString16(mClientPackageName), /*startIfModeDefault*/ false);
 
         if (res == AppOpsManager::MODE_ERRORED) {
             ALOGI("Offline Camera %s: Access for \"%s\" has been revoked",
-                    mCameraIdStr.string(), String8(mClientPackageName).string());
+                    mCameraIdStr.c_str(), mClientPackageName.c_str());
             return PERMISSION_DENIED;
         }
 
@@ -255,7 +255,7 @@
         // 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());
+                    mCameraIdStr.c_str(), mClientPackageName.c_str());
             // Return the same error as for device policy manager rejection
             return -EACCES;
         }
@@ -278,7 +278,7 @@
         if (mAppOpsManager != nullptr) {
         // TODO : possibly change this to OP_OFFLINE_CAMERA_SESSION
             mAppOpsManager->finishOp(AppOpsManager::OP_CAMERA, mClientUid,
-                    mClientPackageName);
+                    toString16(mClientPackageName));
             mOpsActive = false;
         }
     }
@@ -368,10 +368,10 @@
                 CaptureResultExtras());
 }
 
-status_t CameraOfflineSessionClient::injectCamera(const String8& injectedCamId,
+status_t CameraOfflineSessionClient::injectCamera(const std::string& injectedCamId,
             sp<CameraProviderManager> manager) {
     ALOGV("%s: This client doesn't support the injection camera. injectedCamId: %s providerPtr: %p",
-            __FUNCTION__, injectedCamId.string(), manager.get());
+            __FUNCTION__, injectedCamId.c_str(), manager.get());
 
     return OK;
 }
diff --git a/services/camera/libcameraservice/api2/CameraOfflineSessionClient.h b/services/camera/libcameraservice/api2/CameraOfflineSessionClient.h
index ad763f9..70bad03 100644
--- a/services/camera/libcameraservice/api2/CameraOfflineSessionClient.h
+++ b/services/camera/libcameraservice/api2/CameraOfflineSessionClient.h
@@ -47,9 +47,9 @@
             sp<CameraOfflineSessionBase> session,
             const KeyedVector<sp<IBinder>, sp<CompositeStream>>& offlineCompositeStreamMap,
             const sp<ICameraDeviceCallbacks>& remoteCallback,
-            const String16& clientPackageName,
-            const std::optional<String16>& clientFeatureId,
-            const String8& cameraIdStr, int cameraFacing, int sensorOrientation,
+            const std::string& clientPackageName,
+            const std::optional<std::string>& clientFeatureId,
+            const std::string& cameraIdStr, int cameraFacing, int sensorOrientation,
             int clientPid, uid_t clientUid, int servicePid) :
             CameraService::BasicClient(
                     cameraService,
@@ -73,12 +73,12 @@
 
     status_t dumpClient(int /*fd*/, const Vector<String16>& /*args*/) override;
 
-    status_t startWatchingTags(const String8 &tags, int outFd) override;
+    status_t startWatchingTags(const std::string &tags, int outFd) override;
     status_t stopWatchingTags(int outFd) override;
     status_t dumpWatchedEventsToVector(std::vector<std::string> &out) override;
 
     status_t initialize(sp<CameraProviderManager> /*manager*/,
-            const String8& /*monitorTags*/) override;
+            const std::string& /*monitorTags*/) override;
 
     status_t setRotateAndCropOverride(uint8_t rotateAndCrop) override;
 
@@ -117,7 +117,7 @@
     void notifyPrepared(int streamId) override;
     void notifyRequestQueueEmpty() override;
     void notifyRepeatingRequestError(long lastFrameNumber) override;
-    status_t injectCamera(const String8& injectedCamId,
+    status_t injectCamera(const std::string& injectedCamId,
             sp<CameraProviderManager> manager) override;
     status_t stopInjection() override;
 
diff --git a/services/camera/libcameraservice/api2/CompositeStream.cpp b/services/camera/libcameraservice/api2/CompositeStream.cpp
index 4ed1c28..8f53458 100644
--- a/services/camera/libcameraservice/api2/CompositeStream.cpp
+++ b/services/camera/libcameraservice/api2/CompositeStream.cpp
@@ -46,7 +46,7 @@
 
 status_t CompositeStream::createStream(const std::vector<sp<Surface>>& consumers,
         bool hasDeferredConsumer, uint32_t width, uint32_t height, int format,
-        camera_stream_rotation_t rotation, int * id, const String8& physicalCameraId,
+        camera_stream_rotation_t rotation, int * id, const std::string& physicalCameraId,
         const std::unordered_set<int32_t> &sensorPixelModesUsed,
         std::vector<int> * surfaceIds,
         int streamSetId, bool isShared, bool isMultiResolution, int32_t colorSpace,
diff --git a/services/camera/libcameraservice/api2/CompositeStream.h b/services/camera/libcameraservice/api2/CompositeStream.h
index a551d11..1b7fc6e 100644
--- a/services/camera/libcameraservice/api2/CompositeStream.h
+++ b/services/camera/libcameraservice/api2/CompositeStream.h
@@ -43,7 +43,7 @@
 
     status_t createStream(const std::vector<sp<Surface>>& consumers,
             bool hasDeferredConsumer, uint32_t width, uint32_t height, int format,
-            camera_stream_rotation_t rotation, int *id, const String8& physicalCameraId,
+            camera_stream_rotation_t rotation, int *id, const std::string& physicalCameraId,
             const std::unordered_set<int32_t> &sensorPixelModesUsed,
             std::vector<int> *surfaceIds,
             int streamSetId, bool isShared, bool isMultiResolution, int32_t colorSpace,
@@ -57,7 +57,7 @@
     // 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,
-            camera_stream_rotation_t rotation, int *id, const String8& physicalCameraId,
+            camera_stream_rotation_t rotation, int *id, const std::string& physicalCameraId,
             const std::unordered_set<int32_t> &sensorPixelModesUsed,
             std::vector<int> *surfaceIds,
             int streamSetId, bool isShared, int32_t colorSpace,
diff --git a/services/camera/libcameraservice/api2/DepthCompositeStream.cpp b/services/camera/libcameraservice/api2/DepthCompositeStream.cpp
index 737c2b5..1bd0b85 100644
--- a/services/camera/libcameraservice/api2/DepthCompositeStream.cpp
+++ b/services/camera/libcameraservice/api2/DepthCompositeStream.cpp
@@ -20,6 +20,7 @@
 
 #include <aidl/android/hardware/camera/device/CameraBlob.h>
 #include <aidl/android/hardware/camera/device/CameraBlobId.h>
+#include <camera/StringUtils.h>
 
 #include "api1/client2/JpegProcessor.h"
 #include "common/CameraProviderManager.h"
@@ -495,17 +496,17 @@
     status_t err;
     int format;
     if ((err = anw->query(anw, NATIVE_WINDOW_FORMAT, &format)) != OK) {
-        String8 msg = String8::format("Failed to query Surface format: %s (%d)", strerror(-err),
+        std::string msg = fmt::sprintf("Failed to query Surface format: %s (%d)", strerror(-err),
                 err);
-        ALOGE("%s: %s", __FUNCTION__, msg.string());
+        ALOGE("%s: %s", __FUNCTION__, msg.c_str());
         return false;
     }
 
     int dataspace;
     if ((err = anw->query(anw, NATIVE_WINDOW_DEFAULT_DATASPACE, &dataspace)) != OK) {
-        String8 msg = String8::format("Failed to query Surface dataspace: %s (%d)", strerror(-err),
+        std::string msg = fmt::sprintf("Failed to query Surface dataspace: %s (%d)", strerror(-err),
                 err);
-        ALOGE("%s: %s", __FUNCTION__, msg.string());
+        ALOGE("%s: %s", __FUNCTION__, msg.c_str());
         return false;
     }
 
@@ -578,7 +579,7 @@
 
 status_t DepthCompositeStream::createInternalStreams(const std::vector<sp<Surface>>& consumers,
         bool /*hasDeferredConsumer*/, uint32_t width, uint32_t height, int format,
-        camera_stream_rotation_t rotation, int *id, const String8& physicalCameraId,
+        camera_stream_rotation_t rotation, int *id, const std::string& physicalCameraId,
         const std::unordered_set<int32_t> &sensorPixelModesUsed,
         std::vector<int> *surfaceIds,
         int /*streamSetId*/, bool /*isShared*/, int32_t /*colorSpace*/,
diff --git a/services/camera/libcameraservice/api2/DepthCompositeStream.h b/services/camera/libcameraservice/api2/DepthCompositeStream.h
index fbe99dd..f797f9c 100644
--- a/services/camera/libcameraservice/api2/DepthCompositeStream.h
+++ b/services/camera/libcameraservice/api2/DepthCompositeStream.h
@@ -50,7 +50,7 @@
     // CompositeStream overrides
     status_t createInternalStreams(const std::vector<sp<Surface>>& consumers,
             bool hasDeferredConsumer, uint32_t width, uint32_t height, int format,
-            camera_stream_rotation_t rotation, int *id, const String8& physicalCameraId,
+            camera_stream_rotation_t rotation, int *id, const std::string& physicalCameraId,
             const std::unordered_set<int32_t> &sensorPixelModesUsed,
             std::vector<int> *surfaceIds,
             int streamSetId, bool isShared, int32_t colorSpace,
diff --git a/services/camera/libcameraservice/api2/HeicCompositeStream.cpp b/services/camera/libcameraservice/api2/HeicCompositeStream.cpp
index 694aff3..8144792 100644
--- a/services/camera/libcameraservice/api2/HeicCompositeStream.cpp
+++ b/services/camera/libcameraservice/api2/HeicCompositeStream.cpp
@@ -29,6 +29,7 @@
 #include <gui/Surface.h>
 #include <utils/Log.h>
 #include <utils/Trace.h>
+#include <camera/StringUtils.h>
 
 #include <mediadrm/ICrypto.h>
 #include <media/MediaCodecBuffer.h>
@@ -98,17 +99,17 @@
     status_t err;
     int format;
     if ((err = anw->query(anw, NATIVE_WINDOW_FORMAT, &format)) != OK) {
-        String8 msg = String8::format("Failed to query Surface format: %s (%d)", strerror(-err),
+        std::string msg = fmt::sprintf("Failed to query Surface format: %s (%d)", strerror(-err),
                 err);
-        ALOGE("%s: %s", __FUNCTION__, msg.string());
+        ALOGE("%s: %s", __FUNCTION__, msg.c_str());
         return false;
     }
 
     int dataspace;
     if ((err = anw->query(anw, NATIVE_WINDOW_DEFAULT_DATASPACE, &dataspace)) != OK) {
-        String8 msg = String8::format("Failed to query Surface dataspace: %s (%d)", strerror(-err),
+        std::string msg = fmt::sprintf("Failed to query Surface dataspace: %s (%d)", strerror(-err),
                 err);
-        ALOGE("%s: %s", __FUNCTION__, msg.string());
+        ALOGE("%s: %s", __FUNCTION__, msg.c_str());
         return false;
     }
 
@@ -117,7 +118,7 @@
 
 status_t HeicCompositeStream::createInternalStreams(const std::vector<sp<Surface>>& consumers,
         bool /*hasDeferredConsumer*/, uint32_t width, uint32_t height, int format,
-        camera_stream_rotation_t rotation, int *id, const String8& physicalCameraId,
+        camera_stream_rotation_t rotation, int *id, const std::string& physicalCameraId,
         const std::unordered_set<int32_t> &sensorPixelModesUsed,
         std::vector<int> *surfaceIds,
         int /*streamSetId*/, bool /*isShared*/, int32_t colorSpace,
diff --git a/services/camera/libcameraservice/api2/HeicCompositeStream.h b/services/camera/libcameraservice/api2/HeicCompositeStream.h
index 602a247..b539cdd 100644
--- a/services/camera/libcameraservice/api2/HeicCompositeStream.h
+++ b/services/camera/libcameraservice/api2/HeicCompositeStream.h
@@ -45,7 +45,7 @@
 
     status_t createInternalStreams(const std::vector<sp<Surface>>& consumers,
             bool hasDeferredConsumer, uint32_t width, uint32_t height, int format,
-            camera_stream_rotation_t rotation, int *id, const String8& physicalCameraId,
+            camera_stream_rotation_t rotation, int *id, const std::string& physicalCameraId,
             const std::unordered_set<int32_t> &sensorPixelModesUsed,
             std::vector<int> *surfaceIds, int streamSetId, bool isShared, int32_t colorSpace,
             int64_t dynamicProfile, int64_t streamUseCase, bool useReadoutTimestamp) override;
diff --git a/services/camera/libcameraservice/api2/JpegRCompositeStream.cpp b/services/camera/libcameraservice/api2/JpegRCompositeStream.cpp
index 6588470..988446b 100644
--- a/services/camera/libcameraservice/api2/JpegRCompositeStream.cpp
+++ b/services/camera/libcameraservice/api2/JpegRCompositeStream.cpp
@@ -548,7 +548,7 @@
 
 status_t JpegRCompositeStream::createInternalStreams(const std::vector<sp<Surface>>& consumers,
         bool /*hasDeferredConsumer*/, uint32_t width, uint32_t height, int format,
-        camera_stream_rotation_t rotation, int *id, const String8& physicalCameraId,
+        camera_stream_rotation_t rotation, int *id, const std::string& physicalCameraId,
         const std::unordered_set<int32_t> &sensorPixelModesUsed,
         std::vector<int> *surfaceIds,
         int /*streamSetId*/, bool /*isShared*/, int32_t colorSpace,
diff --git a/services/camera/libcameraservice/api2/JpegRCompositeStream.h b/services/camera/libcameraservice/api2/JpegRCompositeStream.h
index 3dfed30..016d57c 100644
--- a/services/camera/libcameraservice/api2/JpegRCompositeStream.h
+++ b/services/camera/libcameraservice/api2/JpegRCompositeStream.h
@@ -47,7 +47,7 @@
     // CompositeStream overrides
     status_t createInternalStreams(const std::vector<sp<Surface>>& consumers,
             bool hasDeferredConsumer, uint32_t width, uint32_t height, int format,
-            camera_stream_rotation_t rotation, int *id, const String8& physicalCameraId,
+            camera_stream_rotation_t rotation, int *id, const std::string& physicalCameraId,
             const std::unordered_set<int32_t> &sensorPixelModesUsed,
             std::vector<int> *surfaceIds,
             int streamSetId, bool isShared, int32_t colorSpace,
diff --git a/services/camera/libcameraservice/common/Camera2ClientBase.cpp b/services/camera/libcameraservice/common/Camera2ClientBase.cpp
index 6e10f30..a54ba9b 100644
--- a/services/camera/libcameraservice/common/Camera2ClientBase.cpp
+++ b/services/camera/libcameraservice/common/Camera2ClientBase.cpp
@@ -28,6 +28,7 @@
 #include <gui/Surface.h>
 
 #include <camera/CameraSessionStats.h>
+#include <camera/StringUtils.h>
 
 #include "common/Camera2ClientBase.h"
 
@@ -49,10 +50,10 @@
         const sp<CameraService>& cameraService,
         const sp<TCamCallbacks>& remoteCallback,
         std::shared_ptr<CameraServiceProxyWrapper> cameraServiceProxyWrapper,
-        const String16& clientPackageName,
+        const std::string& clientPackageName,
         bool systemNativeClient,
-        const std::optional<String16>& clientFeatureId,
-        const String8& cameraId,
+        const std::optional<std::string>& clientFeatureId,
+        const std::string& cameraId,
         int api1CameraId,
         int cameraFacing,
         int sensorOrientation,
@@ -69,8 +70,8 @@
         mCameraServiceProxyWrapper(cameraServiceProxyWrapper),
         mDeviceActive(false), mApi1CameraId(api1CameraId)
 {
-    ALOGI("Camera %s: Opened. Client: %s (PID %d, UID %d)", cameraId.string(),
-            String8(clientPackageName).string(), clientPid, clientUid);
+    ALOGI("Camera %s: Opened. Client: %s (PID %d, UID %d)", cameraId.c_str(),
+            clientPackageName.c_str(), clientPid, clientUid);
 
     mInitialClientPid = clientPid;
     mOverrideForPerfClass = overrideForPerfClass;
@@ -91,21 +92,21 @@
 
 template <typename TClientBase>
 status_t Camera2ClientBase<TClientBase>::initialize(sp<CameraProviderManager> manager,
-        const String8& monitorTags) {
+        const std::string& monitorTags) {
     return initializeImpl(manager, monitorTags);
 }
 
 template <typename TClientBase>
 template <typename TProviderPtr>
 status_t Camera2ClientBase<TClientBase>::initializeImpl(TProviderPtr providerPtr,
-        const String8& monitorTags) {
+        const std::string& monitorTags) {
     ATRACE_CALL();
     ALOGV("%s: Initializing client for camera %s", __FUNCTION__,
-          TClientBase::mCameraIdStr.string());
+          TClientBase::mCameraIdStr.c_str());
     status_t res;
 
     IPCTransport providerTransport = IPCTransport::INVALID;
-    res = providerPtr->getCameraIdIPCTransport(TClientBase::mCameraIdStr.string(),
+    res = providerPtr->getCameraIdIPCTransport(TClientBase::mCameraIdStr,
             &providerTransport);
     if (res != OK) {
         return res;
@@ -125,19 +126,19 @@
              break;
         default:
             ALOGE("%s Invalid transport for camera id %s", __FUNCTION__,
-                    TClientBase::mCameraIdStr.string());
+                    TClientBase::mCameraIdStr.c_str());
             return NO_INIT;
     }
     if (mDevice == NULL) {
         ALOGE("%s: Camera %s: No device connected",
-                __FUNCTION__, TClientBase::mCameraIdStr.string());
+                __FUNCTION__, TClientBase::mCameraIdStr.c_str());
         return NO_INIT;
     }
 
     res = mDevice->initialize(providerPtr, monitorTags);
     if (res != OK) {
         ALOGE("%s: Camera %s: unable to initialize device: %s (%d)",
-                __FUNCTION__, TClientBase::mCameraIdStr.string(), strerror(-res), res);
+                __FUNCTION__, TClientBase::mCameraIdStr.c_str(), strerror(-res), res);
         return res;
     }
 
@@ -152,7 +153,7 @@
     res = mDevice->setNotifyCallback(weakThis);
     if (res != OK) {
         ALOGE("%s: Camera %s: Unable to set notify callback: %s (%d)",
-                __FUNCTION__, TClientBase::mCameraIdStr.string(), strerror(-res), res);
+                __FUNCTION__, TClientBase::mCameraIdStr.c_str(), strerror(-res), res);
         return res;
     }
 
@@ -183,30 +184,30 @@
     }
 
     ALOGI("%s: Client object's dtor for Camera Id %s completed. Client was: %s (PID %d, UID %u)",
-            __FUNCTION__, TClientBase::mCameraIdStr.string(),
-            String8(TClientBase::mClientPackageName).string(),
+            __FUNCTION__, TClientBase::mCameraIdStr.c_str(),
+            TClientBase::mClientPackageName.c_str(),
             mInitialClientPid, TClientBase::mClientUid);
 }
 
 template <typename TClientBase>
 status_t Camera2ClientBase<TClientBase>::dumpClient(int fd,
                                               const Vector<String16>& args) {
-    String8 result;
-    result.appendFormat("Camera2ClientBase[%s] (%p) PID: %d, dump:\n",
-            TClientBase::mCameraIdStr.string(),
+    std::string result;
+    result += fmt::sprintf("Camera2ClientBase[%s] (%p) PID: %d, dump:\n",
+            TClientBase::mCameraIdStr.c_str(),
             (TClientBase::getRemoteCallback() != NULL ?
-                    IInterface::asBinder(TClientBase::getRemoteCallback()).get() : NULL),
+                    (void *)IInterface::asBinder(TClientBase::getRemoteCallback()).get() : NULL),
             TClientBase::mClientPid);
-    result.append("  State: ");
+    result += "  State: ";
 
-    write(fd, result.string(), result.size());
+    write(fd, result.c_str(), result.size());
     // TODO: print dynamic/request section from most recent requests
 
     return dumpDevice(fd, args);
 }
 
 template <typename TClientBase>
-status_t Camera2ClientBase<TClientBase>::startWatchingTags(const String8 &tags, int out) {
+status_t Camera2ClientBase<TClientBase>::startWatchingTags(const std::string &tags, int out) {
   sp<CameraDeviceBase> device = mDevice;
   if (!device) {
     dprintf(out, "  Device is detached");
@@ -241,23 +242,23 @@
 status_t Camera2ClientBase<TClientBase>::dumpDevice(
                                                 int fd,
                                                 const Vector<String16>& args) {
-    String8 result;
+    std::string result;
 
     result = "  Device dump:\n";
-    write(fd, result.string(), result.size());
+    write(fd, result.c_str(), result.size());
 
     sp<CameraDeviceBase> device = mDevice;
     if (!device.get()) {
         result = "  *** Device is detached\n";
-        write(fd, result.string(), result.size());
+        write(fd, result.c_str(), result.size());
         return NO_ERROR;
     }
 
     status_t res = device->dump(fd, args);
     if (res != OK) {
-        result = String8::format("   Error dumping device: %s (%d)",
+        result = fmt::sprintf("   Error dumping device: %s (%d)",
                 strerror(-res), res);
-        write(fd, result.string(), result.size());
+        write(fd, result.c_str(), result.size());
     }
 
     return NO_ERROR;
@@ -284,23 +285,23 @@
 template <typename TClientBase>
 binder::Status Camera2ClientBase<TClientBase>::disconnectImpl() {
     ATRACE_CALL();
-    ALOGD("Camera %s: start to disconnect", TClientBase::mCameraIdStr.string());
+    ALOGD("Camera %s: start to disconnect", TClientBase::mCameraIdStr.c_str());
     Mutex::Autolock icl(mBinderSerializationLock);
 
-    ALOGD("Camera %s: serializationLock acquired", TClientBase::mCameraIdStr.string());
+    ALOGD("Camera %s: serializationLock acquired", TClientBase::mCameraIdStr.c_str());
     binder::Status res = binder::Status::ok();
     // Allow both client and the media server to disconnect at all times
     int callingPid = CameraThreadState::getCallingPid();
     if (callingPid != TClientBase::mClientPid &&
         callingPid != TClientBase::mServicePid) return res;
 
-    ALOGD("Camera %s: Shutting down", TClientBase::mCameraIdStr.string());
+    ALOGD("Camera %s: Shutting down", TClientBase::mCameraIdStr.c_str());
 
     // Before detaching the device, cache the info from current open session.
     // The disconnected check avoids duplication of info and also prevents
     // deadlock while acquiring service lock in cacheDump.
     if (!TClientBase::mDisconnected) {
-        ALOGD("Camera %s: start to cacheDump", TClientBase::mCameraIdStr.string());
+        ALOGD("Camera %s: start to cacheDump", TClientBase::mCameraIdStr.c_str());
         Camera2ClientBase::getCameraService()->cacheDump();
     }
 
@@ -308,7 +309,7 @@
 
     CameraService::BasicClient::disconnect();
 
-    ALOGV("Camera %s: Shut down complete", TClientBase::mCameraIdStr.string());
+    ALOGV("Camera %s: Shut down complete", TClientBase::mCameraIdStr.c_str());
 
     return res;
 }
@@ -318,7 +319,7 @@
     if (mDevice == 0) return;
     mDevice->disconnect();
 
-    ALOGV("Camera %s: Detach complete", TClientBase::mCameraIdStr.string());
+    ALOGV("Camera %s: Detach complete", TClientBase::mCameraIdStr.c_str());
 }
 
 template <typename TClientBase>
@@ -334,7 +335,7 @@
         ALOGE("%s: Camera %s: Connection attempt from pid %d; "
                 "current locked to pid %d",
                 __FUNCTION__,
-                TClientBase::mCameraIdStr.string(),
+                TClientBase::mCameraIdStr.c_str(),
                 CameraThreadState::getCallingPid(),
                 TClientBase::mClientPid);
         return BAD_VALUE;
@@ -365,8 +366,7 @@
         return;
     }
 
-    String8 physicalId8(physicalId.c_str());
-    auto physicalCameraMetadata = mDevice->infoPhysical(physicalId8);
+    auto physicalCameraMetadata = mDevice->infoPhysical(physicalId);
     auto orientationEntry = physicalCameraMetadata.find(ANDROID_SENSOR_ORIENTATION);
 
     if (orientationEntry.count == 1) {
@@ -387,7 +387,7 @@
         status_t res = TClientBase::startCameraStreamingOps();
         if (res != OK) {
             ALOGE("%s: Camera %s: Error starting camera streaming ops: %d", __FUNCTION__,
-                    TClientBase::mCameraIdStr.string(), res);
+                    TClientBase::mCameraIdStr.c_str(), res);
             return res;
         }
         mCameraServiceProxyWrapper->logActive(TClientBase::mCameraIdStr, maxPreviewFps);
@@ -407,7 +407,7 @@
         status_t res = TClientBase::finishCameraStreamingOps();
         if (res != OK) {
             ALOGE("%s: Camera %s: Error finishing streaming ops: %d", __FUNCTION__,
-                    TClientBase::mCameraIdStr.string(), res);
+                    TClientBase::mCameraIdStr.c_str(), res);
         }
         mCameraServiceProxyWrapper->logIdle(TClientBase::mCameraIdStr,
                 requestCount, resultErrorCount, deviceError, userTag, videoStabilizationMode,
@@ -522,7 +522,7 @@
 }
 
 template <typename TClientBase>
-status_t Camera2ClientBase<TClientBase>::injectCamera(const String8& injectedCamId,
+status_t Camera2ClientBase<TClientBase>::injectCamera(const std::string& injectedCamId,
         sp<CameraProviderManager> manager) {
     return mDevice->injectCamera(injectedCamId, manager);
 }
diff --git a/services/camera/libcameraservice/common/Camera2ClientBase.h b/services/camera/libcameraservice/common/Camera2ClientBase.h
index 5cf3033..30c763d 100644
--- a/services/camera/libcameraservice/common/Camera2ClientBase.h
+++ b/services/camera/libcameraservice/common/Camera2ClientBase.h
@@ -50,10 +50,10 @@
     Camera2ClientBase(const sp<CameraService>& cameraService,
                       const sp<TCamCallbacks>& remoteCallback,
                       std::shared_ptr<CameraServiceProxyWrapper> cameraServiceProxyWrapper,
-                      const String16& clientPackageName,
+                      const std::string& clientPackageName,
                       bool systemNativeClient,
-                      const std::optional<String16>& clientFeatureId,
-                      const String8& cameraId,
+                      const std::optional<std::string>& clientFeatureId,
+                      const std::string& cameraId,
                       int api1CameraId,
                       int cameraFacing,
                       int sensorOrientation,
@@ -65,11 +65,12 @@
                       bool legacyClient = false);
     virtual ~Camera2ClientBase();
 
-    virtual status_t      initialize(sp<CameraProviderManager> manager, const String8& monitorTags);
-    virtual status_t      dumpClient(int fd, const Vector<String16>& args);
-    virtual status_t      startWatchingTags(const String8 &tags, int out);
-    virtual status_t      stopWatchingTags(int out);
-    virtual status_t      dumpWatchedEventsToVector(std::vector<std::string> &out);
+    virtual status_t      initialize(sp<CameraProviderManager> manager,
+            const std::string& monitorTags) override;
+    virtual status_t      dumpClient(int fd, const Vector<String16>& args) override;
+    virtual status_t      startWatchingTags(const std::string &tags, int out) override;
+    virtual status_t      stopWatchingTags(int out) override;
+    virtual status_t      dumpWatchedEventsToVector(std::vector<std::string> &out) override;
 
     /**
      * NotificationListener implementation
@@ -130,7 +131,7 @@
         mutable Mutex mRemoteCallbackLock;
     } mSharedCameraCallbacks;
 
-    status_t      injectCamera(const String8& injectedCamId,
+    status_t      injectCamera(const std::string& injectedCamId,
                                sp<CameraProviderManager> manager) override;
     status_t      stopInjection() override;
 
@@ -181,7 +182,7 @@
 
 private:
     template<typename TProviderPtr>
-    status_t              initializeImpl(TProviderPtr providerPtr, const String8& monitorTags);
+    status_t              initializeImpl(TProviderPtr providerPtr, const std::string& monitorTags);
 
     binder::Status disconnectImpl();
 
diff --git a/services/camera/libcameraservice/common/CameraDeviceBase.h b/services/camera/libcameraservice/common/CameraDeviceBase.h
index 919108d..017da0f 100644
--- a/services/camera/libcameraservice/common/CameraDeviceBase.h
+++ b/services/camera/libcameraservice/common/CameraDeviceBase.h
@@ -20,7 +20,6 @@
 #include <list>
 
 #include <utils/RefBase.h>
-#include <utils/String8.h>
 #include <utils/String16.h>
 #include <utils/Vector.h>
 #include <utils/KeyedVector.h>
@@ -99,11 +98,12 @@
      */
     virtual metadata_vendor_id_t getVendorTagId() const = 0;
 
-    virtual status_t initialize(sp<CameraProviderManager> manager, const String8& monitorTags) = 0;
+    virtual status_t initialize(sp<CameraProviderManager> manager,
+            const std::string& monitorTags) = 0;
     virtual status_t disconnect() = 0;
 
     virtual status_t dump(int fd, const Vector<String16> &args) = 0;
-    virtual status_t startWatchingTags(const String8 &tags) = 0;
+    virtual status_t startWatchingTags(const std::string &tags) = 0;
     virtual status_t stopWatchingTags() = 0;
     virtual status_t dumpWatchedEventsToVector(std::vector<std::string> &out) = 0;
 
@@ -111,7 +111,7 @@
      * The physical camera device's static characteristics metadata buffer, or
      * the logical camera's static characteristics if physical id is empty.
      */
-    virtual const CameraMetadata& infoPhysical(const String8& physicalId) const = 0;
+    virtual const CameraMetadata& infoPhysical(const std::string& physicalId) const = 0;
 
     virtual bool isCompositeJpegRDisabled() const { return false; };
 
@@ -188,7 +188,7 @@
     virtual status_t createStream(sp<Surface> consumer,
             uint32_t width, uint32_t height, int format,
             android_dataspace dataSpace, camera_stream_rotation_t rotation, int *id,
-            const String8& physicalCameraId,
+            const std::string& physicalCameraId,
             const std::unordered_set<int32_t>  &sensorPixelModesUsed,
             std::vector<int> *surfaceIds = nullptr,
             int streamSetId = camera3::CAMERA3_STREAM_SET_ID_INVALID,
@@ -212,7 +212,7 @@
     virtual status_t createStream(const std::vector<sp<Surface>>& consumers,
             bool hasDeferredConsumer, uint32_t width, uint32_t height, int format,
             android_dataspace dataSpace, camera_stream_rotation_t rotation, int *id,
-            const String8& physicalCameraId,
+            const std::string& physicalCameraId,
             const std::unordered_set<int32_t> &sensorPixelModesUsed,
             std::vector<int> *surfaceIds = nullptr,
             int streamSetId = camera3::CAMERA3_STREAM_SET_ID_INVALID,
@@ -510,7 +510,7 @@
      * The injection camera session to replace the internal camera
      * session.
      */
-    virtual status_t injectCamera(const String8& injectedCamId,
+    virtual status_t injectCamera(const std::string& injectedCamId,
             sp<CameraProviderManager> manager) = 0;
 
     /**
diff --git a/services/camera/libcameraservice/common/CameraOfflineSessionBase.h b/services/camera/libcameraservice/common/CameraOfflineSessionBase.h
index 63abcf0..976c47c 100644
--- a/services/camera/libcameraservice/common/CameraOfflineSessionBase.h
+++ b/services/camera/libcameraservice/common/CameraOfflineSessionBase.h
@@ -20,7 +20,6 @@
 #include <vector>
 
 #include <utils/RefBase.h>
-#include <utils/String8.h>
 #include <utils/Timers.h>
 
 #include "camera/CaptureResult.h"
diff --git a/services/camera/libcameraservice/common/CameraProviderManager.cpp b/services/camera/libcameraservice/common/CameraProviderManager.cpp
index 1a6e341..23051ef 100644
--- a/services/camera/libcameraservice/common/CameraProviderManager.cpp
+++ b/services/camera/libcameraservice/common/CameraProviderManager.cpp
@@ -43,6 +43,7 @@
 #include <hwbinder/IPCThreadState.h>
 #include <utils/Trace.h>
 #include <ui/PublicFormat.h>
+#include <camera/StringUtils.h>
 
 #include "api2/HeicCompositeStream.h"
 #include "device3/ZoomRatioMapper.h"
@@ -143,7 +144,7 @@
             String16(aidlHalServiceDescriptor));
     for (const auto &aidlInstance : aidlProviders) {
         std::string aidlServiceName =
-                getFullAidlProviderName(std::string(String8(aidlInstance).c_str()));
+                getFullAidlProviderName(toStdString(aidlInstance));
         auto res = sm->registerForNotifications(String16(aidlServiceName.c_str()), this);
         if (res != OK) {
             ALOGE("%s Unable to register for notifications with AIDL service manager",
@@ -774,14 +775,14 @@
         primaryMap = &mCameraProviderByCameraId;
         alternateMap = &mTorchProviderByCameraId;
     }
-    auto id = cameraId.c_str();
-    (*primaryMap)[id] = provider;
-    auto search = alternateMap->find(id);
+
+    (*primaryMap)[cameraId] = provider;
+    auto search = alternateMap->find(cameraId);
     if (search != alternateMap->end()) {
         ALOGW("%s: Camera device %s is using both torch mode and camera mode simultaneously. "
-                "That should not be possible", __FUNCTION__, id);
+                "That should not be possible", __FUNCTION__, cameraId.c_str());
     }
-    ALOGV("%s: Camera device %s connected", __FUNCTION__, id);
+    ALOGV("%s: Camera device %s connected", __FUNCTION__, cameraId.c_str());
 }
 
 void CameraProviderManager::removeRef(DeviceMode usageType, const std::string &cameraId) {
@@ -796,7 +797,7 @@
         providerMap = &mCameraProviderByCameraId;
     }
     std::lock_guard<std::mutex> lock(mProviderInterfaceMapLock);
-    auto search = providerMap->find(cameraId.c_str());
+    auto search = providerMap->find(cameraId);
     if (search != providerMap->end()) {
         // Drop the reference to this ICameraProvider. This is safe to do immediately (without an
         // added delay) because hwservicemanager guarantees to hold the reference for at least five
@@ -805,7 +806,7 @@
         // restart it. An example when this could happen is switching from a front-facing to a
         // rear-facing camera. If the HAL were to exit during the camera switch, the camera could
         // appear janky to the user.
-        providerMap->erase(cameraId.c_str());
+        providerMap->erase(cameraId);
         IPCThreadState::self()->flushCommands();
     } else {
         ALOGE("%s: Asked to remove reference for camera %s, but no reference to it was found. This "
@@ -823,7 +824,7 @@
     {
         std::lock_guard<std::mutex> lock(mInterfaceMutex);
 
-        res = addAidlProviderLocked(String8(name).c_str());
+        res = addAidlProviderLocked(toStdString(name));
     }
 
     sp<StatusListener> listener = getStatusListener();
@@ -2035,14 +2036,14 @@
 status_t CameraProviderManager::removeProvider(const std::string& provider) {
     std::lock_guard<std::mutex> providerLock(mProviderLifecycleLock);
     std::unique_lock<std::mutex> lock(mInterfaceMutex);
-    std::vector<String8> removedDeviceIds;
+    std::vector<std::string> removedDeviceIds;
     status_t res = NAME_NOT_FOUND;
     std::string removedProviderName;
     for (auto it = mProviders.begin(); it != mProviders.end(); it++) {
         if ((*it)->mProviderInstance == provider) {
             removedDeviceIds.reserve((*it)->mDevices.size());
             for (auto& deviceInfo : (*it)->mDevices) {
-                removedDeviceIds.push_back(String8(deviceInfo->mId.c_str()));
+                removedDeviceIds.push_back(deviceInfo->mId);
             }
             removedProviderName = (*it)->mProviderName;
             mProviders.erase(it);
@@ -2182,7 +2183,7 @@
     return OK;
 }
 
-void CameraProviderManager::ProviderInfo::removeDevice(std::string id) {
+void CameraProviderManager::ProviderInfo::removeDevice(const std::string &id) {
     for (auto it = mDevices.begin(); it != mDevices.end(); it++) {
         if ((*it)->mId == id) {
             mUniqueCameraIds.erase(id);
@@ -2222,8 +2223,7 @@
             ALOGV("%s: notify device not_present: %s",
                   __FUNCTION__,
                   deviceName.c_str());
-            listener->onDeviceStatusChanged(String8(id.c_str()),
-                                            CameraDeviceStatus::NOT_PRESENT);
+            listener->onDeviceStatusChanged(id, CameraDeviceStatus::NOT_PRESENT);
             mLock.lock();
         }
     }
@@ -2324,8 +2324,7 @@
     CameraDeviceStatus internalNewStatus = newStatus;
     if (!mInitialized) {
         mCachedStatus.emplace_back(false /*isPhysicalCameraStatus*/,
-                cameraDeviceName.c_str(), std::string().c_str(),
-                internalNewStatus);
+                cameraDeviceName, std::string(), internalNewStatus);
         return;
     }
 
@@ -2339,7 +2338,7 @@
 
     // Call without lock held to allow reentrancy into provider manager
     if (listener != nullptr) {
-        listener->onDeviceStatusChanged(String8(id.c_str()), internalNewStatus);
+        listener->onDeviceStatusChanged(id, internalNewStatus);
     }
 }
 
@@ -2415,8 +2414,7 @@
     }
     // Call without lock held to allow reentrancy into provider manager
     if (listener != nullptr) {
-        listener->onDeviceStatusChanged(String8(id.c_str()),
-                String8(physicalId.c_str()), newStatus);
+        listener->onDeviceStatusChanged(id, physicalId, newStatus);
     }
     return;
 }
@@ -2467,7 +2465,7 @@
     }
 
     *id = cameraId;
-    *physicalId = physicalCameraDeviceName.c_str();
+    *physicalId = physicalCameraDeviceName;
     return OK;
 }
 
@@ -2511,7 +2509,7 @@
     // findDeviceInfo, which should be holding mLock while iterating through
     // each provider's devices).
     if (listener != nullptr) {
-        listener->onTorchStatusChanged(String8(id.c_str()), newStatus, systemCameraKind);
+        listener->onTorchStatusChanged(id, newStatus, systemCameraKind);
     }
     return;
 }
diff --git a/services/camera/libcameraservice/common/CameraProviderManager.h b/services/camera/libcameraservice/common/CameraProviderManager.h
index e6e4619..a2ec576 100644
--- a/services/camera/libcameraservice/common/CameraProviderManager.h
+++ b/services/camera/libcameraservice/common/CameraProviderManager.h
@@ -179,15 +179,15 @@
     struct StatusListener : virtual public RefBase {
         ~StatusListener() {}
 
-        virtual void onDeviceStatusChanged(const String8 &cameraId,
+        virtual void onDeviceStatusChanged(const std::string &cameraId,
                 CameraDeviceStatus newStatus) = 0;
-        virtual void onDeviceStatusChanged(const String8 &cameraId,
-                const String8 &physicalCameraId,
+        virtual void onDeviceStatusChanged(const std::string &cameraId,
+                const std::string &physicalCameraId,
                 CameraDeviceStatus newStatus) = 0;
-        virtual void onTorchStatusChanged(const String8 &cameraId,
+        virtual void onTorchStatusChanged(const std::string &cameraId,
                 TorchModeStatus newStatus,
                 SystemCameraKind kind) = 0;
-        virtual void onTorchStatusChanged(const String8 &cameraId,
+        virtual void onTorchStatusChanged(const std::string &cameraId,
                 TorchModeStatus newStatus) = 0;
         virtual void onNewProviderRegistered() = 0;
     };
@@ -784,7 +784,7 @@
         void torchModeStatusChangeInternal(const std::string& cameraDeviceName,
                 TorchModeStatus newStatus);
 
-        void removeDevice(std::string id);
+        void removeDevice(const std::string &id);
 
     };
 
diff --git a/services/camera/libcameraservice/common/FrameProcessorBase.cpp b/services/camera/libcameraservice/common/FrameProcessorBase.cpp
index e259379..2322def 100644
--- a/services/camera/libcameraservice/common/FrameProcessorBase.cpp
+++ b/services/camera/libcameraservice/common/FrameProcessorBase.cpp
@@ -21,6 +21,7 @@
 #include <map>
 #include <utils/Log.h>
 #include <utils/Trace.h>
+#include <camera/StringUtils.h>
 
 #include "common/FrameProducer.h"
 #include "common/FrameProcessorBase.h"
@@ -86,8 +87,8 @@
 }
 
 void FrameProcessorBase::dump(int fd, const Vector<String16>& /*args*/) {
-    String8 result("    Latest received frame:\n");
-    write(fd, result.string(), result.size());
+    std::string result("    Latest received frame:\n");
+    write(fd, result.c_str(), result.size());
 
     CameraMetadata lastFrame;
     std::map<std::string, CameraMetadata> lastPhysicalFrames;
@@ -97,16 +98,16 @@
         lastFrame = CameraMetadata(mLastFrame);
 
         for (const auto& physicalFrame : mLastPhysicalFrames) {
-            lastPhysicalFrames.emplace(String8(physicalFrame.mPhysicalCameraId),
+            lastPhysicalFrames.emplace(physicalFrame.mPhysicalCameraId,
                     physicalFrame.mPhysicalCameraMetadata);
         }
     }
     lastFrame.dump(fd, /*verbosity*/2, /*indentation*/6);
 
     for (const auto& physicalFrame : lastPhysicalFrames) {
-        result = String8::format("   Latest received frame for physical camera %s:\n",
+        result = fmt::sprintf("   Latest received frame for physical camera %s:\n",
                 physicalFrame.first.c_str());
-        write(fd, result.string(), result.size());
+        write(fd, result.c_str(), result.size());
         CameraMetadata lastPhysicalMetadata = CameraMetadata(physicalFrame.second);
         lastPhysicalMetadata.sort();
         lastPhysicalMetadata.dump(fd, /*verbosity*/2, /*indentation*/6);
@@ -138,7 +139,7 @@
     ATRACE_CALL();
     CaptureResult result;
 
-    ALOGV("%s: Camera %s: Process new frames", __FUNCTION__, device->getId().string());
+    ALOGV("%s: Camera %s: Process new frames", __FUNCTION__, device->getId().c_str());
 
     while ( (res = device->getNextResult(&result)) == OK) {
 
@@ -149,7 +150,7 @@
         entry = result.mMetadata.find(ANDROID_REQUEST_FRAME_COUNT);
         if (entry.count == 0) {
             ALOGE("%s: Camera %s: Error reading frame number",
-                    __FUNCTION__, device->getId().string());
+                    __FUNCTION__, device->getId().c_str());
             break;
         }
         ATRACE_INT("cam2_frame", entry.data.i32[0]);
@@ -167,7 +168,7 @@
     }
     if (res != NOT_ENOUGH_DATA) {
         ALOGE("%s: Camera %s: Error getting next frame: %s (%d)",
-                __FUNCTION__, device->getId().string(), strerror(-res), res);
+                __FUNCTION__, device->getId().c_str(), strerror(-res), res);
         return;
     }
 
@@ -177,7 +178,7 @@
 bool FrameProcessorBase::processSingleFrame(CaptureResult &result,
                                             const sp<FrameProducer> &device) {
     ALOGV("%s: Camera %s: Process single frame (is empty? %d)",
-            __FUNCTION__, device->getId().string(), result.mMetadata.isEmpty());
+            __FUNCTION__, device->getId().c_str(), result.mMetadata.isEmpty());
     return processListeners(result, device) == OK;
 }
 
@@ -197,7 +198,7 @@
     // include CaptureResultExtras.
     entry = result.mMetadata.find(ANDROID_REQUEST_ID);
     if (entry.count == 0) {
-        ALOGE("%s: Camera %s: Error reading frame id", __FUNCTION__, device->getId().string());
+        ALOGE("%s: Camera %s: Error reading frame id", __FUNCTION__, device->getId().c_str());
         return BAD_VALUE;
     }
     int32_t requestId = entry.data.i32[0];
@@ -223,7 +224,7 @@
         }
     }
     ALOGV("%s: Camera %s: Got %zu range listeners out of %zu", __FUNCTION__,
-          device->getId().string(), listeners.size(), mRangeListeners.size());
+          device->getId().c_str(), listeners.size(), mRangeListeners.size());
 
     List<sp<FilteredListener> >::iterator item = listeners.begin();
     for (; item != listeners.end(); item++) {
diff --git a/services/camera/libcameraservice/common/FrameProducer.h b/services/camera/libcameraservice/common/FrameProducer.h
index a14b3d6..dd4df7d 100644
--- a/services/camera/libcameraservice/common/FrameProducer.h
+++ b/services/camera/libcameraservice/common/FrameProducer.h
@@ -18,7 +18,6 @@
 #define ANDROID_SERVERS_CAMERA_FRAMEPRODUCER_H
 
 #include <utils/RefBase.h>
-#include <utils/String8.h>
 #include <utils/Timers.h>
 
 #include "camera/CameraMetadata.h"
@@ -39,7 +38,7 @@
     /**
      * Retrieve the device camera ID
      */
-    virtual const String8& getId() const = 0;
+    virtual const std::string& getId() const = 0;
 
     /**
      * Wait for a new frame to be produced, with timeout in nanoseconds.
diff --git a/services/camera/libcameraservice/common/aidl/AidlProviderInfo.cpp b/services/camera/libcameraservice/common/aidl/AidlProviderInfo.cpp
index b18cbd4..5e79d6b 100644
--- a/services/camera/libcameraservice/common/aidl/AidlProviderInfo.cpp
+++ b/services/camera/libcameraservice/common/aidl/AidlProviderInfo.cpp
@@ -431,7 +431,7 @@
     for (const auto& combination : combs) {
         std::unordered_set<std::string> deviceIds;
         for (const auto &cameraDeviceId : combination.combination) {
-            deviceIds.insert(cameraDeviceId.c_str());
+            deviceIds.insert(cameraDeviceId);
         }
         mConcurrentCameraIdCombinations.push_back(std::move(deviceIds));
     }
@@ -735,7 +735,7 @@
     camera::device::StreamConfiguration streamConfiguration;
     bool earlyExit = false;
     auto bRes = SessionConfigurationUtils::convertToHALStreamCombination(configuration,
-            String8(mId.c_str()), mCameraCharacteristics, mCompositeJpegRDisabled, getMetadata,
+            mId, mCameraCharacteristics, mCompositeJpegRDisabled, getMetadata,
             mPhysicalIds, streamConfiguration, overrideForPerfClass, &earlyExit);
 
     if (!bRes.isOk()) {
@@ -789,9 +789,9 @@
             return res;
         }
         camera3::metadataGetter getMetadata =
-                [this](const String8 &id, bool overrideForPerfClass) {
+                [this](const std::string &id, bool overrideForPerfClass) {
                     CameraMetadata physicalDeviceInfo;
-                    mManager->getCameraCharacteristicsLocked(id.string(), overrideForPerfClass,
+                    mManager->getCameraCharacteristicsLocked(id, overrideForPerfClass,
                                                    &physicalDeviceInfo,
                                                    /*overrideToPortrait*/false);
                     return physicalDeviceInfo;
@@ -801,7 +801,7 @@
         bStatus =
             SessionConfigurationUtils::convertToHALStreamCombination(
                     cameraIdAndSessionConfig.mSessionConfiguration,
-                    String8(cameraId.c_str()), deviceInfo,
+                    cameraId, deviceInfo,
                     mManager->isCompositeJpegRDisabledLocked(cameraId), getMetadata,
                     physicalCameraIds, streamConfiguration,
                     overrideForPerfClass, &shouldExit);
diff --git a/services/camera/libcameraservice/common/hidl/HidlProviderInfo.cpp b/services/camera/libcameraservice/common/hidl/HidlProviderInfo.cpp
index 8ff5c3f..bf7a471 100644
--- a/services/camera/libcameraservice/common/hidl/HidlProviderInfo.cpp
+++ b/services/camera/libcameraservice/common/hidl/HidlProviderInfo.cpp
@@ -533,7 +533,7 @@
                 for (auto& combination : cameraDeviceIdCombinations) {
                     std::unordered_set<std::string> deviceIds;
                     for (auto &cameraDeviceId : combination) {
-                        deviceIds.insert(cameraDeviceId.c_str());
+                        deviceIds.insert(cameraDeviceId);
                     }
                     mConcurrentCameraIdCombinations.push_back(std::move(deviceIds));
                 }
@@ -837,7 +837,7 @@
     hardware::camera::device::V3_7::StreamConfiguration configuration_3_7;
     bool earlyExit = false;
     auto bRes = SessionConfigurationUtils::convertToHALStreamCombination(configuration,
-            String8(mId.c_str()), mCameraCharacteristics, getMetadata, mPhysicalIds,
+            mId, mCameraCharacteristics, getMetadata, mPhysicalIds,
             configuration_3_7, overrideForPerfClass, &earlyExit);
 
     if (!bRes.isOk()) {
@@ -927,9 +927,9 @@
             return res;
         }
         camera3::metadataGetter getMetadata =
-                [this](const String8 &id, bool overrideForPerfClass) {
+                [this](const std::string &id, bool overrideForPerfClass) {
                     CameraMetadata physicalDeviceInfo;
-                    mManager->getCameraCharacteristicsLocked(id.string(), overrideForPerfClass,
+                    mManager->getCameraCharacteristicsLocked(id, overrideForPerfClass,
                             &physicalDeviceInfo, /*overrideToPortrait*/false);
                     return physicalDeviceInfo;
                 };
@@ -938,7 +938,7 @@
         bStatus =
             SessionConfigurationUtils::convertToHALStreamCombination(
                     cameraIdAndSessionConfig.mSessionConfiguration,
-                    String8(cameraId.c_str()), deviceInfo, getMetadata,
+                    cameraId, deviceInfo, getMetadata,
                     physicalCameraIds, streamConfiguration,
                     overrideForPerfClass, &shouldExit);
         if (!bStatus.isOk()) {
diff --git a/services/camera/libcameraservice/device3/Camera3BufferManager.cpp b/services/camera/libcameraservice/device3/Camera3BufferManager.cpp
index 2ac38d5..c42e51a 100644
--- a/services/camera/libcameraservice/device3/Camera3BufferManager.cpp
+++ b/services/camera/libcameraservice/device3/Camera3BufferManager.cpp
@@ -18,10 +18,13 @@
 #define LOG_TAG "Camera3-BufferManager"
 #define ATRACE_TAG ATRACE_TAG_CAMERA
 
+#include <sstream>
+
 #include <gui/ISurfaceComposer.h>
 #include <private/gui/ComposerService.h>
 #include <utils/Log.h>
 #include <utils/Trace.h>
+#include <camera/StringUtils.h>
 #include "utils/CameraTraces.h"
 #include "Camera3BufferManager.h"
 
@@ -454,34 +457,36 @@
 void Camera3BufferManager::dump(int fd, [[maybe_unused]] const Vector<String16>& args) const {
     Mutex::Autolock l(mLock);
 
-    String8 lines;
-    lines.appendFormat("      Total stream sets: %zu\n", mStreamSetMap.size());
+    std::ostringstream lines;
+    lines << fmt::sprintf("      Total stream sets: %zu\n", mStreamSetMap.size());
     for (size_t i = 0; i < mStreamSetMap.size(); i++) {
-        lines.appendFormat("        Stream set %d(%d) has below streams:\n",
+        lines << fmt::sprintf("        Stream set %d(%d) has below streams:\n",
                 mStreamSetMap.keyAt(i).id, mStreamSetMap.keyAt(i).isMultiRes);
         for (size_t j = 0; j < mStreamSetMap[i].streamInfoMap.size(); j++) {
-            lines.appendFormat("          Stream %d\n", mStreamSetMap[i].streamInfoMap[j].streamId);
+            lines << fmt::sprintf("          Stream %d\n",
+                    mStreamSetMap[i].streamInfoMap[j].streamId);
         }
-        lines.appendFormat("          Stream set max allowed buffer count: %zu\n",
+        lines << fmt::sprintf("          Stream set max allowed buffer count: %zu\n",
                 mStreamSetMap[i].maxAllowedBufferCount);
-        lines.appendFormat("          Stream set buffer count water mark: %zu\n",
+        lines << fmt::sprintf("          Stream set buffer count water mark: %zu\n",
                 mStreamSetMap[i].allocatedBufferWaterMark);
-        lines.appendFormat("          Handout buffer counts:\n");
+        lines << "          Handout buffer counts:\n";
         for (size_t m = 0; m < mStreamSetMap[i].handoutBufferCountMap.size(); m++) {
             int streamId = mStreamSetMap[i].handoutBufferCountMap.keyAt(m);
             size_t bufferCount = mStreamSetMap[i].handoutBufferCountMap.valueAt(m);
-            lines.appendFormat("            stream id: %d, buffer count: %zu.\n",
+            lines << fmt::sprintf("            stream id: %d, buffer count: %zu.\n",
                     streamId, bufferCount);
         }
-        lines.appendFormat("          Attached buffer counts:\n");
+        lines << "          Attached buffer counts:\n";
         for (size_t m = 0; m < mStreamSetMap[i].attachedBufferCountMap.size(); m++) {
             int streamId = mStreamSetMap[i].attachedBufferCountMap.keyAt(m);
             size_t bufferCount = mStreamSetMap[i].attachedBufferCountMap.valueAt(m);
-            lines.appendFormat("            stream id: %d, attached buffer count: %zu.\n",
+            lines << fmt::sprintf("            stream id: %d, attached buffer count: %zu.\n",
                     streamId, bufferCount);
         }
     }
-    write(fd, lines.string(), lines.size());
+    std::string linesStr = std::move(lines.str());
+    write(fd, linesStr.c_str(), linesStr.size());
 }
 
 bool Camera3BufferManager::checkIfStreamRegisteredLocked(int streamId,
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index 61c3298..52ba782 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -26,10 +26,10 @@
 #endif
 
 // Convenience macro for transient errors
-#define CLOGE(fmt, ...) ALOGE("Camera %s: %s: " fmt, mId.string(), __FUNCTION__, \
+#define CLOGE(fmt, ...) ALOGE("Camera %s: %s: " fmt, mId.c_str(), __FUNCTION__, \
             ##__VA_ARGS__)
 
-#define CLOGW(fmt, ...) ALOGW("Camera %s: %s: " fmt, mId.string(), __FUNCTION__, \
+#define CLOGW(fmt, ...) ALOGW("Camera %s: %s: " fmt, mId.c_str(), __FUNCTION__, \
             ##__VA_ARGS__)
 
 // Convenience macros for transitioning to the error state
@@ -44,10 +44,12 @@
 
 #include <utility>
 
+#include <android-base/stringprintf.h>
 #include <utils/Log.h>
 #include <utils/Trace.h>
 #include <utils/Timers.h>
 #include <cutils/properties.h>
+#include <camera/StringUtils.h>
 
 #include <android/hardware/camera/device/3.7/ICameraInjectionSession.h>
 #include <android/hardware/camera2/ICameraDeviceUser.h>
@@ -60,9 +62,9 @@
 #include "device3/Camera3InputStream.h"
 #include "device3/Camera3OutputStream.h"
 #include "device3/Camera3SharedOutputStream.h"
-#include "mediautils/SchedulingPolicyService.h"
 #include "utils/CameraThreadState.h"
 #include "utils/CameraTraces.h"
+#include "utils/SchedulingPolicyUtils.h"
 #include "utils/SessionConfigurationUtils.h"
 #include "utils/TraceHFR.h"
 
@@ -75,7 +77,8 @@
 namespace android {
 
 Camera3Device::Camera3Device(std::shared_ptr<CameraServiceProxyWrapper>& cameraServiceProxyWrapper,
-        const String8 &id, bool overrideForPerfClass, bool overrideToPortrait, bool legacyClient):
+        const std::string &id, bool overrideForPerfClass, bool overrideToPortrait,
+        bool legacyClient):
         mCameraServiceProxyWrapper(cameraServiceProxyWrapper),
         mId(id),
         mLegacyClient(legacyClient),
@@ -107,17 +110,17 @@
         mActivePhysicalId("")
 {
     ATRACE_CALL();
-    ALOGV("%s: Created device for camera %s", __FUNCTION__, mId.string());
+    ALOGV("%s: Created device for camera %s", __FUNCTION__, mId.c_str());
 }
 
 Camera3Device::~Camera3Device()
 {
     ATRACE_CALL();
-    ALOGV("%s: Tearing down for camera id %s", __FUNCTION__, mId.string());
+    ALOGV("%s: Tearing down for camera id %s", __FUNCTION__, mId.c_str());
     disconnectImpl();
 }
 
-const String8& Camera3Device::getId() const {
+const std::string& Camera3Device::getId() const {
     return mId;
 }
 
@@ -125,7 +128,7 @@
 
     /** Start up status tracker thread */
     mStatusTracker = new StatusTracker(this);
-    status_t res = mStatusTracker->run(String8::format("C3Dev-%s-Status", mId.string()).string());
+    status_t res = mStatusTracker->run((std::string("C3Dev-") + mId + "-Status").c_str());
     if (res != OK) {
         SET_ERR_L("Unable to start status tracking thread: %s (%d)",
                 strerror(-res), res);
@@ -188,7 +191,7 @@
             this, mStatusTracker, mInterface, sessionParamKeys,
             mUseHalBufManager, mSupportCameraMute, mOverrideToPortrait,
             mSupportZoomOverride);
-    res = mRequestThread->run(String8::format("C3Dev-%s-ReqQueue", mId.string()).string());
+    res = mRequestThread->run((std::string("C3Dev-") + mId + "-ReqQueue").c_str());
     if (res != OK) {
         SET_ERR_L("Unable to start request queue thread: %s (%d)",
                 strerror(-res), res);
@@ -225,23 +228,23 @@
 
     bool usePrecorrectArray = DistortionMapper::isDistortionSupported(mDeviceInfo);
     if (usePrecorrectArray) {
-        res = mDistortionMappers[mId.c_str()].setupStaticInfo(mDeviceInfo);
+        res = mDistortionMappers[mId].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,
+    mZoomRatioMappers[mId] = ZoomRatioMapper(&mDeviceInfo,
             mSupportNativeZoomRatio, usePrecorrectArray);
 
     if (SessionConfigurationUtils::supportsUltraHighResolutionCapture(mDeviceInfo)) {
-        mUHRCropAndMeteringRegionMappers[mId.c_str()] =
+        mUHRCropAndMeteringRegionMappers[mId] =
                 UHRCropAndMeteringRegionMapper(mDeviceInfo, usePrecorrectArray);
     }
 
     if (RotateAndCropMapper::isNeeded(&mDeviceInfo)) {
-        mRotateAndCropMappers.emplace(mId.c_str(), &mDeviceInfo);
+        mRotateAndCropMappers.emplace(mId, &mDeviceInfo);
     }
 
     // Hidl/AidlCamera3DeviceInjectionMethods
@@ -428,7 +431,7 @@
                     /*isUltraHighResolution*/true);
     if (maxDefaultJpegResolution.width == 0) {
         ALOGE("%s: Camera %s: Can't find valid available jpeg sizes in static metadata!",
-                __FUNCTION__, mId.string());
+                __FUNCTION__, mId.c_str());
         return BAD_VALUE;
     }
     bool useMaxSensorPixelModeThreshold = false;
@@ -443,7 +446,7 @@
     camera_metadata_ro_entry jpegBufMaxSize = info.find(ANDROID_JPEG_MAX_SIZE);
     if (jpegBufMaxSize.count == 0) {
         ALOGE("%s: Camera %s: Can't find maximum JPEG size in static metadata!", __FUNCTION__,
-                mId.string());
+                mId.c_str());
         return BAD_VALUE;
     }
     maxJpegBufferSize = jpegBufMaxSize.data.i32[0];
@@ -475,7 +478,7 @@
     camera_metadata_ro_entry maxPointCount = info.find(ANDROID_DEPTH_MAX_DEPTH_SAMPLES);
     if (maxPointCount.count == 0) {
         ALOGE("%s: Camera %s: Can't find maximum depth point cloud size in static metadata!",
-                __FUNCTION__, mId.string());
+                __FUNCTION__, mId.c_str());
         return BAD_VALUE;
     }
     ssize_t maxBytesForPointCloud = sizeof(android_depth_points) +
@@ -497,7 +500,7 @@
     size_t count = rawOpaqueSizes.count;
     if (count == 0 || (count % PER_CONFIGURATION_SIZE)) {
         ALOGE("%s: Camera %s: bad opaque RAW size static metadata length(%zu)!",
-                __FUNCTION__, mId.string(), count);
+                __FUNCTION__, mId.c_str(), count);
         return BAD_VALUE;
     }
 
@@ -509,7 +512,7 @@
     }
 
     ALOGE("%s: Camera %s: cannot find size for %dx%d opaque RAW image!",
-            __FUNCTION__, mId.string(), width, height);
+            __FUNCTION__, mId.c_str(), width, height);
     return BAD_VALUE;
 }
 
@@ -523,10 +526,10 @@
 
     ALOGW_IF(!gotInterfaceLock,
             "Camera %s: %s: Unable to lock interface lock, proceeding anyway",
-            mId.string(), __FUNCTION__);
+            mId.c_str(), __FUNCTION__);
     ALOGW_IF(!gotLock,
             "Camera %s: %s: Unable to lock main lock, proceeding anyway",
-            mId.string(), __FUNCTION__);
+            mId.c_str(), __FUNCTION__);
 
     bool dumpTemplates = false;
 
@@ -536,9 +539,9 @@
         if (args[i] == templatesOption) {
             dumpTemplates = true;
         }
-        if (args[i] == TagMonitor::kMonitorOption) {
+        if (args[i] == toString16(TagMonitor::kMonitorOption)) {
             if (i + 1 < n) {
-                String8 monitorTags = String8(args[i + 1]);
+                std::string monitorTags = toStdString(args[i + 1]);
                 if (monitorTags == "off") {
                     mTagMonitor.disableMonitoring();
                 } else {
@@ -550,7 +553,7 @@
         }
     }
 
-    String8 lines;
+    std::string lines;
 
     const char *status =
             mStatus == STATUS_ERROR         ? "ERROR" :
@@ -560,42 +563,42 @@
             mStatus == STATUS_ACTIVE        ? "ACTIVE" :
             "Unknown";
 
-    lines.appendFormat("    Device status: %s\n", status);
+    lines += fmt::sprintf("    Device status: %s\n", status);
     if (mStatus == STATUS_ERROR) {
-        lines.appendFormat("    Error cause: %s\n", mErrorCause.string());
+        lines += fmt::sprintf("    Error cause: %s\n", mErrorCause.c_str());
     }
-    lines.appendFormat("    Stream configuration:\n");
+    lines += "    Stream configuration:\n";
     const char *mode =
             mOperatingMode == CAMERA_STREAM_CONFIGURATION_NORMAL_MODE ? "NORMAL" :
             mOperatingMode == CAMERA_STREAM_CONFIGURATION_CONSTRAINED_HIGH_SPEED_MODE ?
                     "CONSTRAINED_HIGH_SPEED" : "CUSTOM";
-    lines.appendFormat("    Operation mode: %s (%d) \n", mode, mOperatingMode);
+    lines += fmt::sprintf("    Operation mode: %s (%d) \n", mode, mOperatingMode);
 
     if (mInputStream != NULL) {
-        write(fd, lines.string(), lines.size());
+        write(fd, lines.c_str(), lines.size());
         mInputStream->dump(fd, args);
     } else {
-        lines.appendFormat("      No input stream.\n");
-        write(fd, lines.string(), lines.size());
+        lines += "      No input stream.\n";
+        write(fd, lines.c_str(), lines.size());
     }
     for (size_t i = 0; i < mOutputStreams.size(); i++) {
         mOutputStreams[i]->dump(fd,args);
     }
 
     if (mBufferManager != NULL) {
-        lines = String8("    Camera3 Buffer Manager:\n");
-        write(fd, lines.string(), lines.size());
+        lines = "    Camera3 Buffer Manager:\n";
+        write(fd, lines.c_str(), lines.size());
         mBufferManager->dump(fd, args);
     }
 
-    lines = String8("    In-flight requests:\n");
+    lines = "    In-flight requests:\n";
     if (mInFlightLock.try_lock()) {
         if (mInFlightMap.size() == 0) {
-            lines.append("      None\n");
+            lines += "      None\n";
         } else {
             for (size_t i = 0; i < mInFlightMap.size(); i++) {
                 InFlightRequest r = mInFlightMap.valueAt(i);
-                lines.appendFormat("      Frame %d |  Timestamp: %" PRId64 ", metadata"
+                lines += fmt::sprintf("      Frame %d |  Timestamp: %" PRId64 ", metadata"
                         " arrived: %s, buffers left: %d\n", mInFlightMap.keyAt(i),
                         r.shutterTimestamp, r.haveResultMetadata ? "true" : "false",
                         r.numBuffersLeft);
@@ -603,9 +606,9 @@
         }
         mInFlightLock.unlock();
     } else {
-        lines.append("      Failed to acquire In-flight lock!\n");
+        lines += "      Failed to acquire In-flight lock!\n";
     }
-    write(fd, lines.string(), lines.size());
+    write(fd, lines.c_str(), lines.size());
 
     if (mRequestThread != NULL) {
         mRequestThread->dumpCaptureRequestLatency(fd,
@@ -613,8 +616,8 @@
     }
 
     {
-        lines = String8("    Last request sent:\n");
-        write(fd, lines.string(), lines.size());
+        lines = "    Last request sent:\n";
+        write(fd, lines.c_str(), lines.size());
 
         CameraMetadata lastRequest = getLatestRequestLocked();
         lastRequest.dump(fd, /*verbosity*/2, /*indentation*/6);
@@ -634,12 +637,12 @@
             camera_metadata_t *templateRequest = nullptr;
             mInterface->constructDefaultRequestSettings(
                     (camera_request_template_t) i, &templateRequest);
-            lines = String8::format("    HAL Request %s:\n", templateNames[i-1]);
+            lines = fmt::sprintf("    HAL Request %s:\n", templateNames[i-1]);
             if (templateRequest == nullptr) {
-                lines.append("       Not supported\n");
-                write(fd, lines.string(), lines.size());
+                lines += "       Not supported\n";
+                write(fd, lines.c_str(), lines.size());
             } else {
-                write(fd, lines.string(), lines.size());
+                write(fd, lines.c_str(), lines.size());
                 dump_indented_camera_metadata(templateRequest,
                         fd, /*verbosity*/2, /*indentation*/8);
             }
@@ -650,8 +653,8 @@
     mTagMonitor.dumpMonitoredMetadata(fd);
 
     if (mInterface->valid()) {
-        lines = String8("     HAL device dump:\n");
-        write(fd, lines.string(), lines.size());
+        lines = "     HAL device dump:\n";
+        write(fd, lines.c_str(), lines.size());
         mInterface->dump(fd);
     }
 
@@ -661,7 +664,7 @@
     return OK;
 }
 
-status_t Camera3Device::startWatchingTags(const String8 &tags) {
+status_t Camera3Device::startWatchingTags(const std::string &tags) {
     mTagMonitor.parseTagsToMonitor(tags);
     return OK;
 }
@@ -676,7 +679,7 @@
     return OK;
 }
 
-const CameraMetadata& Camera3Device::infoPhysical(const String8& physicalId) const {
+const CameraMetadata& Camera3Device::infoPhysical(const std::string& physicalId) const {
     ALOGVV("%s: E", __FUNCTION__);
     if (CC_UNLIKELY(mStatus == STATUS_UNINITIALIZED ||
                     mStatus == STATUS_ERROR)) {
@@ -684,12 +687,11 @@
                 mStatus == STATUS_ERROR ?
                 "when in error state" : "before init");
     }
-    if (physicalId.isEmpty()) {
+    if (physicalId.empty()) {
         return mDeviceInfo;
     } else {
-        std::string id(physicalId.c_str());
-        if (mPhysicalDeviceInfoMap.find(id) != mPhysicalDeviceInfoMap.end()) {
-            return mPhysicalDeviceInfoMap.at(id);
+        if (mPhysicalDeviceInfoMap.find(physicalId) != mPhysicalDeviceInfoMap.end()) {
+            return mPhysicalDeviceInfoMap.at(physicalId);
         } else {
             ALOGE("%s: Invalid physical camera id %s", __FUNCTION__, physicalId.c_str());
             return mDeviceInfo;
@@ -698,8 +700,7 @@
 }
 
 const CameraMetadata& Camera3Device::info() const {
-    String8 emptyId;
-    return infoPhysical(emptyId);
+    return infoPhysical(/*physicalId*/ std::string());
 }
 
 status_t Camera3Device::checkStatusOkToCaptureLocked() {
@@ -793,7 +794,7 @@
         std::list<const SurfaceMap>& surfaceMaps,
         const CameraMetadata& request) {
     PhysicalCameraSettingsList requestList;
-    requestList.push_back({std::string(getId().string()), request});
+    requestList.push_back({getId(), request});
     requestsList.push_back(requestList);
 
     SurfaceMap surfaceMap;
@@ -845,7 +846,7 @@
             SET_ERR_L("Can't transition to active in %f seconds!",
                     kActiveTimeout/1e9);
         }
-        ALOGV("Camera %s: Capture request %" PRId32 " enqueued", mId.string(),
+        ALOGV("Camera %s: Capture request %" PRId32 " enqueued", mId.c_str(),
               (*(requestList.begin()))->mResultExtras.requestId);
     } else {
         CLOGE("Cannot queue request. Impossible.");
@@ -928,7 +929,7 @@
             SET_ERR_L("Unexpected status: %d", mStatus);
             return INVALID_OPERATION;
     }
-    ALOGV("Camera %s: Clearing repeating request", mId.string());
+    ALOGV("Camera %s: Clearing repeating request", mId.c_str());
 
     return mRequestThread->clearRepeatingRequests(lastFrameNumber);
 }
@@ -947,7 +948,7 @@
     nsecs_t maxExpectedDuration = getExpectedInFlightDuration();
     Mutex::Autolock l(mLock);
     ALOGV("Camera %s: Creating new input stream %d: %d x %d, format %d",
-            mId.string(), mNextStreamId, width, height, format);
+            mId.c_str(), mNextStreamId, width, height, format);
 
     status_t res;
     bool wasActive = false;
@@ -1006,14 +1007,14 @@
         internalResumeLocked();
     }
 
-    ALOGV("Camera %s: Created input stream", mId.string());
+    ALOGV("Camera %s: Created input stream", mId.c_str());
     return OK;
 }
 
 status_t Camera3Device::createStream(sp<Surface> consumer,
             uint32_t width, uint32_t height, int format,
             android_dataspace dataSpace, camera_stream_rotation_t rotation, int *id,
-            const String8& physicalCameraId,
+            const std::string& physicalCameraId,
             const std::unordered_set<int32_t> &sensorPixelModesUsed,
             std::vector<int> *surfaceIds, int streamSetId, bool isShared, bool isMultiResolution,
             uint64_t consumerUsage, int64_t dynamicRangeProfile, int64_t streamUseCase,
@@ -1049,7 +1050,8 @@
 status_t Camera3Device::createStream(const std::vector<sp<Surface>>& consumers,
         bool hasDeferredConsumer, uint32_t width, uint32_t height, int format,
         android_dataspace dataSpace, camera_stream_rotation_t rotation, int *id,
-        const String8& physicalCameraId, const std::unordered_set<int32_t> &sensorPixelModesUsed,
+        const std::string& physicalCameraId,
+        const std::unordered_set<int32_t> &sensorPixelModesUsed,
         std::vector<int> *surfaceIds, int streamSetId, bool isShared, bool isMultiResolution,
         uint64_t consumerUsage, int64_t dynamicRangeProfile, int64_t streamUseCase,
         int timestampBase, int mirrorMode, int32_t colorSpace, bool useReadoutTimestamp) {
@@ -1062,8 +1064,8 @@
             " consumer usage %" PRIu64 ", isShared %d, physicalCameraId %s, isMultiResolution %d"
             " dynamicRangeProfile 0x%" PRIx64 ", streamUseCase %" PRId64 ", timestampBase %d,"
             " mirrorMode %d, colorSpace %d, useReadoutTimestamp %d",
-            mId.string(), mNextStreamId, width, height, format, dataSpace, rotation,
-            consumerUsage, isShared, physicalCameraId.string(), isMultiResolution,
+            mId.c_str(), mNextStreamId, width, height, format, dataSpace, rotation,
+            consumerUsage, isShared, physicalCameraId.c_str(), isMultiResolution,
             dynamicRangeProfile, streamUseCase, timestampBase, mirrorMode, colorSpace,
             useReadoutTimestamp);
 
@@ -1214,7 +1216,7 @@
         }
         internalResumeLocked();
     }
-    ALOGV("Camera %s: Created new stream", mId.string());
+    ALOGV("Camera %s: Created new stream", mId.c_str());
     return OK;
 }
 
@@ -1299,18 +1301,18 @@
     Mutex::Autolock l(mLock);
     status_t res;
 
-    ALOGV("%s: Camera %s: Deleting stream %d", __FUNCTION__, mId.string(), id);
+    ALOGV("%s: Camera %s: Deleting stream %d", __FUNCTION__, mId.c_str(), id);
 
     // CameraDevice semantics require device to already be idle before
     // deleteStream is called, unlike for createStream.
     if (mStatus == STATUS_ACTIVE) {
-        ALOGW("%s: Camera %s: Device not idle", __FUNCTION__, mId.string());
+        ALOGW("%s: Camera %s: Device not idle", __FUNCTION__, mId.c_str());
         return -EBUSY;
     }
 
     if (mStatus == STATUS_ERROR) {
         ALOGW("%s: Camera %s: deleteStream not allowed in ERROR state",
-                __FUNCTION__, mId.string());
+                __FUNCTION__, mId.c_str());
         return -EBUSY;
     }
 
@@ -1502,7 +1504,7 @@
         mRequestTemplateCache[templateId].acquire(rawRequest);
 
         // Override the template request with zoomRatioMapper
-        res = mZoomRatioMappers[mId.c_str()].initZoomRatioInTemplate(
+        res = mZoomRatioMappers[mId].initZoomRatioInTemplate(
                 &mRequestTemplateCache[templateId]);
         if (res != OK) {
             CLOGE("Failed to update zoom ratio for template %d: %s (%d)",
@@ -1555,7 +1557,7 @@
             SET_ERR_L("Unexpected status: %d",mStatus);
             return INVALID_OPERATION;
     }
-    ALOGV("%s: Camera %s: Waiting until idle (%" PRIi64 "ns)", __FUNCTION__, mId.string(),
+    ALOGV("%s: Camera %s: Waiting until idle (%" PRIi64 "ns)", __FUNCTION__, mId.c_str(),
             maxExpectedDuration);
     status_t res = waitUntilStateThenRelock(/*active*/ false, maxExpectedDuration,
                            /*requestThreadInvocation*/ false);
@@ -1583,7 +1585,7 @@
         return NO_INIT;
     }
 
-    ALOGV("%s: Camera %s: Internal wait until idle (% " PRIi64 " ns)", __FUNCTION__, mId.string(),
+    ALOGV("%s: Camera %s: Internal wait until idle (% " PRIi64 " ns)", __FUNCTION__, mId.c_str(),
           maxExpectedDuration);
     status_t res = waitUntilStateThenRelock(/*active*/ false, maxExpectedDuration,
                            requestThreadInvocation);
@@ -1602,7 +1604,7 @@
 
     mRequestThread->setPaused(false);
 
-    ALOGV("%s: Camera %s: Internal wait until active (% " PRIi64 " ns)", __FUNCTION__, mId.string(),
+    ALOGV("%s: Camera %s: Internal wait until active (% " PRIi64 " ns)", __FUNCTION__, mId.c_str(),
             kActiveTimeout);
     // internalResumeLocked is always called from a binder thread.
     res = waitUntilStateThenRelock(/*active*/ true, kActiveTimeout,
@@ -1819,7 +1821,7 @@
 
 status_t Camera3Device::flush(int64_t *frameNumber) {
     ATRACE_CALL();
-    ALOGV("%s: Camera %s: Flushing all requests", __FUNCTION__, mId.string());
+    ALOGV("%s: Camera %s: Flushing all requests", __FUNCTION__, mId.c_str());
     Mutex::Autolock il(mInterfaceLock);
 
     {
@@ -1851,7 +1853,7 @@
 
 status_t Camera3Device::prepare(int maxCount, int streamId) {
     ATRACE_CALL();
-    ALOGV("%s: Camera %s: Preparing stream %d", __FUNCTION__, mId.string(), streamId);
+    ALOGV("%s: Camera %s: Preparing stream %d", __FUNCTION__, mId.c_str(), streamId);
     Mutex::Autolock il(mInterfaceLock);
     Mutex::Autolock l(mLock);
 
@@ -1876,7 +1878,7 @@
 
 status_t Camera3Device::tearDown(int streamId) {
     ATRACE_CALL();
-    ALOGV("%s: Camera %s: Tearing down stream %d", __FUNCTION__, mId.string(), streamId);
+    ALOGV("%s: Camera %s: Tearing down stream %d", __FUNCTION__, mId.c_str(), streamId);
     Mutex::Autolock il(mInterfaceLock);
     Mutex::Autolock l(mLock);
 
@@ -1897,7 +1899,8 @@
 status_t Camera3Device::addBufferListenerForStream(int streamId,
         wp<Camera3StreamBufferListener> listener) {
     ATRACE_CALL();
-    ALOGV("%s: Camera %s: Adding buffer listener for stream %d", __FUNCTION__, mId.string(), streamId);
+    ALOGV("%s: Camera %s: Adding buffer listener for stream %d", __FUNCTION__, mId.c_str(),
+            streamId);
     Mutex::Autolock il(mInterfaceLock);
     Mutex::Autolock l(mLock);
 
@@ -1945,7 +1948,7 @@
         if (mStatus != STATUS_ACTIVE && mStatus != STATUS_CONFIGURED) {
             return;
         }
-        ALOGV("%s: Camera %s: Now %s, pauseState: %s", __FUNCTION__, mId.string(),
+        ALOGV("%s: Camera %s: Now %s, pauseState: %s", __FUNCTION__, mId.c_str(),
                 idle ? "idle" : "active", mPauseStateNotify ? "true" : "false");
         internalUpdateStatusLocked(idle ? STATUS_CONFIGURED : STATUS_ACTIVE);
 
@@ -2026,7 +2029,7 @@
         const std::vector<sp<Surface>>& consumers, std::vector<int> *surfaceIds) {
     ATRACE_CALL();
     ALOGV("%s: Camera %s: set consumer surface for stream %d",
-            __FUNCTION__, mId.string(), streamId);
+            __FUNCTION__, mId.c_str(), streamId);
 
     if (surfaceIds == nullptr) {
         return BAD_VALUE;
@@ -2306,7 +2309,7 @@
 
     res = mPreparerThread->resume();
     if (res != OK) {
-        ALOGE("%s: Camera %s: Preparer thread failed to resume!", __FUNCTION__, mId.string());
+        ALOGE("%s: Camera %s: Preparer thread failed to resume!", __FUNCTION__, mId.c_str());
     }
 }
 
@@ -2466,7 +2469,7 @@
     overrideStreamUseCaseLocked();
 
     // Start configuring the streams
-    ALOGV("%s: Camera %s: Starting stream configuration", __FUNCTION__, mId.string());
+    ALOGV("%s: Camera %s: Starting stream configuration", __FUNCTION__, mId.c_str());
 
     mPreparerThread->pause();
 
@@ -2522,7 +2525,7 @@
                      static_cast<android_dataspace_t>(
                          aidl::android::hardware::graphics::common::Dataspace::JPEG_R))) {
                 bufferSizes[k] = static_cast<uint32_t>(
-                        getJpegBufferSize(infoPhysical(String8(outputStream->physical_camera_id)),
+                        getJpegBufferSize(infoPhysical(outputStream->physical_camera_id),
                                 outputStream->width, outputStream->height));
             } else if (outputStream->data_space ==
                     static_cast<android_dataspace>(HAL_DATASPACE_JPEG_APP_SEGMENTS)) {
@@ -2535,7 +2538,7 @@
 
         if (mOutputStreams[i]->isMultiResolution()) {
             int32_t streamGroupId = mOutputStreams[i]->getHalStreamGroupId();
-            const String8& physicalCameraId = mOutputStreams[i]->getPhysicalCameraId();
+            const std::string &physicalCameraId = mOutputStreams[i]->getPhysicalCameraId();
             mGroupIdPhysicalCameraMap[streamGroupId].insert(physicalCameraId);
         }
 
@@ -2625,8 +2628,8 @@
     if (disableFifo != 1) {
         // Boost priority of request thread to SCHED_FIFO.
         pid_t requestThreadTid = mRequestThread->getTid();
-        res = requestPriority(getpid(), requestThreadTid,
-                kRequestThreadPriority, /*isForApp*/ false, /*asynchronous*/ false);
+        res = SchedulingPolicyUtils::requestPriorityDirect(getpid(), requestThreadTid,
+                kRequestThreadPriority);
         if (res != OK) {
             ALOGW("Can't set realtime priority for request processing thread: %s (%d)",
                     strerror(-res), res);
@@ -2650,14 +2653,14 @@
     internalUpdateStatusLocked((mFakeStreamId == NO_STREAM) ?
             STATUS_CONFIGURED : STATUS_UNCONFIGURED);
 
-    ALOGV("%s: Camera %s: Stream configuration complete", __FUNCTION__, mId.string());
+    ALOGV("%s: Camera %s: Stream configuration complete", __FUNCTION__, mId.c_str());
 
     // tear down the deleted streams after configure streams.
     mDeletedStreams.clear();
 
     auto rc = mPreparerThread->resume();
     if (rc != OK) {
-        SET_ERR_L("%s: Camera %s: Preparer thread failed to resume!", __FUNCTION__, mId.string());
+        SET_ERR_L("%s: Camera %s: Preparer thread failed to resume!", __FUNCTION__, mId.c_str());
         return rc;
     }
 
@@ -2671,7 +2674,7 @@
     // configure the injection streams.
     if (mInjectionMethods->isInjecting()) {
         ALOGD("%s: Injection camera %s: Start to configure streams.",
-              __FUNCTION__, mInjectionMethods->getInjectedCamId().string());
+              __FUNCTION__, mInjectionMethods->getInjectedCamId().c_str());
         res = mInjectionMethods->injectCamera(config, bufferSizes);
         if (res != OK) {
             ALOGE("Can't finish inject camera process!");
@@ -2700,11 +2703,11 @@
         // Should never be adding a second fake stream when one is already
         // active
         SET_ERR_L("%s: Camera %s: A fake stream already exists!",
-                __FUNCTION__, mId.string());
+                __FUNCTION__, mId.c_str());
         return INVALID_OPERATION;
     }
 
-    ALOGV("%s: Camera %s: Adding a fake stream", __FUNCTION__, mId.string());
+    ALOGV("%s: Camera %s: Adding a fake stream", __FUNCTION__, mId.c_str());
 
     sp<Camera3OutputStreamInterface> fakeStream =
             new Camera3FakeStream(mNextStreamId);
@@ -2728,7 +2731,7 @@
     if (mFakeStreamId == NO_STREAM) return OK;
     if (mOutputStreams.size() == 1) return OK;
 
-    ALOGV("%s: Camera %s: Removing the fake stream", __FUNCTION__, mId.string());
+    ALOGV("%s: Camera %s: Removing the fake stream", __FUNCTION__, mId.c_str());
 
     // Ok, have a fake stream and there's at least one other output stream,
     // so remove the fake
@@ -2780,8 +2783,9 @@
 
 void Camera3Device::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());
+    std::string errorCause;
+    base::StringAppendV(&errorCause, fmt, args);
+    ALOGE("Camera %s: %s", mId.c_str(), errorCause.c_str());
 
     // But only do error state transition steps for the first error
     if (mStatus == STATUS_ERROR || mStatus == STATUS_UNINITIALIZED) return;
@@ -2813,7 +2817,7 @@
 status_t Camera3Device::registerInFlight(uint32_t frameNumber,
         int32_t numBuffers, CaptureResultExtras resultExtras, bool hasInput,
         bool hasAppCallback, nsecs_t minExpectedDuration, nsecs_t maxExpectedDuration,
-        bool isFixedFps, const std::set<std::set<String8>>& physicalCameraIds,
+        bool isFixedFps, const std::set<std::set<std::string>>& physicalCameraIds,
         bool isStillCapture, bool isZslCapture, bool rotateAndCropAuto, bool autoframingAuto,
         const std::set<std::string>& cameraIdsWithZoom,
         const SurfaceMap& outputSurfaces, nsecs_t requestTimeNs) {
@@ -3064,7 +3068,7 @@
 
 void Camera3Device::RequestThread::configurationComplete(bool isConstrainedHighSpeed,
         const CameraMetadata& sessionParams,
-        const std::map<int32_t, std::set<String8>>& groupIdPhysicalCameraMap) {
+        const std::map<int32_t, std::set<std::string>>& groupIdPhysicalCameraMap) {
     ATRACE_CALL();
     Mutex::Autolock l(mRequestLock);
     mReconfigured = true;
@@ -3117,8 +3121,8 @@
     return OK;
 }
 
-const String8& Camera3Device::RequestThread::getId(const wp<Camera3Device> &device) {
-    static String8 deadId("<DeadDevice>");
+const std::string& Camera3Device::RequestThread::getId(const wp<Camera3Device> &device) {
+    static std::string deadId("<DeadDevice>");
     sp<Camera3Device> d = device.promote();
     if (d != nullptr) return d->mId;
     return deadId;
@@ -3928,7 +3932,7 @@
         outputBuffers->insertAt(camera_stream_buffer_t(), 0,
                 captureRequest->mOutputStreams.size());
         halRequest->output_buffers = outputBuffers->array();
-        std::set<std::set<String8>> requestedPhysicalCameras;
+        std::set<std::set<std::string>> requestedPhysicalCameras;
 
         sp<Camera3Device> parent = mParent.promote();
         if (parent == NULL) {
@@ -4009,11 +4013,11 @@
             {
                 sp<Camera3Device> parent = mParent.promote();
                 if (parent != nullptr) {
-                    const String8& streamCameraId = outputStream->getPhysicalCameraId();
+                    const std::string& streamCameraId = outputStream->getPhysicalCameraId();
                     for (const auto& settings : captureRequest->mSettingsList) {
-                        if ((streamCameraId.isEmpty() &&
-                                parent->getId() == settings.cameraId.c_str()) ||
-                                streamCameraId == settings.cameraId.c_str()) {
+                        if ((streamCameraId.empty() &&
+                                parent->getId() == settings.cameraId) ||
+                                streamCameraId == settings.cameraId) {
                             outputStream->fireBufferRequestForFrameNumber(
                                     captureRequest->mResultExtras.frameNumber,
                                     settings.metadata);
@@ -4022,12 +4026,12 @@
                 }
             }
 
-            String8 physicalCameraId = outputStream->getPhysicalCameraId();
+            const std::string &physicalCameraId = outputStream->getPhysicalCameraId();
             int32_t streamGroupId = outputStream->getHalStreamGroupId();
             if (streamGroupId != -1 && mGroupIdPhysicalCameraMap.count(streamGroupId) == 1) {
                 requestedPhysicalCameras.insert(mGroupIdPhysicalCameraMap[streamGroupId]);
-            } else if (!physicalCameraId.isEmpty()) {
-                requestedPhysicalCameras.insert(std::set<String8>({physicalCameraId}));
+            } else if (!physicalCameraId.empty()) {
+                requestedPhysicalCameras.insert(std::set<std::string>({physicalCameraId}));
             }
             halRequest->num_output_buffers++;
         }
@@ -5456,9 +5460,9 @@
     return mRequestThread->setZoomOverride(zoomOverride);
 }
 
-status_t Camera3Device::injectCamera(const String8& injectedCamId,
+status_t Camera3Device::injectCamera(const std::string& injectedCamId,
                                      sp<CameraProviderManager> manager) {
-    ALOGI("%s Injection camera: injectedCamId = %s", __FUNCTION__, injectedCamId.string());
+    ALOGI("%s Injection camera: injectedCamId = %s", __FUNCTION__, injectedCamId.c_str());
     ATRACE_CALL();
     Mutex::Autolock il(mInterfaceLock);
     // When the camera device is active, injectCamera() and stopInjection() will call
diff --git a/services/camera/libcameraservice/device3/Camera3Device.h b/services/camera/libcameraservice/device3/Camera3Device.h
index b1dd135..0c1bbcb 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.h
+++ b/services/camera/libcameraservice/device3/Camera3Device.h
@@ -85,7 +85,7 @@
   public:
 
     explicit Camera3Device(std::shared_ptr<CameraServiceProxyWrapper>& cameraServiceProxyWrapper,
-            const String8& id, bool overrideForPerfClass, bool overrideToPortrait,
+            const std::string& id, bool overrideForPerfClass, bool overrideToPortrait,
             bool legacyClient = false);
 
     virtual ~Camera3Device();
@@ -101,7 +101,7 @@
      * CameraDeviceBase interface
      */
 
-    const String8& getId() const override;
+    const std::string& getId() const override;
 
     metadata_vendor_id_t getVendorTagId() const override { return mVendorTagId; }
 
@@ -110,15 +110,15 @@
 
     // Transitions to idle state on success.
     virtual status_t initialize(sp<CameraProviderManager> /*manager*/,
-            const String8& /*monitorTags*/) = 0;
+            const std::string& /*monitorTags*/) = 0;
 
     status_t disconnect() override;
     status_t dump(int fd, const Vector<String16> &args) override;
-    status_t startWatchingTags(const String8 &tags) override;
+    status_t startWatchingTags(const std::string &tags) override;
     status_t stopWatchingTags() override;
     status_t dumpWatchedEventsToVector(std::vector<std::string> &out) override;
     const CameraMetadata& info() const override;
-    const CameraMetadata& infoPhysical(const String8& physicalId) const override;
+    const CameraMetadata& infoPhysical(const std::string& physicalId) const override;
     bool isCompositeJpegRDisabled() const override { return mIsCompositeJpegRDisabled; };
 
     // Capture and setStreamingRequest will configure streams if currently in
@@ -144,7 +144,7 @@
     status_t createStream(sp<Surface> consumer,
             uint32_t width, uint32_t height, int format,
             android_dataspace dataSpace, camera_stream_rotation_t rotation, int *id,
-            const String8& physicalCameraId,
+            const std::string& physicalCameraId,
             const std::unordered_set<int32_t> &sensorPixelModesUsed,
             std::vector<int> *surfaceIds = nullptr,
             int streamSetId = camera3::CAMERA3_STREAM_SET_ID_INVALID,
@@ -162,7 +162,7 @@
     status_t createStream(const std::vector<sp<Surface>>& consumers,
             bool hasDeferredConsumer, uint32_t width, uint32_t height, int format,
             android_dataspace dataSpace, camera_stream_rotation_t rotation, int *id,
-            const String8& physicalCameraId,
+            const std::string& physicalCameraId,
             const std::unordered_set<int32_t> &sensorPixelModesUsed,
             std::vector<int> *surfaceIds = nullptr,
             int streamSetId = camera3::CAMERA3_STREAM_SET_ID_INVALID,
@@ -330,7 +330,7 @@
      * The injection camera session to replace the internal camera
      * session.
      */
-    status_t injectCamera(const String8& injectedCamId,
+    status_t injectCamera(const std::string& injectedCamId,
                           sp<CameraProviderManager> manager);
 
     /**
@@ -376,7 +376,7 @@
     Mutex                      mLock;
 
     // Camera device ID
-    const String8              mId;
+    const std::string          mId;
 
     // Legacy camera client flag
     bool                       mLegacyClient;
@@ -586,14 +586,14 @@
     Condition                  mStatusChanged;
 
     // Tracking cause of fatal errors when in STATUS_ERROR
-    String8                    mErrorCause;
+    std::string                mErrorCause;
 
     camera3::StreamSet         mOutputStreams;
     sp<camera3::Camera3Stream> mInputStream;
     bool                       mIsInputStreamMultiResolution;
     SessionStatsBuilder        mSessionStatsBuilder;
     // Map from stream group ID to physical cameras backing the stream group
-    std::map<int32_t, std::set<String8>> mGroupIdPhysicalCameraMap;
+    std::map<int32_t, std::set<std::string>> mGroupIdPhysicalCameraMap;
 
     int                        mNextStreamId;
     bool                       mNeedConfig;
@@ -709,7 +709,7 @@
      */
     virtual CameraMetadata getLatestRequestLocked();
 
-    virtual status_t injectionCameraInitialize(const String8 &injectCamId,
+    virtual status_t injectionCameraInitialize(const std::string &injectCamId,
             sp<CameraProviderManager> manager) = 0;
 
     /**
@@ -891,7 +891,7 @@
          */
         void     configurationComplete(bool isConstrainedHighSpeed,
                 const CameraMetadata& sessionParams,
-                const std::map<int32_t, std::set<String8>>& groupIdPhysicalCameraMap);
+                const std::map<int32_t, std::set<std::string>>& groupIdPhysicalCameraMap);
 
         /**
          * Set or clear the list of repeating requests. Does not block
@@ -996,7 +996,7 @@
 
         virtual bool threadLoop();
 
-        static const String8& getId(const wp<Camera3Device> &device);
+        static const std::string& getId(const wp<Camera3Device> &device);
 
         status_t           queueTriggerLocked(RequestTrigger trigger);
         // Mix-in queued triggers into this request
@@ -1102,7 +1102,7 @@
 
         wp<NotificationListener> mListener;
 
-        const String8      mId;       // The camera ID
+        const std::string  mId;       // The camera ID
         int                mStatusId; // The RequestThread's component ID for
                                       // status tracking
 
@@ -1173,7 +1173,7 @@
         Vector<int32_t>    mSessionParamKeys;
         CameraMetadata     mLatestSessionParams;
 
-        std::map<int32_t, std::set<String8>> mGroupIdPhysicalCameraMap;
+        std::map<int32_t, std::set<std::string>> mGroupIdPhysicalCameraMap;
 
         const bool         mUseHalBufManager;
         const bool         mSupportCameraMute;
@@ -1209,7 +1209,7 @@
     status_t registerInFlight(uint32_t frameNumber,
             int32_t numBuffers, CaptureResultExtras resultExtras, bool hasInput,
             bool callback, nsecs_t minExpectedDuration, nsecs_t maxExpectedDuration,
-            bool isFixedFps, const std::set<std::set<String8>>& physicalCameraIds,
+            bool isFixedFps, const std::set<std::set<std::string>>& physicalCameraIds,
             bool isStillCapture, bool isZslCapture, bool rotateAndCropAuto, bool autoframingAuto,
             const std::set<std::string>& cameraIdsWithZoom, const SurfaceMap& outputSurfaces,
             nsecs_t requestTimeNs);
@@ -1503,7 +1503,7 @@
 
         bool isStreamConfigCompleteButNotInjected();
 
-        const String8& getInjectedCamId() const;
+        const std::string& getInjectedCamId() const;
 
         void getInjectionConfig(/*out*/ camera3::camera_stream_configuration* injectionConfig,
                 /*out*/ std::vector<uint32_t>* injectionBufferSizes);
@@ -1557,7 +1557,7 @@
         Mutex mInjectionLock;
 
         // The injection camera ID.
-        String8 mInjectedCamId;
+        std::string mInjectedCamId;
     };
 
     virtual sp<Camera3DeviceInjectionMethods>
diff --git a/services/camera/libcameraservice/device3/Camera3DeviceInjectionMethods.cpp b/services/camera/libcameraservice/device3/Camera3DeviceInjectionMethods.cpp
index ab772d4..b0e4ca3 100644
--- a/services/camera/libcameraservice/device3/Camera3DeviceInjectionMethods.cpp
+++ b/services/camera/libcameraservice/device3/Camera3DeviceInjectionMethods.cpp
@@ -157,7 +157,7 @@
     return mIsStreamConfigCompleteButNotInjected;
 }
 
-const String8& Camera3Device::Camera3DeviceInjectionMethods::getInjectedCamId()
+const std::string& Camera3Device::Camera3DeviceInjectionMethods::getInjectedCamId()
         const {
     return mInjectedCamId;
 }
@@ -206,7 +206,7 @@
 
     // Start configuring the streams
     ALOGV("%s: Injection camera %s: Starting stream configuration", __FUNCTION__,
-            mInjectedCamId.string());
+            mInjectedCamId.c_str());
 
     parent->mPreparerThread->pause();
 
@@ -249,12 +249,12 @@
     parent->internalUpdateStatusLocked(STATUS_CONFIGURED);
 
     ALOGV("%s: Injection camera %s: Stream configuration complete", __FUNCTION__,
-            mInjectedCamId.string());
+            mInjectedCamId.c_str());
 
     auto rc = parent->mPreparerThread->resume();
     if (rc != OK) {
         ALOGE("%s: Injection camera %s: Preparer thread failed to resume!",
-                 __FUNCTION__, mInjectedCamId.string());
+                 __FUNCTION__, mInjectedCamId.c_str());
         return rc;
     }
 
diff --git a/services/camera/libcameraservice/device3/Camera3FakeStream.cpp b/services/camera/libcameraservice/device3/Camera3FakeStream.cpp
index 8c0ac71..75162bf 100644
--- a/services/camera/libcameraservice/device3/Camera3FakeStream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3FakeStream.cpp
@@ -20,13 +20,14 @@
 
 #include <utils/Log.h>
 #include <utils/Trace.h>
+#include <camera/StringUtils.h>
 #include "Camera3FakeStream.h"
 
 namespace android {
 
 namespace camera3 {
 
-const String8 Camera3FakeStream::FAKE_ID;
+const std::string Camera3FakeStream::FAKE_ID;
 
 Camera3FakeStream::Camera3FakeStream(int id) :
         Camera3IOStreamBase(id, CAMERA_STREAM_OUTPUT, FAKE_WIDTH, FAKE_HEIGHT,
@@ -68,9 +69,9 @@
 }
 
 void Camera3FakeStream::dump(int fd, [[maybe_unused]] const Vector<String16> &args) const {
-    String8 lines;
-    lines.appendFormat("    Stream[%d]: Fake\n", mId);
-    write(fd, lines.string(), lines.size());
+    std::string lines;
+    lines += fmt::sprintf("    Stream[%d]: Fake\n", mId);
+    write(fd, lines.c_str(), lines.size());
 
     Camera3IOStreamBase::dump(fd, args);
 }
@@ -115,7 +116,7 @@
     return OK;
 }
 
-const String8& Camera3FakeStream::getPhysicalCameraId() const {
+const std::string& Camera3FakeStream::getPhysicalCameraId() const {
     return FAKE_ID;
 }
 
diff --git a/services/camera/libcameraservice/device3/Camera3FakeStream.h b/services/camera/libcameraservice/device3/Camera3FakeStream.h
index 1e9f478..1d82190 100644
--- a/services/camera/libcameraservice/device3/Camera3FakeStream.h
+++ b/services/camera/libcameraservice/device3/Camera3FakeStream.h
@@ -65,7 +65,7 @@
     /**
      * Query the physical camera id for the output stream.
      */
-    virtual const String8& getPhysicalCameraId() const override;
+    virtual const std::string& getPhysicalCameraId() const override;
 
     /**
      * Return if this output stream is for video encoding.
@@ -130,7 +130,7 @@
     static const android_dataspace FAKE_DATASPACE = HAL_DATASPACE_UNKNOWN;
     static const camera_stream_rotation_t FAKE_ROTATION = CAMERA_STREAM_ROTATION_0;
     static const uint64_t FAKE_USAGE = GRALLOC_USAGE_HW_COMPOSER;
-    static const String8 FAKE_ID;
+    static const std::string FAKE_ID;
 
     /**
      * Internal Camera3Stream interface
diff --git a/services/camera/libcameraservice/device3/Camera3IOStreamBase.cpp b/services/camera/libcameraservice/device3/Camera3IOStreamBase.cpp
index fbaaf7b..c59138c 100644
--- a/services/camera/libcameraservice/device3/Camera3IOStreamBase.cpp
+++ b/services/camera/libcameraservice/device3/Camera3IOStreamBase.cpp
@@ -18,10 +18,13 @@
 #define ATRACE_TAG ATRACE_TAG_CAMERA
 //#define LOG_NDEBUG 0
 
+#include <sstream>
+
 #include <inttypes.h>
 
 #include <utils/Log.h>
 #include <utils/Trace.h>
+#include <camera/StringUtils.h>
 #include "device3/Camera3IOStreamBase.h"
 #include "device3/StatusTracker.h"
 
@@ -32,7 +35,7 @@
 Camera3IOStreamBase::Camera3IOStreamBase(int id, camera_stream_type_t type,
         uint32_t width, uint32_t height, size_t maxSize, int format,
         android_dataspace dataSpace, camera_stream_rotation_t rotation,
-        const String8& physicalCameraId,
+        const std::string& physicalCameraId,
         const std::unordered_set<int32_t> &sensorPixelModesUsed,
         int setId, bool isMultiResolution, int64_t dynamicRangeProfile, int64_t streamUseCase,
         bool deviceTimeBaseIsRealtime, int timestampBase, int32_t colorSpace) :
@@ -75,32 +78,34 @@
 }
 
 void Camera3IOStreamBase::dump(int fd, [[maybe_unused]] const Vector<String16> &args) const {
-    String8 lines;
+    std::ostringstream lines;
 
     uint64_t consumerUsage = 0;
     status_t res = getEndpointUsage(&consumerUsage);
     if (res != OK) consumerUsage = 0;
 
-    lines.appendFormat("      State: %d\n", mState);
-    lines.appendFormat("      Dims: %d x %d, format 0x%x, dataspace 0x%x\n",
+    lines << fmt::sprintf("      State: %d\n", mState);
+    lines << fmt::sprintf("      Dims: %d x %d, format 0x%x, dataspace 0x%x\n",
             camera_stream::width, camera_stream::height,
             camera_stream::format, camera_stream::data_space);
-    lines.appendFormat("      Max size: %zu\n", mMaxSize);
-    lines.appendFormat("      Combined usage: 0x%" PRIx64 ", max HAL buffers: %d\n",
+    lines << fmt::sprintf("      Max size: %zu\n", mMaxSize);
+    lines << fmt::sprintf("      Combined usage: 0x%" PRIx64 ", max HAL buffers: %d\n",
             mUsage | consumerUsage, camera_stream::max_buffers);
-    if (strlen(camera_stream::physical_camera_id) > 0) {
-        lines.appendFormat("      Physical camera id: %s\n", camera_stream::physical_camera_id);
+    if (!camera_stream::physical_camera_id.empty()) {
+        lines << "      Physical camera id: " << camera_stream::physical_camera_id << "\n";
     }
-    lines.appendFormat("      Dynamic Range Profile: 0x%" PRIx64 "\n",
+    lines << fmt::sprintf("      Dynamic Range Profile: 0x%" PRIx64 "\n",
             camera_stream::dynamic_range_profile);
-    lines.appendFormat("      Color Space: %d\n", camera_stream::color_space);
-    lines.appendFormat("      Stream use case: %" PRId64 "\n", camera_stream::use_case);
-    lines.appendFormat("      Timestamp base: %d\n", getTimestampBase());
-    lines.appendFormat("      Frames produced: %d, last timestamp: %" PRId64 " ns\n",
+    lines << fmt::sprintf("      Color Space: %d\n", camera_stream::color_space);
+    lines << fmt::sprintf("      Stream use case: %" PRId64 "\n", camera_stream::use_case);
+    lines << fmt::sprintf("      Timestamp base: %d\n", getTimestampBase());
+    lines << fmt::sprintf("      Frames produced: %d, last timestamp: %" PRId64 " ns\n",
             mFrameCount, mLastTimestamp);
-    lines.appendFormat("      Total buffers: %zu, currently dequeued: %zu, currently cached: %zu\n",
-            mTotalBufferCount, mHandoutTotalBufferCount, mCachedOutputBufferCount);
-    write(fd, lines.string(), lines.size());
+    lines << fmt::sprintf("      Total buffers: %zu, currently dequeued: %zu, "
+            "currently cached: %zu\n", mTotalBufferCount, mHandoutTotalBufferCount,
+            mCachedOutputBufferCount);
+    std::string linesStr = std::move(lines.str());
+    write(fd, linesStr.c_str(), linesStr.size());
 
     Camera3Stream::dump(fd, args);
 }
@@ -268,7 +273,7 @@
     // carry on
 
     if (releaseFence != 0) {
-        mCombinedFence = Fence::merge(mName, mCombinedFence, releaseFence);
+        mCombinedFence = Fence::merge(toString8(mName), mCombinedFence, releaseFence);
     }
 
     if (output) {
diff --git a/services/camera/libcameraservice/device3/Camera3IOStreamBase.h b/services/camera/libcameraservice/device3/Camera3IOStreamBase.h
index 6af0875..239fc71 100644
--- a/services/camera/libcameraservice/device3/Camera3IOStreamBase.h
+++ b/services/camera/libcameraservice/device3/Camera3IOStreamBase.h
@@ -35,7 +35,7 @@
     Camera3IOStreamBase(int id, camera_stream_type_t type,
             uint32_t width, uint32_t height, size_t maxSize, int format,
             android_dataspace dataSpace, camera_stream_rotation_t rotation,
-            const String8& physicalCameraId,
+            const std::string& physicalCameraId,
             const std::unordered_set<int32_t> &sensorPixelModesUsed,
             int setId = CAMERA3_STREAM_SET_ID_INVALID, bool isMultiResolution = false,
             int64_t dynamicProfile = ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD,
diff --git a/services/camera/libcameraservice/device3/Camera3InputStream.cpp b/services/camera/libcameraservice/device3/Camera3InputStream.cpp
index 631bb43..54ffbd7 100644
--- a/services/camera/libcameraservice/device3/Camera3InputStream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3InputStream.cpp
@@ -21,13 +21,14 @@
 #include <gui/BufferItem.h>
 #include <utils/Log.h>
 #include <utils/Trace.h>
+#include <camera/StringUtils.h>
 #include "Camera3InputStream.h"
 
 namespace android {
 
 namespace camera3 {
 
-const String8 Camera3InputStream::FAKE_ID;
+const std::string Camera3InputStream::FAKE_ID;
 
 Camera3InputStream::Camera3InputStream(int id,
         uint32_t width, uint32_t height, int format) :
@@ -216,9 +217,9 @@
 }
 
 void Camera3InputStream::dump(int fd, [[maybe_unused]] const Vector<String16> &args) const {
-    String8 lines;
-    lines.appendFormat("    Stream[%d]: Input\n", mId);
-    write(fd, lines.string(), lines.size());
+    std::string lines;
+    lines += fmt::sprintf("    Stream[%d]: Input\n", mId);
+    write(fd, lines.c_str(), lines.size());
 
     Camera3IOStreamBase::dump(fd, args);
 }
diff --git a/services/camera/libcameraservice/device3/Camera3InputStream.h b/services/camera/libcameraservice/device3/Camera3InputStream.h
index 5e0587b..d4f4b15 100644
--- a/services/camera/libcameraservice/device3/Camera3InputStream.h
+++ b/services/camera/libcameraservice/device3/Camera3InputStream.h
@@ -53,7 +53,7 @@
     sp<IGraphicBufferProducer> mProducer;
     Vector<BufferItem> mBuffersInFlight;
 
-    static const String8 FAKE_ID;
+    static const std::string FAKE_ID;
 
     /**
      * Camera3IOStreamBase
diff --git a/services/camera/libcameraservice/device3/Camera3OfflineSession.cpp b/services/camera/libcameraservice/device3/Camera3OfflineSession.cpp
index 1e7bd57..172b62a 100644
--- a/services/camera/libcameraservice/device3/Camera3OfflineSession.cpp
+++ b/services/camera/libcameraservice/device3/Camera3OfflineSession.cpp
@@ -27,7 +27,9 @@
 
 #include <inttypes.h>
 
+#include <android-base/stringprintf.h>
 #include <utils/Trace.h>
+#include <camera/StringUtils.h>
 
 #include <android/hardware/camera2/ICameraDeviceCallbacks.h>
 
@@ -42,7 +44,7 @@
 
 namespace android {
 
-Camera3OfflineSession::Camera3OfflineSession(const String8 &id,
+Camera3OfflineSession::Camera3OfflineSession(const std::string &id,
         const sp<camera3::Camera3Stream>& inputStream,
         const camera3::StreamSet& offlineStreamSet,
         camera3::BufferRecords&& bufferRecords,
@@ -75,15 +77,15 @@
         mRotateAndCropMappers(offlineStates.mRotateAndCropMappers),
         mStatus(STATUS_UNINITIALIZED) {
     ATRACE_CALL();
-    ALOGV("%s: Created offline session for camera %s", __FUNCTION__, mId.string());
+    ALOGV("%s: Created offline session for camera %s", __FUNCTION__, mId.c_str());
 }
 
 Camera3OfflineSession::~Camera3OfflineSession() {
     ATRACE_CALL();
-    ALOGV("%s: Tearing down offline session for camera id %s", __FUNCTION__, mId.string());
+    ALOGV("%s: Tearing down offline session for camera id %s", __FUNCTION__, mId.c_str());
 }
 
-const String8& Camera3OfflineSession::getId() const {
+const std::string& Camera3OfflineSession::getId() const {
     return mId;
 }
 
@@ -109,7 +111,7 @@
             return OK; // don't close twice
         } else if (mStatus == STATUS_ERROR) {
             ALOGE("%s: offline session %s shutting down in error state",
-                    __FUNCTION__, mId.string());
+                    __FUNCTION__, mId.c_str());
         }
         listener = mListener.promote();
     }
@@ -217,8 +219,9 @@
 
 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());
+    std::string errorCause;
+    base::StringAppendV(&errorCause, fmt, args);
+    ALOGE("Camera %s: %s", mId.c_str(), errorCause.c_str());
 
     // But only do error state transition steps for the first error
     if (mStatus == STATUS_ERROR || mStatus == STATUS_UNINITIALIZED) return;
diff --git a/services/camera/libcameraservice/device3/Camera3OfflineSession.h b/services/camera/libcameraservice/device3/Camera3OfflineSession.h
index e780043..b5fd486 100644
--- a/services/camera/libcameraservice/device3/Camera3OfflineSession.h
+++ b/services/camera/libcameraservice/device3/Camera3OfflineSession.h
@@ -20,9 +20,6 @@
 #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>
@@ -138,7 +135,7 @@
   public:
 
     // initialize by Camera3Device.
-    explicit Camera3OfflineSession(const String8& id,
+    explicit Camera3OfflineSession(const std::string& id,
             const sp<camera3::Camera3Stream>& inputStream,
             const camera3::StreamSet& offlineStreamSet,
             camera3::BufferRecords&& bufferRecords,
@@ -158,7 +155,7 @@
     /**
      * FrameProducer interface
      */
-    const String8& getId() const override;
+    const std::string& getId() const override;
     const CameraMetadata& info() const override;
     status_t waitForNextFrame(nsecs_t timeout) override;
     status_t getNextResult(CaptureResult *frame) override;
@@ -171,7 +168,7 @@
 
   protected:
     // Camera device ID
-    const String8 mId;
+    const std::string mId;
     sp<camera3::Camera3Stream> mInputStream;
     camera3::StreamSet mOutputStreams;
     camera3::BufferRecords mBufferRecords;
@@ -236,7 +233,7 @@
     std::mutex mProcessCaptureResultLock;
 
     // Tracking cause of fatal errors when in STATUS_ERROR
-    String8 mErrorCause;
+    std::string mErrorCause;
 
     // Lock to ensure requestStreamBuffers() callbacks are serialized
     std::mutex mRequestBufferInterfaceLock;
diff --git a/services/camera/libcameraservice/device3/Camera3OutputStream.cpp b/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
index aaf5d8d..f98636b 100644
--- a/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
@@ -31,6 +31,7 @@
 #include <ui/GraphicBuffer.h>
 #include <utils/Log.h>
 #include <utils/Trace.h>
+#include <camera/StringUtils.h>
 
 #include <common/CameraDeviceBase.h>
 #include "api1/client2/JpegProcessor.h"
@@ -53,7 +54,7 @@
         sp<Surface> consumer,
         uint32_t width, uint32_t height, int format,
         android_dataspace dataSpace, camera_stream_rotation_t rotation,
-        nsecs_t timestampOffset, const String8& physicalCameraId,
+        nsecs_t timestampOffset, const std::string& physicalCameraId,
         const std::unordered_set<int32_t> &sensorPixelModesUsed, IPCTransport transport,
         int setId, bool isMultiResolution, int64_t dynamicRangeProfile,
         int64_t streamUseCase, bool deviceTimeBaseIsRealtime, int timestampBase,
@@ -88,7 +89,7 @@
         sp<Surface> consumer,
         uint32_t width, uint32_t height, size_t maxSize, int format,
         android_dataspace dataSpace, camera_stream_rotation_t rotation,
-        nsecs_t timestampOffset, const String8& physicalCameraId,
+        nsecs_t timestampOffset, const std::string& physicalCameraId,
         const std::unordered_set<int32_t> &sensorPixelModesUsed, IPCTransport transport,
         int setId, bool isMultiResolution, int64_t dynamicRangeProfile,
         int64_t streamUseCase, bool deviceTimeBaseIsRealtime, int timestampBase,
@@ -128,7 +129,7 @@
         uint32_t width, uint32_t height, int format,
         uint64_t consumerUsage, android_dataspace dataSpace,
         camera_stream_rotation_t rotation, nsecs_t timestampOffset,
-        const String8& physicalCameraId,
+        const std::string& physicalCameraId,
         const std::unordered_set<int32_t> &sensorPixelModesUsed, IPCTransport transport,
         int setId, bool isMultiResolution, int64_t dynamicRangeProfile,
         int64_t streamUseCase, bool deviceTimeBaseIsRealtime, int timestampBase,
@@ -164,7 +165,7 @@
         mState = STATE_ERROR;
     }
 
-    mConsumerName = String8("Deferred");
+    mConsumerName = "Deferred";
     bool needsReleaseNotify = setId > CAMERA3_STREAM_SET_ID_INVALID;
     mBufferProducerListener = new BufferProducerListener(this, needsReleaseNotify);
 }
@@ -174,7 +175,7 @@
                                          int format,
                                          android_dataspace dataSpace,
                                          camera_stream_rotation_t rotation,
-                                         const String8& physicalCameraId,
+                                         const std::string& physicalCameraId,
                                          const std::unordered_set<int32_t> &sensorPixelModesUsed,
                                          IPCTransport transport,
                                          uint64_t consumerUsage, nsecs_t timestampOffset,
@@ -523,10 +524,10 @@
 }
 
 void Camera3OutputStream::dump(int fd, [[maybe_unused]] const Vector<String16> &args) const {
-    String8 lines;
-    lines.appendFormat("    Stream[%d]: Output\n", mId);
-    lines.appendFormat("      Consumer name: %s\n", mConsumerName.string());
-    write(fd, lines.string(), lines.size());
+    std::string lines;
+    lines += fmt::sprintf("    Stream[%d]: Output\n", mId);
+    lines += fmt::sprintf("      Consumer name: %s\n", mConsumerName);
+    write(fd, lines.c_str(), lines.size());
 
     Camera3IOStreamBase::dump(fd, args);
 
@@ -710,7 +711,8 @@
             // service. So update mMaxCachedBufferCount.
             mMaxCachedBufferCount = 1;
             mTotalBufferCount += mMaxCachedBufferCount;
-            res = mPreviewFrameSpacer->run(String8::format("PreviewSpacer-%d", mId).string());
+            res = mPreviewFrameSpacer->run((std::string("PreviewSpacer-")
+                    + std::to_string(mId)).c_str());
             if (res != OK) {
                 ALOGE("%s: Unable to start preview spacer: %s (%d)", __FUNCTION__,
                         strerror(-res), res);
@@ -1234,7 +1236,7 @@
     return OK;
 }
 
-const String8& Camera3OutputStream::getPhysicalCameraId() const {
+const std::string& Camera3OutputStream::getPhysicalCameraId() const {
     Mutex::Autolock l(mLock);
     return physicalCameraId();
 }
@@ -1338,7 +1340,7 @@
     // Output image data to file
     std::string filePath = "/data/misc/cameraserver/";
     filePath += imageFileName;
-    std::ofstream imageFile(filePath.c_str(), std::ofstream::binary);
+    std::ofstream imageFile(filePath, std::ofstream::binary);
     if (!imageFile.is_open()) {
         ALOGE("%s: Unable to create file %s", __FUNCTION__, filePath.c_str());
         graphicBuffer->unlock();
diff --git a/services/camera/libcameraservice/device3/Camera3OutputStream.h b/services/camera/libcameraservice/device3/Camera3OutputStream.h
index ebd5797..65791a9 100644
--- a/services/camera/libcameraservice/device3/Camera3OutputStream.h
+++ b/services/camera/libcameraservice/device3/Camera3OutputStream.h
@@ -89,7 +89,7 @@
     Camera3OutputStream(int id, sp<Surface> consumer,
             uint32_t width, uint32_t height, int format,
             android_dataspace dataSpace, camera_stream_rotation_t rotation,
-            nsecs_t timestampOffset, const String8& physicalCameraId,
+            nsecs_t timestampOffset, const std::string& physicalCameraId,
             const std::unordered_set<int32_t> &sensorPixelModesUsed, IPCTransport transport,
             int setId = CAMERA3_STREAM_SET_ID_INVALID, bool isMultiResolution = false,
             int64_t dynamicProfile = ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD,
@@ -108,7 +108,7 @@
     Camera3OutputStream(int id, sp<Surface> consumer,
             uint32_t width, uint32_t height, size_t maxSize, int format,
             android_dataspace dataSpace, camera_stream_rotation_t rotation,
-            nsecs_t timestampOffset, const String8& physicalCameraId,
+            nsecs_t timestampOffset, const std::string& physicalCameraId,
             const std::unordered_set<int32_t> &sensorPixelModesUsed, IPCTransport transport,
             int setId = CAMERA3_STREAM_SET_ID_INVALID, bool isMultiResolution = false,
             int64_t dynamicProfile = ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD,
@@ -126,7 +126,7 @@
     Camera3OutputStream(int id, uint32_t width, uint32_t height, int format,
             uint64_t consumerUsage, android_dataspace dataSpace,
             camera_stream_rotation_t rotation, nsecs_t timestampOffset,
-            const String8& physicalCameraId,
+            const std::string& physicalCameraId,
             const std::unordered_set<int32_t> &sensorPixelModesUsed, IPCTransport transport,
             int setId = CAMERA3_STREAM_SET_ID_INVALID, bool isMultiResolution = false,
             int64_t dynamicProfile = ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD,
@@ -214,7 +214,7 @@
     /**
      * Query the physical camera id for the output stream.
      */
-    virtual const String8& getPhysicalCameraId() const override;
+    virtual const std::string& getPhysicalCameraId() const override;
 
     /**
      * Set the graphic buffer manager to get/return the stream buffers.
@@ -276,7 +276,7 @@
     Camera3OutputStream(int id, camera_stream_type_t type,
             uint32_t width, uint32_t height, int format,
             android_dataspace dataSpace, camera_stream_rotation_t rotation,
-            const String8& physicalCameraId,
+            const std::string& physicalCameraId,
             const std::unordered_set<int32_t> &sensorPixelModesUsed, IPCTransport transport,
             uint64_t consumerUsage = 0, nsecs_t timestampOffset = 0,
             int setId = CAMERA3_STREAM_SET_ID_INVALID, bool isMultiResolution = false,
@@ -327,7 +327,7 @@
     bool mTraceFirstBuffer;
 
     // Name of Surface consumer
-    String8           mConsumerName;
+    std::string           mConsumerName;
 
     /**
      * GraphicBuffer manager this stream is registered to. Used to replace the buffer
diff --git a/services/camera/libcameraservice/device3/Camera3OutputStreamInterface.h b/services/camera/libcameraservice/device3/Camera3OutputStreamInterface.h
index 4baa7e8..1ab8162 100644
--- a/services/camera/libcameraservice/device3/Camera3OutputStreamInterface.h
+++ b/services/camera/libcameraservice/device3/Camera3OutputStreamInterface.h
@@ -94,7 +94,7 @@
     /**
      * Query the physical camera id for the output stream.
      */
-    virtual const String8& getPhysicalCameraId() const = 0;
+    virtual const std::string& getPhysicalCameraId() const = 0;
 
     /**
      * Set the batch size for buffer operations. The output stream will request
diff --git a/services/camera/libcameraservice/device3/Camera3OutputUtils.cpp b/services/camera/libcameraservice/device3/Camera3OutputUtils.cpp
index f742a6d..88a7d69 100644
--- a/services/camera/libcameraservice/device3/Camera3OutputUtils.cpp
+++ b/services/camera/libcameraservice/device3/Camera3OutputUtils.cpp
@@ -43,6 +43,7 @@
 #include <android/hardware/camera/device/3.5/ICameraDeviceSession.h>
 
 #include <camera/CameraUtils.h>
+#include <camera/StringUtils.h>
 #include <camera_metadata_hidden.h>
 
 #include "device3/Camera3OutputUtils.h"
@@ -249,18 +250,18 @@
     // and RotationAndCrop mappers.
     std::set<uint32_t> keysToRemove;
 
-    auto iter = states.distortionMappers.find(states.cameraId.c_str());
+    auto iter = states.distortionMappers.find(states.cameraId);
     if (iter != states.distortionMappers.end()) {
         const auto& remappedKeys = iter->second.getRemappedKeys();
         keysToRemove.insert(remappedKeys.begin(), remappedKeys.end());
     }
 
-    const auto& remappedKeys = states.zoomRatioMappers[states.cameraId.c_str()].getRemappedKeys();
+    const auto& remappedKeys = states.zoomRatioMappers[states.cameraId].getRemappedKeys();
     keysToRemove.insert(remappedKeys.begin(), remappedKeys.end());
 
-    auto mapper = states.rotateAndCropMappers.find(states.cameraId.c_str());
+    auto mapper = states.rotateAndCropMappers.find(states.cameraId);
     if (mapper != states.rotateAndCropMappers.end()) {
-        const auto& remappedKeys = iter->second.getRemappedKeys();
+        const auto& remappedKeys = mapper->second.getRemappedKeys();
         keysToRemove.insert(remappedKeys.begin(), remappedKeys.end());
     }
 
@@ -342,14 +343,14 @@
                 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);
+                    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());
+    auto iter = states.distortionMappers.find(states.cameraId);
     if (iter != states.distortionMappers.end()) {
         res = iter->second.correctCaptureResult(&captureResult.mMetadata);
         if (res != OK) {
@@ -361,8 +362,8 @@
 
     // 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(
+    bool zoomRatioIs1 = cameraIdsWithZoom.find(states.cameraId) == cameraIdsWithZoom.end();
+    res = states.zoomRatioMappers[states.cameraId].updateCaptureResult(
             &captureResult.mMetadata, zoomRatioIs1);
     if (res != OK) {
         SET_ERR("Failed to update capture result zoom ratio metadata for frame %d: %s (%d)",
@@ -372,7 +373,7 @@
 
     // Fix up result metadata to account for rotateAndCrop in AUTO mode
     if (rotateAndCropAuto) {
-        auto mapper = states.rotateAndCropMappers.find(states.cameraId.c_str());
+        auto mapper = states.rotateAndCropMappers.find(states.cameraId);
         if (mapper != states.rotateAndCropMappers.end()) {
             res = mapper->second.updateCaptureResult(
                     &captureResult.mMetadata);
@@ -401,8 +402,8 @@
     }
 
     for (auto& physicalMetadata : captureResult.mPhysicalMetadatas) {
-        String8 cameraId8(physicalMetadata.mPhysicalCameraId);
-        auto mapper = states.distortionMappers.find(cameraId8.c_str());
+        const std::string cameraId = physicalMetadata.mPhysicalCameraId;
+        auto mapper = states.distortionMappers.find(cameraId);
         if (mapper != states.distortionMappers.end()) {
             res = mapper->second.correctCaptureResult(
                     &physicalMetadata.mPhysicalCameraMetadata);
@@ -413,12 +414,12 @@
             }
         }
 
-        zoomRatioIs1 = cameraIdsWithZoom.find(cameraId8.c_str()) == cameraIdsWithZoom.end();
-        res = states.zoomRatioMappers[cameraId8.c_str()].updateCaptureResult(
+        zoomRatioIs1 = cameraIdsWithZoom.find(cameraId) == cameraIdsWithZoom.end();
+        res = states.zoomRatioMappers[cameraId].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);
+                    "frame %d: %s(%d)", cameraId.c_str(), frameNumber, strerror(-res), res);
             return;
         }
     }
@@ -430,9 +431,9 @@
         return;
     }
     for (auto& physicalMetadata : captureResult.mPhysicalMetadatas) {
-        String8 cameraId8(physicalMetadata.mPhysicalCameraId);
+        const std::string &cameraId = physicalMetadata.mPhysicalCameraId;
         res = fixupMonochromeTags(states,
-                states.physicalDeviceInfoMap.at(cameraId8.c_str()),
+                states.physicalDeviceInfoMap.at(cameraId),
                 physicalMetadata.mPhysicalCameraMetadata);
         if (res != OK) {
             SET_ERR("Failed to override result metadata: %s (%d)", strerror(-res), res);
@@ -442,7 +443,7 @@
 
     std::unordered_map<std::string, CameraMetadata> monitoredPhysicalMetadata;
     for (auto& m : physicalMetadatas) {
-        monitoredPhysicalMetadata.emplace(String8(m.mPhysicalCameraId).string(),
+        monitoredPhysicalMetadata.emplace(m.mPhysicalCameraId,
                 CameraMetadata(m.mPhysicalCameraMetadata));
     }
     states.tagMonitor.monitorMetadata(TagMonitor::RESULT,
@@ -528,7 +529,7 @@
 
 // Erase the subset of physicalCameraIds that contains id
 bool erasePhysicalCameraIdSet(
-        std::set<std::set<String8>>& physicalCameraIds, const String8& id) {
+        std::set<std::set<std::string>>& physicalCameraIds, const std::string& id) {
     bool found = false;
     for (auto iter = physicalCameraIds.begin(); iter != physicalCameraIds.end(); iter++) {
         if (iter->count(id) == 1) {
@@ -712,7 +713,7 @@
                 return;
             }
             for (uint32_t i = 0; i < result->num_physcam_metadata; i++) {
-                String8 physicalId(result->physcam_ids[i]);
+                const std::string physicalId = result->physcam_ids[i];
                 bool validPhysicalCameraMetadata =
                         erasePhysicalCameraIdSet(request.physicalCameraIds, physicalId);
                 if (!validPhysicalCameraMetadata) {
@@ -768,7 +769,7 @@
             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]),
+                request.physicalMetadatas.push_back({result->physcam_ids[i],
                         physicalMetadata});
             }
             if (shutterTimestamp == 0) {
@@ -996,7 +997,7 @@
             }
             if (r.hasCallback) {
                 ALOGVV("Camera %s: %s: Shutter fired for frame %d (id %d) at %" PRId64,
-                    states.cameraId.string(), __FUNCTION__,
+                    states.cameraId.c_str(), __FUNCTION__,
                     msg.frame_number, r.resultExtras.requestId, msg.timestamp);
                 // Call listener, if any
                 if (states.listener != nullptr) {
@@ -1053,15 +1054,15 @@
             hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_INVALID_ERROR;
 
     int streamId = 0;
-    String16 physicalCameraId;
+    std::string physicalCameraId;
     if (msg.error_stream != nullptr) {
         Camera3Stream *stream =
                 Camera3Stream::cast(msg.error_stream);
         streamId = stream->getId();
-        physicalCameraId = String16(stream->physicalCameraId());
+        physicalCameraId = stream->physicalCameraId();
     }
     ALOGV("Camera %s: %s: HAL error, frame %d, stream %d: %d",
-            states.cameraId.string(), __FUNCTION__, msg.frame_number,
+            states.cameraId.c_str(), __FUNCTION__, msg.frame_number,
             streamId, msg.error_code);
 
     CaptureResultExtras resultExtras;
@@ -1083,13 +1084,12 @@
                     if (hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_RESULT ==
                             errorCode) {
                         if (physicalCameraId.size() > 0) {
-                            String8 cameraId(physicalCameraId);
                             bool validPhysicalCameraId =
-                                    erasePhysicalCameraIdSet(r.physicalCameraIds, cameraId);
+                                    erasePhysicalCameraIdSet(r.physicalCameraIds, physicalCameraId);
                             if (!validPhysicalCameraId) {
                                 ALOGE("%s: Reported result failure for physical camera device: %s "
                                         " which is not part of the respective request!",
-                                        __FUNCTION__, cameraId.string());
+                                        __FUNCTION__, physicalCameraId.c_str());
                                 break;
                             }
                             resultExtras.errorPhysicalCameraId = physicalCameraId;
@@ -1114,7 +1114,7 @@
                 } else {
                     resultExtras.frameNumber = msg.frame_number;
                     ALOGE("Camera %s: %s: cannot find in-flight request on "
-                            "frame %" PRId64 " error", states.cameraId.string(), __FUNCTION__,
+                            "frame %" PRId64 " error", states.cameraId.c_str(), __FUNCTION__,
                             resultExtras.frameNumber);
                 }
             }
@@ -1123,7 +1123,7 @@
                 states.listener->notifyError(errorCode, resultExtras);
             } else {
                 ALOGE("Camera %s: %s: no listener available",
-                        states.cameraId.string(), __FUNCTION__);
+                        states.cameraId.c_str(), __FUNCTION__);
             }
             break;
         case hardware::camera2::ICameraDeviceCallbacks::ERROR_CAMERA_BUFFER:
diff --git a/services/camera/libcameraservice/device3/Camera3OutputUtils.h b/services/camera/libcameraservice/device3/Camera3OutputUtils.h
index d5328c5..134c037 100644
--- a/services/camera/libcameraservice/device3/Camera3OutputUtils.h
+++ b/services/camera/libcameraservice/device3/Camera3OutputUtils.h
@@ -71,7 +71,7 @@
     // Camera3Device/Camera3OfflineSession internal states used in notify/processCaptureResult
     // callbacks
     struct CaptureOutputStates {
-        const String8& cameraId;
+        const std::string& cameraId;
         std::mutex& inflightLock;
         int64_t& lastCompletedRegularFrameNumber;
         int64_t& lastCompletedReprocessFrameNumber;
@@ -115,7 +115,7 @@
     void notify(CaptureOutputStates& states, const camera_notify_msg *msg);
 
     struct RequestBufferStates {
-        const String8& cameraId;
+        const std::string& cameraId;
         std::mutex& reqBufferLock; // lock to serialize request buffer calls
         const bool useHalBufManager;
         StreamSet& outputStreams;
@@ -126,7 +126,7 @@
     };
 
     struct ReturnBufferStates {
-        const String8& cameraId;
+        const std::string& cameraId;
         const bool useHalBufManager;
         StreamSet& outputStreams;
         SessionStatsBuilder& sessionStatsBuilder;
@@ -134,7 +134,7 @@
     };
 
     struct FlushInflightReqStates {
-        const String8& cameraId;
+        const std::string& cameraId;
         std::mutex& inflightLock;
         InFlightRequestMap& inflightMap; // end of inflightLock scope
         const bool useHalBufManager;
diff --git a/services/camera/libcameraservice/device3/Camera3OutputUtilsTemplated.h b/services/camera/libcameraservice/device3/Camera3OutputUtilsTemplated.h
index 2e05dda..3ac666b 100644
--- a/services/camera/libcameraservice/device3/Camera3OutputUtilsTemplated.h
+++ b/services/camera/libcameraservice/device3/Camera3OutputUtilsTemplated.h
@@ -296,7 +296,7 @@
         const VecStreamBufferType& buffers) {
     if (!states.useHalBufManager) {
         ALOGE("%s: Camera %s does not support HAL buffer managerment",
-                __FUNCTION__, states.cameraId.string());
+                __FUNCTION__, states.cameraId.c_str());
         return;
     }
 
diff --git a/services/camera/libcameraservice/device3/Camera3SharedOutputStream.cpp b/services/camera/libcameraservice/device3/Camera3SharedOutputStream.cpp
index f3a7359..1191f05 100644
--- a/services/camera/libcameraservice/device3/Camera3SharedOutputStream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3SharedOutputStream.cpp
@@ -31,7 +31,7 @@
         uint32_t width, uint32_t height, int format,
         uint64_t consumerUsage, android_dataspace dataSpace,
         camera_stream_rotation_t rotation,
-        nsecs_t timestampOffset, const String8& physicalCameraId,
+        nsecs_t timestampOffset, const std::string& physicalCameraId,
         const std::unordered_set<int32_t> &sensorPixelModesUsed, IPCTransport transport,
         int setId, bool useHalBufManager, int64_t dynamicProfile,
         int64_t streamUseCase, bool deviceTimeBaseIsRealtime, int timestampBase,
diff --git a/services/camera/libcameraservice/device3/Camera3SharedOutputStream.h b/services/camera/libcameraservice/device3/Camera3SharedOutputStream.h
index 1102ecb..c2ff20e 100644
--- a/services/camera/libcameraservice/device3/Camera3SharedOutputStream.h
+++ b/services/camera/libcameraservice/device3/Camera3SharedOutputStream.h
@@ -37,7 +37,7 @@
             uint32_t width, uint32_t height, int format,
             uint64_t consumerUsage, android_dataspace dataSpace,
             camera_stream_rotation_t rotation, nsecs_t timestampOffset,
-            const String8& physicalCameraId,
+            const std::string& physicalCameraId,
             const std::unordered_set<int32_t> &sensorPixelModesUsed, IPCTransport transport,
             int setId = CAMERA3_STREAM_SET_ID_INVALID,
             bool useHalBufManager = false,
diff --git a/services/camera/libcameraservice/device3/Camera3Stream.cpp b/services/camera/libcameraservice/device3/Camera3Stream.cpp
index 4395455..23afa6e 100644
--- a/services/camera/libcameraservice/device3/Camera3Stream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Stream.cpp
@@ -22,6 +22,7 @@
 
 #include <utils/Log.h>
 #include <utils/Trace.h>
+#include <camera/StringUtils.h>
 #include "device3/Camera3Stream.h"
 #include "device3/StatusTracker.h"
 #include "utils/TraceHFR.h"
@@ -52,7 +53,7 @@
         camera_stream_type type,
         uint32_t width, uint32_t height, size_t maxSize, int format,
         android_dataspace dataSpace, camera_stream_rotation_t rotation,
-        const String8& physicalCameraId,
+        const std::string& physicalCameraId,
         const std::unordered_set<int32_t> &sensorPixelModesUsed,
         int setId, bool isMultiResolution, int64_t dynamicRangeProfile,
         int64_t streamUseCase, bool deviceTimeBaseIsRealtime, int timestampBase,
@@ -60,7 +61,7 @@
     camera_stream(),
     mId(id),
     mSetId(setId),
-    mName(String8::format("Camera3Stream[%d]", id)),
+    mName(fmt::sprintf("Camera3Stream[%d]", id)),
     mMaxSize(maxSize),
     mState(STATE_CONSTRUCTED),
     mStatusId(StatusTracker::NO_STATUS_ID),
@@ -92,7 +93,7 @@
     camera_stream::data_space = dataSpace;
     camera_stream::rotation = rotation;
     camera_stream::max_buffers = 0;
-    camera_stream::physical_camera_id = mPhysicalCameraId.string();
+    camera_stream::physical_camera_id = mPhysicalCameraId;
     camera_stream::sensor_pixel_modes_used = sensorPixelModesUsed;
     camera_stream::dynamic_range_profile = dynamicRangeProfile;
     camera_stream::use_case = streamUseCase;
@@ -177,7 +178,7 @@
     return mOriginalDataSpace;
 }
 
-const String8& Camera3Stream::physicalCameraId() const {
+const std::string& Camera3Stream::physicalCameraId() const {
     return mPhysicalCameraId;
 }
 
@@ -376,7 +377,7 @@
     sp<StatusTracker> statusTracker = mStatusTracker.promote();
     if (statusTracker != 0 && mStatusId == StatusTracker::NO_STATUS_ID) {
         std::string name = std::string("Stream ") + std::to_string(mId);
-        mStatusId = statusTracker->addComponent(name.c_str());
+        mStatusId = statusTracker->addComponent(name);
     }
 
     // Check if the stream configuration is unchanged, and skip reallocation if
diff --git a/services/camera/libcameraservice/device3/Camera3Stream.h b/services/camera/libcameraservice/device3/Camera3Stream.h
index f32053b..2bfaaab 100644
--- a/services/camera/libcameraservice/device3/Camera3Stream.h
+++ b/services/camera/libcameraservice/device3/Camera3Stream.h
@@ -19,7 +19,6 @@
 
 #include <gui/Surface.h>
 #include <utils/RefBase.h>
-#include <utils/String8.h>
 #include <utils/String16.h>
 #include <utils/List.h>
 
@@ -163,25 +162,25 @@
     /**
      * Get the stream's dimensions and format
      */
-    uint32_t          getWidth() const;
-    uint32_t          getHeight() const;
-    int               getFormat() const;
-    android_dataspace getDataSpace() const;
-    int32_t           getColorSpace() const;
-    uint64_t          getUsage() const;
-    void              setUsage(uint64_t usage);
-    void              setFormatOverride(bool formatOverriden);
-    bool              isFormatOverridden() const;
-    int               getOriginalFormat() const;
-    int64_t           getDynamicRangeProfile() const;
-    void              setDataSpaceOverride(bool dataSpaceOverriden);
-    bool              isDataSpaceOverridden() const;
-    android_dataspace getOriginalDataSpace() const;
-    int               getMaxHalBuffers() const;
-    const String8&    physicalCameraId() const;
-    int64_t           getStreamUseCase() const;
-    int               getTimestampBase() const;
-    bool              isDeviceTimeBaseRealtime() const;
+    uint32_t           getWidth() const;
+    uint32_t           getHeight() const;
+    int                getFormat() const;
+    android_dataspace  getDataSpace() const;
+    int32_t            getColorSpace() const;
+    uint64_t           getUsage() const;
+    void               setUsage(uint64_t usage);
+    void               setFormatOverride(bool formatOverridden);
+    bool               isFormatOverridden() const;
+    int                getOriginalFormat() const;
+    int64_t            getDynamicRangeProfile() const;
+    void               setDataSpaceOverride(bool dataSpaceOverridden);
+    bool               isDataSpaceOverridden() const;
+    android_dataspace  getOriginalDataSpace() const;
+    int                getMaxHalBuffers() const;
+    const std::string& physicalCameraId() const;
+    int64_t            getStreamUseCase() const;
+    int                getTimestampBase() const;
+    bool               isDeviceTimeBaseRealtime() const;
 
     void              setOfflineProcessingSupport(bool) override;
     bool              getOfflineProcessingSupport() const override;
@@ -487,7 +486,7 @@
      */
     const int mSetId;
 
-    const String8 mName;
+    const std::string mName;
     // Zero for formats with fixed buffer size for given dimensions.
     const size_t mMaxSize;
 
@@ -507,7 +506,7 @@
     Camera3Stream(int id, camera_stream_type type,
             uint32_t width, uint32_t height, size_t maxSize, int format,
             android_dataspace dataSpace, camera_stream_rotation_t rotation,
-            const String8& physicalCameraId,
+            const std::string& physicalCameraId,
             const std::unordered_set<int32_t> &sensorPixelModesUsed,
             int setId, bool isMultiResolution, int64_t dynamicRangeProfile,
             int64_t streamUseCase, bool deviceTimeBaseIsRealtime, int timestampBase,
@@ -634,7 +633,7 @@
     bool mDataSpaceOverridden;
     const android_dataspace mOriginalDataSpace;
 
-    String8 mPhysicalCameraId;
+    std::string mPhysicalCameraId;
     nsecs_t mLastTimestamp;
 
     bool mIsMultiResolution = false;
diff --git a/services/camera/libcameraservice/device3/Camera3StreamInterface.h b/services/camera/libcameraservice/device3/Camera3StreamInterface.h
index 823be2e..7fa6273 100644
--- a/services/camera/libcameraservice/device3/Camera3StreamInterface.h
+++ b/services/camera/libcameraservice/device3/Camera3StreamInterface.h
@@ -62,7 +62,7 @@
     uint32_t max_buffers;
     android_dataspace_t data_space;
     camera_stream_rotation_t rotation;
-    const char* physical_camera_id;
+    std::string physical_camera_id;
 
     std::unordered_set<int32_t> sensor_pixel_modes_used;
     int64_t dynamic_range_profile;
diff --git a/services/camera/libcameraservice/device3/Camera3StreamSplitter.cpp b/services/camera/libcameraservice/device3/Camera3StreamSplitter.cpp
index fd23958..8175eb5 100644
--- a/services/camera/libcameraservice/device3/Camera3StreamSplitter.cpp
+++ b/services/camera/libcameraservice/device3/Camera3StreamSplitter.cpp
@@ -25,6 +25,7 @@
 #include <gui/IGraphicBufferProducer.h>
 #include <gui/BufferQueue.h>
 #include <gui/Surface.h>
+#include <camera/StringUtils.h>
 
 #include <ui/GraphicBuffer.h>
 
@@ -92,7 +93,7 @@
     if (mBufferItemConsumer == nullptr) {
         return NO_MEMORY;
     }
-    mConsumer->setConsumerName(mConsumerName);
+    mConsumer->setConsumerName(toString8(mConsumerName));
 
     *consumer = new Surface(mProducer);
     if (*consumer == nullptr) {
@@ -408,9 +409,9 @@
     return res;
 }
 
-String8 Camera3StreamSplitter::getUniqueConsumerName() {
+std::string Camera3StreamSplitter::getUniqueConsumerName() {
     static volatile int32_t counter = 0;
-    return String8::format("Camera3StreamSplitter-%d", android_atomic_inc(&counter));
+    return fmt::sprintf("Camera3StreamSplitter-%d", android_atomic_inc(&counter));
 }
 
 status_t Camera3StreamSplitter::notifyBufferReleased(const sp<GraphicBuffer>& buffer) {
diff --git a/services/camera/libcameraservice/device3/Camera3StreamSplitter.h b/services/camera/libcameraservice/device3/Camera3StreamSplitter.h
index 0f728a0..639353c 100644
--- a/services/camera/libcameraservice/device3/Camera3StreamSplitter.h
+++ b/services/camera/libcameraservice/device3/Camera3StreamSplitter.h
@@ -30,10 +30,10 @@
 #include <utils/StrongPointer.h>
 #include <utils/Timers.h>
 
-#define SP_LOGV(x, ...) ALOGV("[%s] " x, mConsumerName.string(), ##__VA_ARGS__)
-#define SP_LOGI(x, ...) ALOGI("[%s] " x, mConsumerName.string(), ##__VA_ARGS__)
-#define SP_LOGW(x, ...) ALOGW("[%s] " x, mConsumerName.string(), ##__VA_ARGS__)
-#define SP_LOGE(x, ...) ALOGE("[%s] " x, mConsumerName.string(), ##__VA_ARGS__)
+#define SP_LOGV(x, ...) ALOGV("[%s] " x, mConsumerName.c_str(), ##__VA_ARGS__)
+#define SP_LOGI(x, ...) ALOGI("[%s] " x, mConsumerName.c_str(), ##__VA_ARGS__)
+#define SP_LOGW(x, ...) ALOGW("[%s] " x, mConsumerName.c_str(), ##__VA_ARGS__)
+#define SP_LOGE(x, ...) ALOGE("[%s] " x, mConsumerName.c_str(), ##__VA_ARGS__)
 
 namespace android {
 
@@ -222,7 +222,7 @@
             const BufferItem& bufferItem, size_t surfaceId);
 
     // Get unique name for the buffer queue consumer
-    String8 getUniqueConsumerName();
+    std::string getUniqueConsumerName();
 
     // Helper function to get the BufferQueue slot where a particular buffer is attached to.
     int getSlotForOutputLocked(const sp<IGraphicBufferProducer>& gbp,
@@ -289,7 +289,7 @@
     // Currently acquired input buffers
     size_t mAcquiredInputBuffers;
 
-    String8 mConsumerName;
+    std::string mConsumerName;
 
     const bool mUseHalBufManager;
 };
diff --git a/services/camera/libcameraservice/device3/InFlightRequest.h b/services/camera/libcameraservice/device3/InFlightRequest.h
index 870825a..665ac73 100644
--- a/services/camera/libcameraservice/device3/InFlightRequest.h
+++ b/services/camera/libcameraservice/device3/InFlightRequest.h
@@ -21,7 +21,6 @@
 
 #include <camera/CaptureResult.h>
 #include <camera/CameraMetadata.h>
-#include <utils/String8.h>
 #include <utils/Timers.h>
 
 #include "common/CameraDeviceBase.h"
@@ -168,7 +167,7 @@
     // For request on a physical camera stream, the inside set contains one Id
     // For request on a stream group containing physical camera streams, the
     // inside set contains all stream Ids in the group.
-    std::set<std::set<String8>> physicalCameraIds;
+    std::set<std::set<std::string>> physicalCameraIds;
 
     // Map of physicalCameraId <-> Metadata
     std::vector<PhysicalCaptureResultInfo> physicalMetadatas;
@@ -224,7 +223,7 @@
 
     InFlightRequest(int numBuffers, CaptureResultExtras extras, bool hasInput,
             bool hasAppCallback, nsecs_t minDuration, nsecs_t maxDuration, bool fixedFps,
-            const std::set<std::set<String8>>& physicalCameraIdSet, bool isStillCapture,
+            const std::set<std::set<std::string>>& physicalCameraIdSet, bool isStillCapture,
             bool isZslCapture, bool rotateAndCropAuto, bool autoframingAuto,
             const std::set<std::string>& idsWithZoom, nsecs_t requestNs,
             const SurfaceMap& outSurfaces = SurfaceMap{}) :
diff --git a/services/camera/libcameraservice/device3/aidl/AidlCamera3Device.cpp b/services/camera/libcameraservice/device3/aidl/AidlCamera3Device.cpp
index aa941b0..af48dd6 100644
--- a/services/camera/libcameraservice/device3/aidl/AidlCamera3Device.cpp
+++ b/services/camera/libcameraservice/device3/aidl/AidlCamera3Device.cpp
@@ -26,10 +26,10 @@
 #endif
 
 // Convenience macro for transient errors
-#define CLOGE(fmt, ...) ALOGE("Camera %s: %s: " fmt, mId.string(), __FUNCTION__, \
+#define CLOGE(fmt, ...) ALOGE("Camera %s: %s: " fmt, mId.c_str(), __FUNCTION__, \
             ##__VA_ARGS__)
 
-#define CLOGW(fmt, ...) ALOGW("Camera %s: %s: " fmt, mId.string(), __FUNCTION__, \
+#define CLOGW(fmt, ...) ALOGW("Camera %s: %s: " fmt, mId.c_str(), __FUNCTION__, \
             ##__VA_ARGS__)
 
 // Convenience macros for transitioning to the error state
@@ -53,6 +53,7 @@
 #include <aidlcommonsupport/NativeHandle.h>
 #include <android/binder_ibinder_platform.h>
 #include <android/hardware/camera2/ICameraDeviceUser.h>
+#include <camera/StringUtils.h>
 
 #include "utils/CameraTraces.h"
 #include "mediautils/SchedulingPolicyService.h"
@@ -164,7 +165,7 @@
 
 AidlCamera3Device::AidlCamera3Device(
         std::shared_ptr<CameraServiceProxyWrapper>& cameraServiceProxyWrapper,
-        const String8& id, bool overrideForPerfClass, bool overrideToPortrait,
+        const std::string& id, bool overrideForPerfClass, bool overrideToPortrait,
         bool legacyClient) :
         Camera3Device(cameraServiceProxyWrapper, id, overrideForPerfClass, overrideToPortrait,
         legacyClient) {
@@ -172,12 +173,12 @@
 }
 
 status_t AidlCamera3Device::initialize(sp<CameraProviderManager> manager,
-        const String8& monitorTags) {
+        const std::string& monitorTags) {
     ATRACE_CALL();
     Mutex::Autolock il(mInterfaceLock);
     Mutex::Autolock l(mLock);
 
-    ALOGV("%s: Initializing AIDL device for camera %s", __FUNCTION__, mId.string());
+    ALOGV("%s: Initializing AIDL device for camera %s", __FUNCTION__, mId.c_str());
     if (mStatus != STATUS_UNINITIALIZED) {
         CLOGE("Already initialized!");
         return INVALID_OPERATION;
@@ -186,7 +187,7 @@
 
     std::shared_ptr<camera::device::ICameraDeviceSession> session;
     ATRACE_BEGIN("CameraHal::openSession");
-    status_t res = manager->openAidlSession(mId.string(), mCallbacks,
+    status_t res = manager->openAidlSession(mId, mCallbacks,
             /*out*/ &session);
     ATRACE_END();
     if (res != OK) {
@@ -197,18 +198,18 @@
       SET_ERR("Session iface returned is null");
       return INVALID_OPERATION;
     }
-    res = manager->getCameraCharacteristics(mId.string(), mOverrideForPerfClass, &mDeviceInfo,
+    res = manager->getCameraCharacteristics(mId, mOverrideForPerfClass, &mDeviceInfo,
             mOverrideToPortrait);
     if (res != OK) {
         SET_ERR_L("Could not retrieve camera characteristics: %s (%d)", strerror(-res), res);
         session->close();
         return res;
     }
-    mSupportNativeZoomRatio = manager->supportNativeZoomRatio(mId.string());
-    mIsCompositeJpegRDisabled = manager->isCompositeJpegRDisabled(mId.string());
+    mSupportNativeZoomRatio = manager->supportNativeZoomRatio(mId);
+    mIsCompositeJpegRDisabled = manager->isCompositeJpegRDisabled(mId);
 
     std::vector<std::string> physicalCameraIds;
-    bool isLogical = manager->isLogicalCamera(mId.string(), &physicalCameraIds);
+    bool isLogical = manager->isLogicalCamera(mId, &physicalCameraIds);
     if (isLogical) {
         for (auto& physicalId : physicalCameraIds) {
             // Do not override characteristics for physical cameras
@@ -299,10 +300,10 @@
     mInterface = new AidlHalInterface(session, queue, mUseHalBufManager, mSupportOfflineProcessing);
 
     std::string providerType;
-    mVendorTagId = manager->getProviderTagIdLocked(mId.string());
+    mVendorTagId = manager->getProviderTagIdLocked(mId);
     mTagMonitor.initialize(mVendorTagId);
-    if (!monitorTags.isEmpty()) {
-        mTagMonitor.parseTagsToMonitor(String8(monitorTags));
+    if (!monitorTags.empty()) {
+        mTagMonitor.parseTagsToMonitor(monitorTags);
     }
 
     for (size_t i = 0; i < capabilities.count; i++) {
@@ -922,7 +923,7 @@
         dst.colorSpace = src->color_space;
 
         dst.bufferSize = bufferSizes[i];
-        if (src->physical_camera_id != nullptr) {
+        if (!src->physical_camera_id.empty()) {
             dst.physicalCameraId = src->physical_camera_id;
         }
         dst.groupId = cam3stream->getHalStreamGroupId();
@@ -1100,7 +1101,7 @@
             mapToAidlDataspace(cam3stream->isDataSpaceOverridden() ?
                     cam3stream->getOriginalDataSpace() : src->data_space);
         dst.bufferSize = bufferSizes[i];
-        if (src->physical_camera_id != nullptr) {
+        if (!src->physical_camera_id.empty()) {
             dst.physicalCameraId = src->physical_camera_id;
         }
         dst.groupId = cam3stream->getHalStreamGroupId();
@@ -1456,7 +1457,7 @@
 }
 
 status_t AidlCamera3Device::AidlCamera3DeviceInjectionMethods::injectionInitialize(
-        const String8& injectedCamId, sp<CameraProviderManager> manager,
+        const std::string& injectedCamId, sp<CameraProviderManager> manager,
         const std::shared_ptr<camera::device::ICameraDeviceCallback>&callback) {
     ATRACE_CALL();
     Mutex::Autolock lock(mInjectionLock);
@@ -1480,7 +1481,7 @@
     mInjectedCamId = injectedCamId;
     std::shared_ptr<camera::device::ICameraInjectionSession> injectionSession;
     ATRACE_BEGIN("Injection CameraHal::openSession");
-    status_t res = manager->openAidlInjectionSession(injectedCamId.string(), callback,
+    status_t res = manager->openAidlInjectionSession(injectedCamId, callback,
                                           /*out*/ &injectionSession);
     ATRACE_END();
     if (res != OK) {
@@ -1579,7 +1580,7 @@
     return OK;
 }
 
-status_t AidlCamera3Device::injectionCameraInitialize(const String8 &injectedCamId,
+status_t AidlCamera3Device::injectionCameraInitialize(const std::string &injectedCamId,
             sp<CameraProviderManager> manager) {
         return (static_cast<AidlCamera3DeviceInjectionMethods *>
                     (mInjectionMethods.get()))->injectionInitialize(injectedCamId, manager,
diff --git a/services/camera/libcameraservice/device3/aidl/AidlCamera3Device.h b/services/camera/libcameraservice/device3/aidl/AidlCamera3Device.h
index 99a308b..e0be367 100644
--- a/services/camera/libcameraservice/device3/aidl/AidlCamera3Device.h
+++ b/services/camera/libcameraservice/device3/aidl/AidlCamera3Device.h
@@ -41,7 +41,7 @@
     friend class AidlCameraDeviceCallbacks;
     explicit AidlCamera3Device(
             std::shared_ptr<CameraServiceProxyWrapper>& cameraServiceProxyWrapper,
-            const String8& id, bool overrideForPerfClass, bool overrideToPortrait,
+            const std::string& id, bool overrideForPerfClass, bool overrideToPortrait,
             bool legacyClient = false);
 
     virtual ~AidlCamera3Device() { }
@@ -71,7 +71,7 @@
     virtual status_t switchToOffline(const std::vector<int32_t>& /*streamsToKeep*/,
             /*out*/ sp<CameraOfflineSessionBase>* /*session*/) override;
 
-    status_t initialize(sp<CameraProviderManager> manager, const String8& monitorTags) override;
+    status_t initialize(sp<CameraProviderManager> manager, const std::string& monitorTags) override;
     class AidlHalInterface : public Camera3Device::HalInterface {
      public:
         AidlHalInterface(std::shared_ptr<
@@ -196,7 +196,7 @@
      public:
         // Initialize the injection camera and generate an hal interface.
         status_t injectionInitialize(
-                const String8& injectedCamId, sp<CameraProviderManager> manager,
+                const std::string& injectedCamId, sp<CameraProviderManager> manager,
                 const std::shared_ptr<
                     aidl::android::hardware::camera::device::ICameraDeviceCallback>&
                     callback);
@@ -257,7 +257,7 @@
     };
 
   private:
-    virtual status_t injectionCameraInitialize(const String8 &injectCamId,
+    virtual status_t injectionCameraInitialize(const std::string &injectCamId,
             sp<CameraProviderManager> manager) override;
 
     virtual sp<RequestThread> createNewRequestThread(wp<Camera3Device> parent,
diff --git a/services/camera/libcameraservice/device3/aidl/AidlCamera3OfflineSession.cpp b/services/camera/libcameraservice/device3/aidl/AidlCamera3OfflineSession.cpp
index 3c3db97..01c4e88 100644
--- a/services/camera/libcameraservice/device3/aidl/AidlCamera3OfflineSession.cpp
+++ b/services/camera/libcameraservice/device3/aidl/AidlCamera3OfflineSession.cpp
@@ -31,6 +31,7 @@
 
 #include <android/hardware/camera2/ICameraDeviceCallbacks.h>
 #include <android/binder_ibinder_platform.h>
+#include <camera/StringUtils.h>
 
 #include "device3/aidl/AidlCamera3OfflineSession.h"
 #include "device3/Camera3OutputStream.h"
@@ -47,7 +48,7 @@
 
 AidlCamera3OfflineSession::~AidlCamera3OfflineSession() {
     ATRACE_CALL();
-    ALOGV("%s: Tearing down aidl offline session for camera id %s", __FUNCTION__, mId.string());
+    ALOGV("%s: Tearing down aidl offline session for camera id %s", __FUNCTION__, mId.c_str());
     Camera3OfflineSession::disconnectImpl();
 }
 
@@ -113,7 +114,7 @@
 
     std::string activePhysicalId(""); // Unused
     AidlCaptureOutputStates states {
-      {mId,
+      { mId,
         mOfflineReqsLock, mLastCompletedRegularFrameNumber,
         mLastCompletedReprocessFrameNumber, mLastCompletedZslFrameNumber,
         mOfflineReqs, mOutputLock, mResultQueue, mResultSignal,
@@ -160,7 +161,7 @@
 
     std::string activePhysicalId(""); // Unused
     AidlCaptureOutputStates states {
-      {mId,
+      { mId,
         mOfflineReqsLock, mLastCompletedRegularFrameNumber,
         mLastCompletedReprocessFrameNumber, mLastCompletedZslFrameNumber,
         mOfflineReqs, mOutputLock, mResultQueue, mResultSignal,
diff --git a/services/camera/libcameraservice/device3/aidl/AidlCamera3OfflineSession.h b/services/camera/libcameraservice/device3/aidl/AidlCamera3OfflineSession.h
index b31ffb7..33b638c 100644
--- a/services/camera/libcameraservice/device3/aidl/AidlCamera3OfflineSession.h
+++ b/services/camera/libcameraservice/device3/aidl/AidlCamera3OfflineSession.h
@@ -20,7 +20,6 @@
 #include <memory>
 #include <mutex>
 
-#include <utils/String8.h>
 #include <utils/String16.h>
 
 #include "AidlCamera3OutputUtils.h"
@@ -106,7 +105,7 @@
     };
 
     // initialize by Camera3Device.
-    explicit AidlCamera3OfflineSession(const String8& id,
+    explicit AidlCamera3OfflineSession(const std::string& id,
             const sp<camera3::Camera3Stream>& inputStream,
             const camera3::StreamSet& offlineStreamSet,
             camera3::BufferRecords&& bufferRecords,
diff --git a/services/camera/libcameraservice/device3/aidl/AidlCamera3OutputUtils.cpp b/services/camera/libcameraservice/device3/aidl/AidlCamera3OutputUtils.cpp
index b2accc1..74d4230 100644
--- a/services/camera/libcameraservice/device3/aidl/AidlCamera3OutputUtils.cpp
+++ b/services/camera/libcameraservice/device3/aidl/AidlCamera3OutputUtils.cpp
@@ -145,7 +145,7 @@
     outBuffers->clear();
     if (!states.useHalBufManager) {
         ALOGE("%s: Camera %s does not support HAL buffer management",
-                __FUNCTION__, states.cameraId.string());
+                __FUNCTION__, states.cameraId.c_str());
         *status = BufferRequestStatus::FAILED_ILLEGAL_ARGUMENTS;
         return;
     }
diff --git a/services/camera/libcameraservice/device3/hidl/HidlCamera3Device.cpp b/services/camera/libcameraservice/device3/hidl/HidlCamera3Device.cpp
index 0d44dd5..06af5ff 100644
--- a/services/camera/libcameraservice/device3/hidl/HidlCamera3Device.cpp
+++ b/services/camera/libcameraservice/device3/hidl/HidlCamera3Device.cpp
@@ -26,7 +26,7 @@
 #endif
 
 // Convenience macro for transient errors
-#define CLOGE(fmt, ...) ALOGE("Camera %s: %s: " fmt, mId.string(), __FUNCTION__, \
+#define CLOGE(fmt, ...) ALOGE("Camera %s: %s: " fmt, mId.c_str(), __FUNCTION__, \
             ##__VA_ARGS__)
 
 // Convenience macros for transitioning to the error state
@@ -46,6 +46,7 @@
 #include <utils/Trace.h>
 #include <utils/Timers.h>
 #include <cutils/properties.h>
+#include <camera/StringUtils.h>
 
 #include <android/hardware/camera/device/3.7/ICameraInjectionSession.h>
 #include <android/hardware/camera2/ICameraDeviceUser.h>
@@ -140,12 +141,12 @@
 }
 
 status_t HidlCamera3Device::initialize(sp<CameraProviderManager> manager,
-        const String8& monitorTags) {
+        const std::string& monitorTags) {
     ATRACE_CALL();
     Mutex::Autolock il(mInterfaceLock);
     Mutex::Autolock l(mLock);
 
-    ALOGV("%s: Initializing HIDL device for camera %s", __FUNCTION__, mId.string());
+    ALOGV("%s: Initializing HIDL device for camera %s", __FUNCTION__, mId.c_str());
     if (mStatus != STATUS_UNINITIALIZED) {
         CLOGE("Already initialized!");
         return INVALID_OPERATION;
@@ -154,7 +155,7 @@
 
     sp<ICameraDeviceSession> session;
     ATRACE_BEGIN("CameraHal::openSession");
-    status_t res = manager->openHidlSession(mId.string(), this,
+    status_t res = manager->openHidlSession(mId, this,
             /*out*/ &session);
     ATRACE_END();
     if (res != OK) {
@@ -162,17 +163,17 @@
         return res;
     }
 
-    res = manager->getCameraCharacteristics(mId.string(), mOverrideForPerfClass, &mDeviceInfo,
+    res = manager->getCameraCharacteristics(mId, mOverrideForPerfClass, &mDeviceInfo,
             /*overrideToPortrait*/false);
     if (res != OK) {
         SET_ERR_L("Could not retrieve camera characteristics: %s (%d)", strerror(-res), res);
         session->close();
         return res;
     }
-    mSupportNativeZoomRatio = manager->supportNativeZoomRatio(mId.string());
+    mSupportNativeZoomRatio = manager->supportNativeZoomRatio(mId);
 
     std::vector<std::string> physicalCameraIds;
-    bool isLogical = manager->isLogicalCamera(mId.string(), &physicalCameraIds);
+    bool isLogical = manager->isLogicalCamera(mId, &physicalCameraIds);
     if (isLogical) {
         for (auto& physicalId : physicalCameraIds) {
             // Do not override characteristics for physical cameras
@@ -271,17 +272,17 @@
     mInterface = new HidlHalInterface(session, queue, mUseHalBufManager, mSupportOfflineProcessing);
 
     std::string providerType;
-    mVendorTagId = manager->getProviderTagIdLocked(mId.string());
+    mVendorTagId = manager->getProviderTagIdLocked(mId);
     mTagMonitor.initialize(mVendorTagId);
-    if (!monitorTags.isEmpty()) {
-        mTagMonitor.parseTagsToMonitor(String8(monitorTags));
+    if (!monitorTags.empty()) {
+        mTagMonitor.parseTagsToMonitor(monitorTags);
     }
 
     // Metadata tags needs fixup for monochrome camera device version less
     // than 3.5.
     hardware::hidl_version maxVersion{0,0};
     IPCTransport transport = IPCTransport::HIDL;
-    res = manager->getHighestSupportedVersion(mId.string(), &maxVersion, &transport);
+    res = manager->getHighestSupportedVersion(mId, &maxVersion, &transport);
     if (res != OK) {
         ALOGE("%s: Error in getting camera device version id: %s (%d)",
                 __FUNCTION__, strerror(-res), res);
@@ -416,7 +417,7 @@
     }
 
     HidlCaptureOutputStates states {
-      {mId,
+      { mId,
         mInFlightLock, mLastCompletedRegularFrameNumber,
         mLastCompletedReprocessFrameNumber, mLastCompletedZslFrameNumber,
         mInFlightMap, mOutputLock,  mResultQueue, mResultSignal,
@@ -464,7 +465,7 @@
     }
 
     HidlCaptureOutputStates states {
-      {mId,
+      { mId,
         mInFlightLock, mLastCompletedRegularFrameNumber,
         mLastCompletedReprocessFrameNumber, mLastCompletedZslFrameNumber,
         mInFlightMap, mOutputLock,  mResultQueue, mResultSignal,
@@ -715,7 +716,7 @@
     return new HidlCamera3DeviceInjectionMethods(parent);
 }
 
-status_t HidlCamera3Device::injectionCameraInitialize(const String8 &injectedCamId,
+status_t HidlCamera3Device::injectionCameraInitialize(const std::string &injectedCamId,
             sp<CameraProviderManager> manager) {
         return (static_cast<HidlCamera3DeviceInjectionMethods *>(
                 mInjectionMethods.get()))->injectionInitialize(injectedCamId, manager, this);
@@ -941,7 +942,7 @@
         }
         dst3_4.v3_2 = dst3_2;
         dst3_4.bufferSize = bufferSizes[i];
-        if (src->physical_camera_id != nullptr) {
+        if (!src->physical_camera_id.empty()) {
             dst3_4.physicalCameraId = src->physical_camera_id;
         }
         dst3_7.v3_4 = dst3_4;
@@ -1259,7 +1260,7 @@
         }
         dst3_4.v3_2 = dst3_2;
         dst3_4.bufferSize = bufferSizes[i];
-        if (src->physical_camera_id != nullptr) {
+        if (!src->physical_camera_id.empty()) {
             dst3_4.physicalCameraId = src->physical_camera_id;
         }
         dst3_7.v3_4 = dst3_4;
@@ -1739,7 +1740,7 @@
 }
 
 status_t HidlCamera3Device::HidlCamera3DeviceInjectionMethods::injectionInitialize(
-        const String8& injectedCamId, sp<CameraProviderManager> manager,
+        const std::string& injectedCamId, sp<CameraProviderManager> manager,
         const sp<android::hardware::camera::device::V3_2::ICameraDeviceCallback>&
                 callback) {
     ATRACE_CALL();
@@ -1759,7 +1760,7 @@
     mInjectedCamId = injectedCamId;
     sp<ICameraDeviceSession> session;
     ATRACE_BEGIN("Injection CameraHal::openSession");
-    status_t res = manager->openHidlSession(injectedCamId.string(), callback,
+    status_t res = manager->openHidlSession(injectedCamId, callback,
                                           /*out*/ &session);
     ATRACE_END();
     if (res != OK) {
diff --git a/services/camera/libcameraservice/device3/hidl/HidlCamera3Device.h b/services/camera/libcameraservice/device3/hidl/HidlCamera3Device.h
index 1e50844..2cfdf9d 100644
--- a/services/camera/libcameraservice/device3/hidl/HidlCamera3Device.h
+++ b/services/camera/libcameraservice/device3/hidl/HidlCamera3Device.h
@@ -31,8 +31,9 @@
             public Camera3Device {
   public:
 
-   explicit HidlCamera3Device(std::shared_ptr<CameraServiceProxyWrapper>& cameraServiceProxyWrapper,
-        const String8& id, bool overrideForPerfClass, bool overrideToPortrait,
+    explicit HidlCamera3Device(
+        std::shared_ptr<CameraServiceProxyWrapper>& cameraServiceProxyWrapper,
+        const std::string& id, bool overrideForPerfClass, bool overrideToPortrait,
         bool legacyClient = false) :
         Camera3Device(cameraServiceProxyWrapper, id, overrideForPerfClass, overrideToPortrait,
                 legacyClient) { }
@@ -59,7 +60,7 @@
     static uint64_t mapProducerToFrameworkUsage(
             hardware::camera::device::V3_2::BufferUsageFlags usage);
 
-    status_t initialize(sp<CameraProviderManager> manager, const String8& monitorTags) override;
+    status_t initialize(sp<CameraProviderManager> manager, const std::string& monitorTags) override;
 
     /**
      * Implementation of android::hardware::camera::device::V3_5::ICameraDeviceCallback
@@ -191,7 +192,7 @@
      public:
         // Initialize the injection camera and generate an hal interface.
         status_t injectionInitialize(
-                const String8& injectedCamId, sp<CameraProviderManager> manager,
+                const std::string& injectedCamId, sp<CameraProviderManager> manager,
                 const sp<
                     android::hardware::camera::device::V3_2 ::ICameraDeviceCallback>&
                     callback);
@@ -217,7 +218,7 @@
     hardware::Return<void> notifyHelper(
             const hardware::hidl_vec<NotifyMsgType>& msgs);
 
-    virtual status_t injectionCameraInitialize(const String8 &injectCamId,
+    virtual status_t injectionCameraInitialize(const std::string &injectCamId,
             sp<CameraProviderManager> manager) override;
 
     virtual sp<RequestThread> createNewRequestThread(wp<Camera3Device> parent,
diff --git a/services/camera/libcameraservice/device3/hidl/HidlCamera3OfflineSession.cpp b/services/camera/libcameraservice/device3/hidl/HidlCamera3OfflineSession.cpp
index 28b2b47..e328ef6 100644
--- a/services/camera/libcameraservice/device3/hidl/HidlCamera3OfflineSession.cpp
+++ b/services/camera/libcameraservice/device3/hidl/HidlCamera3OfflineSession.cpp
@@ -23,6 +23,7 @@
 #include <utils/Trace.h>
 
 #include <android/hardware/camera2/ICameraDeviceCallbacks.h>
+#include <camera/StringUtils.h>
 
 #include "device3/hidl/HidlCamera3OfflineSession.h"
 #include "device3/Camera3OutputStream.h"
@@ -38,7 +39,7 @@
 
 HidlCamera3OfflineSession::~HidlCamera3OfflineSession() {
     ATRACE_CALL();
-    ALOGV("%s: Tearing down hidl offline session for camera id %s", __FUNCTION__, mId.string());
+    ALOGV("%s: Tearing down hidl offline session for camera id %s", __FUNCTION__, mId.c_str());
     Camera3OfflineSession::disconnectImpl();
 }
 
@@ -94,7 +95,7 @@
 
     std::string activePhysicalId("");
     HidlCaptureOutputStates states {
-      {mId,
+      { mId,
         mOfflineReqsLock, mLastCompletedRegularFrameNumber,
         mLastCompletedReprocessFrameNumber, mLastCompletedZslFrameNumber,
         mOfflineReqs, mOutputLock, mResultQueue, mResultSignal,
@@ -136,7 +137,7 @@
 
     std::string activePhysicalId("");
     HidlCaptureOutputStates states {
-      {mId,
+      { mId,
         mOfflineReqsLock, mLastCompletedRegularFrameNumber,
         mLastCompletedReprocessFrameNumber, mLastCompletedZslFrameNumber,
         mOfflineReqs, mOutputLock, mResultQueue, mResultSignal,
@@ -173,7 +174,7 @@
 
     std::string activePhysicalId("");
     HidlCaptureOutputStates states {
-      {mId,
+      { mId,
         mOfflineReqsLock, mLastCompletedRegularFrameNumber,
         mLastCompletedReprocessFrameNumber, mLastCompletedZslFrameNumber,
         mOfflineReqs, mOutputLock, mResultQueue, mResultSignal,
diff --git a/services/camera/libcameraservice/device3/hidl/HidlCamera3OfflineSession.h b/services/camera/libcameraservice/device3/hidl/HidlCamera3OfflineSession.h
index d22a447..df306b2 100644
--- a/services/camera/libcameraservice/device3/hidl/HidlCamera3OfflineSession.h
+++ b/services/camera/libcameraservice/device3/hidl/HidlCamera3OfflineSession.h
@@ -20,7 +20,6 @@
 #include <memory>
 #include <mutex>
 
-#include <utils/String8.h>
 #include <utils/String16.h>
 
 #include <android/hardware/camera/device/3.6/ICameraOfflineSession.h>
@@ -53,7 +52,7 @@
   public:
 
     // initialize by Camera3Device.
-    explicit HidlCamera3OfflineSession(const String8& id,
+    explicit HidlCamera3OfflineSession(const std::string& id,
             const sp<camera3::Camera3Stream>& inputStream,
             const camera3::StreamSet& offlineStreamSet,
             camera3::BufferRecords&& bufferRecords,
diff --git a/services/camera/libcameraservice/gui/RingBufferConsumer.cpp b/services/camera/libcameraservice/gui/RingBufferConsumer.cpp
index ee018c3..cd4a92c 100644
--- a/services/camera/libcameraservice/gui/RingBufferConsumer.cpp
+++ b/services/camera/libcameraservice/gui/RingBufferConsumer.cpp
@@ -23,6 +23,7 @@
 #include <utils/Log.h>
 
 #include <gui/RingBufferConsumer.h>
+#include <camera/StringUtils.h>
 
 #define BI_LOGV(x, ...) ALOGV("[%s] " x, mName.string(), ##__VA_ARGS__)
 #define BI_LOGD(x, ...) ALOGD("[%s] " x, mName.string(), ##__VA_ARGS__)
@@ -53,10 +54,10 @@
 RingBufferConsumer::~RingBufferConsumer() {
 }
 
-void RingBufferConsumer::setName(const String8& name) {
+void RingBufferConsumer::setName(const std::string& name) {
     Mutex::Autolock _l(mMutex);
-    mName = name;
-    mConsumer->setConsumerName(name);
+    mName = toString8(name);
+    mConsumer->setConsumerName(mName);
 }
 
 sp<PinnedBufferItem> RingBufferConsumer::pinSelectedBuffer(
diff --git a/services/camera/libcameraservice/gui/RingBufferConsumer.h b/services/camera/libcameraservice/gui/RingBufferConsumer.h
index b737469..2e523d1 100644
--- a/services/camera/libcameraservice/gui/RingBufferConsumer.h
+++ b/services/camera/libcameraservice/gui/RingBufferConsumer.h
@@ -27,8 +27,6 @@
 
 namespace android {
 
-class String8;
-
 /**
  * The RingBufferConsumer maintains a ring buffer of BufferItem objects,
  * (which are 'acquired' as long as they are part of the ring buffer, and
@@ -67,7 +65,7 @@
 
     // set the name of the RingBufferConsumer that will be used to identify it in
     // log messages.
-    void setName(const String8& name);
+    void setName(const std::string& name);
 
     // setDefaultBufferSize is used to set the size of buffers returned by
     // requestBuffers when a with and height of zero is requested.
diff --git a/services/camera/libcameraservice/hidl/AidlCameraServiceListener.cpp b/services/camera/libcameraservice/hidl/AidlCameraServiceListener.cpp
index add9121..2b81224 100644
--- a/services/camera/libcameraservice/hidl/AidlCameraServiceListener.cpp
+++ b/services/camera/libcameraservice/hidl/AidlCameraServiceListener.cpp
@@ -16,6 +16,7 @@
 
 #include <hidl/AidlCameraServiceListener.h>
 #include <hidl/Utils.h>
+#include <camera/StringUtils.h>
 
 namespace android {
 namespace frameworks {
@@ -28,11 +29,11 @@
 typedef frameworks::cameraservice::service::V2_1::ICameraServiceListener HCameraServiceListener2_1;
 
 binder::Status H2BCameraServiceListener::onStatusChanged(
-    int32_t status, const ::android::String16& cameraId) {
+    int32_t status, const std::string& cameraId) {
   HCameraDeviceStatus hCameraDeviceStatus = convertToHidlCameraDeviceStatus(status);
   CameraStatusAndId cameraStatusAndId;
   cameraStatusAndId.deviceStatus = hCameraDeviceStatus;
-  cameraStatusAndId.cameraId = String8(cameraId).string();
+  cameraStatusAndId.cameraId = cameraId;
   auto ret = mBase->onStatusChanged(cameraStatusAndId);
   if (!ret.isOk()) {
       ALOGE("%s OnStatusChanged callback failed due to %s",__FUNCTION__,
@@ -42,8 +43,8 @@
 }
 
 binder::Status H2BCameraServiceListener::onPhysicalCameraStatusChanged(
-    int32_t status, const ::android::String16& cameraId,
-    const ::android::String16& physicalCameraId) {
+    int32_t status, const std::string& cameraId,
+    const std::string& physicalCameraId) {
   auto cast2_1 = HCameraServiceListener2_1::castFrom(mBase);
   sp<HCameraServiceListener2_1> interface2_1 = nullptr;
   if (cast2_1.isOk()) {
@@ -52,8 +53,8 @@
       HCameraDeviceStatus hCameraDeviceStatus = convertToHidlCameraDeviceStatus(status);
       V2_1::PhysicalCameraStatusAndId cameraStatusAndId;
       cameraStatusAndId.deviceStatus = hCameraDeviceStatus;
-      cameraStatusAndId.cameraId = String8(cameraId).string();
-      cameraStatusAndId.physicalCameraId = String8(physicalCameraId).string();
+      cameraStatusAndId.cameraId = cameraId;
+      cameraStatusAndId.physicalCameraId = physicalCameraId;
       auto ret = interface2_1->onPhysicalCameraStatusChanged(cameraStatusAndId);
       if (!ret.isOk()) {
         ALOGE("%s OnPhysicalCameraStatusChanged callback failed due to %s",__FUNCTION__,
@@ -65,13 +66,13 @@
 }
 
 ::android::binder::Status H2BCameraServiceListener::onTorchStatusChanged(
-    int32_t, const ::android::String16&) {
+    int32_t, const std::string&) {
   // We don't implement onTorchStatusChanged
   return binder::Status::ok();
 }
 
 ::android::binder::Status H2BCameraServiceListener::onTorchStrengthLevelChanged(
-    const ::android::String16&, int32_t) {
+    const std::string&, int32_t) {
   return binder::Status::ok();
 }
 
diff --git a/services/camera/libcameraservice/hidl/AidlCameraServiceListener.h b/services/camera/libcameraservice/hidl/AidlCameraServiceListener.h
index 7ef413f..91a4c16 100644
--- a/services/camera/libcameraservice/hidl/AidlCameraServiceListener.h
+++ b/services/camera/libcameraservice/hidl/AidlCameraServiceListener.h
@@ -47,25 +47,25 @@
     ~H2BCameraServiceListener() { }
 
     virtual ::android::binder::Status onStatusChanged(int32_t status,
-            const ::android::String16& cameraId) override;
+            const std::string& cameraId) override;
     virtual ::android::binder::Status onPhysicalCameraStatusChanged(int32_t status,
-            const ::android::String16& cameraId,
-            const ::android::String16& physicalCameraId) override;
+            const std::string& cameraId,
+            const std::string& physicalCameraId) override;
 
     virtual ::android::binder::Status onTorchStatusChanged(
-            int32_t status, const ::android::String16& cameraId) override;
+            int32_t status, const std::string& cameraId) override;
     virtual ::android::binder::Status onTorchStrengthLevelChanged(
-            const ::android::String16& cameraId, int32_t newStrengthLevel) override;
+            const std::string& cameraId, int32_t newStrengthLevel) override;
     virtual binder::Status onCameraAccessPrioritiesChanged() {
         // TODO: no implementation yet.
         return binder::Status::ok();
     }
-    virtual binder::Status onCameraOpened(const ::android::String16& /*cameraId*/,
-            const ::android::String16& /*clientPackageId*/) {
+    virtual binder::Status onCameraOpened(const std::string& /*cameraId*/,
+            const std::string& /*clientPackageId*/) {
         // empty implementation
         return binder::Status::ok();
     }
-    virtual binder::Status onCameraClosed(const ::android::String16& /*cameraId*/) {
+    virtual binder::Status onCameraClosed(const std::string& /*cameraId*/) {
         // empty implementation
         return binder::Status::ok();
     }
diff --git a/services/camera/libcameraservice/hidl/HidlCameraDeviceUser.cpp b/services/camera/libcameraservice/hidl/HidlCameraDeviceUser.cpp
index 0f7f127..59fc1cd 100644
--- a/services/camera/libcameraservice/hidl/HidlCameraDeviceUser.cpp
+++ b/services/camera/libcameraservice/hidl/HidlCameraDeviceUser.cpp
@@ -112,7 +112,7 @@
         physicalCameraSettings->emplace_back();
         CaptureRequest::PhysicalCameraSettings &physicalCameraSetting =
             physicalCameraSettings->back();
-        physicalCameraSetting.id = e.id.c_str();
+        physicalCameraSetting.id = e.id;
 
         // Read the settings either from the fmq or straightaway from the
         // request. We don't need any synchronization, since submitRequestList
diff --git a/services/camera/libcameraservice/hidl/HidlCameraService.cpp b/services/camera/libcameraservice/hidl/HidlCameraService.cpp
index d6910fe..4f12933 100644
--- a/services/camera/libcameraservice/hidl/HidlCameraService.cpp
+++ b/services/camera/libcameraservice/hidl/HidlCameraService.cpp
@@ -65,7 +65,7 @@
     android::CameraMetadata cameraMetadata;
     HStatus status = HStatus::NO_ERROR;
     binder::Status serviceRet =
-        mAidlICameraService->getCameraCharacteristics(String16(cameraId.c_str()),
+        mAidlICameraService->getCameraCharacteristics(cameraId,
                 /*targetSdkVersion*/__ANDROID_API_FUTURE__, /*overrideToPortrait*/false,
                 &cameraMetadata);
     HCameraMetadata hidlMetadata;
@@ -116,7 +116,7 @@
     }
     sp<hardware::camera2::ICameraDeviceCallbacks> callbacks = hybridCallbacks;
     binder::Status serviceRet = mAidlICameraService->connectDevice(
-            callbacks, String16(cameraId.c_str()), String16(""), {},
+            callbacks, cameraId, std::string(), {},
             hardware::ICameraService::USE_CALLING_UID, 0/*oomScoreOffset*/,
             /*targetSdkVersion*/__ANDROID_API_FUTURE__, /*overrideToPortrait*/false,
             /*out*/&deviceRemote);
@@ -242,7 +242,7 @@
             [this](const hardware::CameraStatus& s) {
                 bool supportsHAL3 = false;
                 binder::Status sRet =
-                            mAidlICameraService->supportsCameraApi(String16(s.cameraId),
+                            mAidlICameraService->supportsCameraApi(s.cameraId,
                                     hardware::ICameraService::API_VERSION_2, &supportsHAL3);
                 return !sRet.isOk() || !supportsHAL3;
             }), cameraStatusAndIds->end());
diff --git a/services/camera/libcameraservice/hidl/Utils.cpp b/services/camera/libcameraservice/hidl/Utils.cpp
index 2a24a23..b5dddf7 100644
--- a/services/camera/libcameraservice/hidl/Utils.cpp
+++ b/services/camera/libcameraservice/hidl/Utils.cpp
@@ -18,6 +18,7 @@
 #include <gui/bufferqueue/1.0/H2BGraphicBufferProducer.h>
 #include <cutils/native_handle.h>
 #include <mediautils/AImageReaderUtils.h>
+#include <camera/StringUtils.h>
 
 namespace android {
 namespace hardware {
@@ -89,9 +90,9 @@
     for (auto &handle : windowHandles) {
         iGBPs.push_back(new H2BGraphicBufferProducer(AImageReader_getHGBPFromHandle(handle)));
     }
-    String16 physicalCameraId16(hOutputConfiguration.physicalCameraId.c_str());
     hardware::camera2::params::OutputConfiguration outputConfiguration(
-        iGBPs, convertFromHidl(hOutputConfiguration.rotation), physicalCameraId16,
+        iGBPs, convertFromHidl(hOutputConfiguration.rotation),
+        hOutputConfiguration.physicalCameraId,
         hOutputConfiguration.windowGroupId, OutputConfiguration::SURFACE_TYPE_UNKNOWN, 0, 0,
         (windowHandles.size() > 1));
     return outputConfiguration;
@@ -157,8 +158,8 @@
     hCaptureResultExtras.frameNumber = captureResultExtras.frameNumber;
     hCaptureResultExtras.partialResultCount = captureResultExtras.partialResultCount;
     hCaptureResultExtras.errorStreamId = captureResultExtras.errorStreamId;
-    hCaptureResultExtras.errorPhysicalCameraId = hidl_string(String8(
-            captureResultExtras.errorPhysicalCameraId).string());
+    hCaptureResultExtras.errorPhysicalCameraId = hidl_string(
+            captureResultExtras.errorPhysicalCameraId.c_str());
     return hCaptureResultExtras;
 }
 
@@ -191,7 +192,7 @@
     size_t i = 0;
     for (auto &statusAndId : src) {
         auto &a = (*dst)[i++];
-        a.cameraId = statusAndId.cameraId.c_str();
+        a.cameraId = statusAndId.cameraId;
         a.deviceStatus = convertToHidlCameraDeviceStatus(statusAndId.status);
     }
     return;
@@ -203,12 +204,12 @@
     size_t i = 0;
     for (const auto &statusAndId : src) {
         auto &a = (*dst)[i++];
-        a.v2_0.cameraId = statusAndId.cameraId.c_str();
+        a.v2_0.cameraId = statusAndId.cameraId;
         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();
+            a.unavailPhysicalCameraIds[j] = statusAndId.unavailablePhysicalIds[j];
         }
     }
     return;
@@ -265,7 +266,7 @@
     std::shared_ptr<CaptureResultMetadataQueue> &captureResultMetadataQueue) {
     HPhysicalCaptureResultInfo hPhysicalCaptureResultInfo;
     hPhysicalCaptureResultInfo.physicalCameraId =
-        String8(physicalCaptureResultInfo.mPhysicalCameraId).string();
+        toString8(physicalCaptureResultInfo.mPhysicalCameraId);
     const camera_metadata_t *rawMetadata =
         physicalCaptureResultInfo.mPhysicalCameraMetadata.getAndLock();
     // Try using fmq at first.
diff --git a/services/camera/libcameraservice/libcameraservice_fuzzer/camera_service_fuzzer.cpp b/services/camera/libcameraservice/libcameraservice_fuzzer/camera_service_fuzzer.cpp
index b397573..854c342 100644
--- a/services/camera/libcameraservice/libcameraservice_fuzzer/camera_service_fuzzer.cpp
+++ b/services/camera/libcameraservice/libcameraservice_fuzzer/camera_service_fuzzer.cpp
@@ -219,13 +219,13 @@
 }
 
 void CameraFuzzer::getCameraInformation(int32_t cameraId) {
-    String16 cameraIdStr = String16(String8::format("%d", cameraId));
+    std::string cameraIdStr = std::to_string(cameraId);
     bool isSupported = false;
     mCameraService->supportsCameraApi(
         cameraIdStr, kCameraApiVersion[mFuzzedDataProvider->ConsumeBool()], &isSupported);
     mCameraService->isHiddenPhysicalCamera(cameraIdStr, &isSupported);
 
-    String16 parameters;
+    std::string parameters;
     mCameraService->getLegacyParameters(cameraId, &parameters);
 
     std::vector<hardware::camera2::utils::ConcurrentCameraIdCombination> concurrentCameraIds;
@@ -318,7 +318,7 @@
 }
 
 void CameraFuzzer::invokeTorchAPIs(int32_t cameraId) {
-    String16 cameraIdStr = String16(String8::format("%d", cameraId));
+    std::string cameraIdStr = std::to_string(cameraId);
     sp<IBinder> binder = new BBinder;
 
     mCameraService->setTorchMode(cameraIdStr, true, binder);
@@ -342,7 +342,7 @@
     ::android::binder::Status rc;
     sp<ICamera> cameraDevice;
 
-    rc = mCameraService->connect(this, cameraId, String16(),
+    rc = mCameraService->connect(this, cameraId, std::string(),
                                  android::CameraService::USE_CALLING_UID,
                                  android::CameraService::USE_CALLING_PID,
                                  /*targetSdkVersion*/ __ANDROID_API_FUTURE__,
@@ -484,17 +484,18 @@
 public:
     virtual ~TestCameraServiceListener() {};
 
-    virtual binder::Status onStatusChanged(int32_t , const String16&) {
+    virtual binder::Status onStatusChanged(int32_t, const std::string&) {
         return binder::Status::ok();
     };
 
     virtual binder::Status onPhysicalCameraStatusChanged(int32_t /*status*/,
-            const String16& /*cameraId*/, const String16& /*physicalCameraId*/) {
+            const std::string& /*cameraId*/, const std::string& /*physicalCameraId*/) {
         // No op
         return binder::Status::ok();
     };
 
-    virtual binder::Status onTorchStatusChanged(int32_t /*status*/, const String16& /*cameraId*/) {
+    virtual binder::Status onTorchStatusChanged(int32_t /*status*/,
+            const std::string& /*cameraId*/) {
         return binder::Status::ok();
     };
 
@@ -503,18 +504,18 @@
         return binder::Status::ok();
     }
 
-    virtual binder::Status onCameraOpened(const String16& /*cameraId*/,
-            const String16& /*clientPackageName*/) {
+    virtual binder::Status onCameraOpened(const std::string& /*cameraId*/,
+            const std::string& /*clientPackageName*/) {
         // No op
         return binder::Status::ok();
     }
 
-    virtual binder::Status onCameraClosed(const String16& /*cameraId*/) {
+    virtual binder::Status onCameraClosed(const std::string& /*cameraId*/) {
         // No op
         return binder::Status::ok();
     }
 
-    virtual binder::Status onTorchStrengthLevelChanged(const String16& /*cameraId*/,
+    virtual binder::Status onTorchStrengthLevelChanged(const std::string& /*cameraId*/,
             int32_t /*torchStrength*/) {
         // No op
         return binder::Status::ok();
@@ -579,7 +580,7 @@
     for (auto s : statuses) {
         sp<TestCameraDeviceCallbacks> callbacks(new TestCameraDeviceCallbacks());
         sp<hardware::camera2::ICameraDeviceUser> device;
-        mCameraService->connectDevice(callbacks, String16(s.cameraId), String16(), {},
+        mCameraService->connectDevice(callbacks, s.cameraId, std::string(), {},
                 android::CameraService::USE_CALLING_UID, 0/*oomScoreDiff*/,
                 /*targetSdkVersion*/__ANDROID_API_FUTURE__, /*overrideToPortrait*/true,
                 &device);
@@ -600,7 +601,7 @@
 
         sp<Surface> surface(new Surface(gbProducer, /*controlledByApp*/false));
 
-        String16 noPhysicalId;
+        std::string noPhysicalId;
         size_t rotations = sizeof(kRotations) / sizeof(int32_t) - 1;
         OutputConfiguration output(gbProducer,
                 kRotations[mFuzzedDataProvider->ConsumeIntegralInRange<size_t>(0, rotations)],
@@ -626,9 +627,9 @@
                     kSensorPixelModes[mFuzzedDataProvider->ConsumeBool() ? 1 : 0];
             requestTemplate.update(ANDROID_SENSOR_PIXEL_MODE, &sensorPixelMode, 1);
             request.mPhysicalCameraSettings.clear();
-            request.mPhysicalCameraSettings.push_back({s.cameraId.string(), requestTemplate});
+            request.mPhysicalCameraSettings.push_back({s.cameraId, requestTemplate});
             device->submitRequest(request, /*streaming*/false, /*out*/&info);
-            ALOGV("%s : camera id %s submit request id %d",__FUNCTION__, s.cameraId.string(),
+            ALOGV("%s : camera id %s submit request id %d",__FUNCTION__, s.cameraId.c_str(),
                     info.mRequestId);
         }
         device->disconnect();
diff --git a/services/camera/libcameraservice/tests/Android.bp b/services/camera/libcameraservice/tests/Android.bp
index 5e2a3fb..b035edd 100644
--- a/services/camera/libcameraservice/tests/Android.bp
+++ b/services/camera/libcameraservice/tests/Android.bp
@@ -31,11 +31,14 @@
         "libmedia_headers",
     ],
 
+    defaults: [
+        "libcameraservice_deps",
+    ],
+
     shared_libs: [
         "libbase",
         "libbinder",
         "libcutils",
-        "libcameraservice",
         "libhidlbase",
         "liblog",
         "libcamera_client",
@@ -45,11 +48,6 @@
         "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.provider@2.7",
-        "android.hardware.camera.provider-V2-ndk",
         "android.hardware.camera.device@1.0",
         "android.hardware.camera.device@3.2",
         "android.hardware.camera.device@3.4",
@@ -58,6 +56,12 @@
     ],
 
     static_libs: [
+        "android.hardware.camera.provider@2.4",
+        "android.hardware.camera.provider@2.5",
+        "android.hardware.camera.provider@2.6",
+        "android.hardware.camera.provider@2.7",
+        "android.hardware.camera.provider-V2-ndk",
+        "libcameraservice",
         "libgmock",
     ],
 
diff --git a/services/camera/libcameraservice/tests/CameraPermissionsTest.cpp b/services/camera/libcameraservice/tests/CameraPermissionsTest.cpp
index 731eebf..db43a02 100644
--- a/services/camera/libcameraservice/tests/CameraPermissionsTest.cpp
+++ b/services/camera/libcameraservice/tests/CameraPermissionsTest.cpp
@@ -37,17 +37,18 @@
 public:
     virtual ~TestCameraServiceListener() {};
 
-    virtual binder::Status onStatusChanged(int32_t , const String16&) {
+    virtual binder::Status onStatusChanged(int32_t , const std::string&) {
         return binder::Status::ok();
     };
 
     virtual binder::Status onPhysicalCameraStatusChanged(int32_t /*status*/,
-            const String16& /*cameraId*/, const String16& /*physicalCameraId*/) {
+            const std::string& /*cameraId*/, const std::string& /*physicalCameraId*/) {
         // No op
         return binder::Status::ok();
     };
 
-    virtual binder::Status onTorchStatusChanged(int32_t /*status*/, const String16& /*cameraId*/) {
+    virtual binder::Status onTorchStatusChanged(int32_t /*status*/,
+            const std::string& /*cameraId*/) {
         return binder::Status::ok();
     };
 
@@ -56,18 +57,18 @@
         return binder::Status::ok();
     }
 
-    virtual binder::Status onCameraOpened(const String16& /*cameraId*/,
-            const String16& /*clientPackageName*/) {
+    virtual binder::Status onCameraOpened(const std::string& /*cameraId*/,
+            const std::string& /*clientPackageName*/) {
         // No op
         return binder::Status::ok();
     }
 
-    virtual binder::Status onCameraClosed(const String16& /*cameraId*/) {
+    virtual binder::Status onCameraClosed(const std::string& /*cameraId*/) {
         // No op
         return binder::Status::ok();
     }
 
-    virtual binder::Status onTorchStrengthLevelChanged(const String16& /*cameraId*/,
+    virtual binder::Status onTorchStrengthLevelChanged(const std::string& /*cameraId*/,
             int32_t /*torchStrength*/) {
         // No op
         return binder::Status::ok();
@@ -123,13 +124,13 @@
             mCameraDisabled(false), mOverrideCameraDisabled(false)
     { }
 
-    virtual binder::Status getRotateAndCropOverride(const String16& packageName, int lensFacing,
+    virtual binder::Status getRotateAndCropOverride(const std::string& packageName, int lensFacing,
             int userId, int *ret) override {
         return mCameraServiceProxy->getRotateAndCropOverride(packageName, lensFacing,
                 userId, ret);
     }
 
-    virtual binder::Status getAutoframingOverride(const String16& packageName, int *ret) override {
+    virtual binder::Status getAutoframingOverride(const std::string& packageName, int *ret) override {
         return mCameraServiceProxy->getAutoframingOverride(packageName, ret);
     }
 
@@ -224,7 +225,7 @@
         sp<TestCameraDeviceCallbacks> callbacks = new TestCameraDeviceCallbacks();
         sp<hardware::camera2::ICameraDeviceUser> device;
         binder::Status status =
-                sCameraService->connectDevice(callbacks, String16(s.cameraId), String16(), {},
+                sCameraService->connectDevice(callbacks, s.cameraId, std::string(), {},
                 android::CameraService::USE_CALLING_UID, 0/*oomScoreDiff*/,
                 /*targetSdkVersion*/__ANDROID_API_FUTURE__, /*overrideToPortrait*/false, &device);
         AutoDisconnectDevice autoDisconnect(device);
@@ -238,7 +239,7 @@
         sp<TestCameraDeviceCallbacks> callbacks = new TestCameraDeviceCallbacks();
         sp<hardware::camera2::ICameraDeviceUser> device;
         binder::Status status =
-                sCameraService->connectDevice(callbacks, String16(s.cameraId), String16(), {},
+                sCameraService->connectDevice(callbacks, s.cameraId, std::string(), {},
                 android::CameraService::USE_CALLING_UID, 0/*oomScoreDiff*/,
                 /*targetSdkVersion*/__ANDROID_API_FUTURE__, /*overrideToPortrait*/false, &device);
         AutoDisconnectDevice autoDisconnect(device);
@@ -257,14 +258,14 @@
         sp<TestCameraDeviceCallbacks> callbacks = new TestCameraDeviceCallbacks();
         sp<hardware::camera2::ICameraDeviceUser> deviceA, deviceB;
         binder::Status status =
-                sCameraService->connectDevice(callbacks, String16(s.cameraId), String16(), {},
+                sCameraService->connectDevice(callbacks, s.cameraId, std::string(), {},
                 android::CameraService::USE_CALLING_UID, 0/*oomScoreDiff*/,
                 /*targetSdkVersion*/__ANDROID_API_FUTURE__, /*overrideToPortrait*/false, &deviceA);
         AutoDisconnectDevice autoDisconnectA(deviceA);
         ASSERT_TRUE(status.isOk()) << "Exception code " << status.exceptionCode() <<
                 " service specific error code " << status.serviceSpecificErrorCode();
         status =
-                sCameraService->connectDevice(callbacks, String16(s.cameraId), String16(), {},
+                sCameraService->connectDevice(callbacks, s.cameraId, std::string(), {},
                 android::CameraService::USE_CALLING_UID, 0/*oomScoreDiff*/,
                 /*targetSdkVersion*/__ANDROID_API_FUTURE__, /*overrideToPortrait*/false, &deviceB);
         AutoDisconnectDevice autoDisconnectB(deviceB);
@@ -285,14 +286,14 @@
         sp<TestCameraDeviceCallbacks> callbacks = new TestCameraDeviceCallbacks();
         sp<hardware::camera2::ICameraDeviceUser> deviceA, deviceB;
         binder::Status status =
-                sCameraService->connectDevice(callbacks, String16(s.cameraId), String16(), {},
+                sCameraService->connectDevice(callbacks, s.cameraId, std::string(), {},
                 android::CameraService::USE_CALLING_UID, 0/*oomScoreDiff*/,
                 /*targetSdkVersion*/__ANDROID_API_FUTURE__, /*overrideToPortrait*/false, &deviceA);
         AutoDisconnectDevice autoDisconnectA(deviceA);
         ASSERT_TRUE(status.isOk()) << "Exception code " << status.exceptionCode() <<
                 " service specific error code " << status.serviceSpecificErrorCode();
         status =
-                sCameraService->connectDevice(callbacks, String16(s.cameraId), String16(), {},
+                sCameraService->connectDevice(callbacks, s.cameraId, std::string(), {},
                 android::CameraService::USE_CALLING_UID, 1/*oomScoreDiff*/,
                 /*targetSdkVersion*/__ANDROID_API_FUTURE__, /*overrideToPortrait*/false, &deviceB);
         AutoDisconnectDevice autoDisconnectB(deviceB);
diff --git a/services/camera/libcameraservice/tests/CameraProviderManagerTest.cpp b/services/camera/libcameraservice/tests/CameraProviderManagerTest.cpp
index 1a6b2e0..c0cd1a9 100644
--- a/services/camera/libcameraservice/tests/CameraProviderManagerTest.cpp
+++ b/services/camera/libcameraservice/tests/CameraProviderManagerTest.cpp
@@ -302,15 +302,15 @@
 
     ~TestStatusListener() {}
 
-    void onDeviceStatusChanged(const String8 &,
+    void onDeviceStatusChanged(const std::string &,
             CameraDeviceStatus) override {}
-    void onDeviceStatusChanged(const String8 &, const String8 &,
+    void onDeviceStatusChanged(const std::string &, const std::string &,
             CameraDeviceStatus) override {
         mPhysicalCameraStatusChangeCount++;
     }
-    void onTorchStatusChanged(const String8 &,
+    void onTorchStatusChanged(const std::string &,
             TorchModeStatus) override {}
-    void onTorchStatusChanged(const String8 &,
+    void onTorchStatusChanged(const std::string &,
             TorchModeStatus, SystemCameraKind) override {}
     void onNewProviderRegistered() override {}
 };
diff --git a/services/camera/libcameraservice/tests/DistortionMapperTest.cpp b/services/camera/libcameraservice/tests/DistortionMapperTest.cpp
index b367571..33cc61a 100644
--- a/services/camera/libcameraservice/tests/DistortionMapperTest.cpp
+++ b/services/camera/libcameraservice/tests/DistortionMapperTest.cpp
@@ -19,8 +19,8 @@
 
 #include <random>
 
+#include <fmt/printf.h>
 #include <gtest/gtest.h>
-#include <android-base/stringprintf.h>
 #include <android-base/chrono_utils.h>
 
 #include "../device3/DistortionMapper.h"
@@ -260,9 +260,9 @@
                 rawToCorrectedDurationMs) / (randCoords.size() / 2) ).count();
 
     test->RecordProperty("CorrectedToRawDurationPerCoordUs",
-            base::StringPrintf("%f", correctedToRawDurationPerCoordUs));
+            fmt::sprintf("%f", correctedToRawDurationPerCoordUs));
     test->RecordProperty("RawToCorrectedDurationPerCoordUs",
-            base::StringPrintf("%f", rawToCorrectedDurationPerCoordUs));
+            fmt::sprintf("%f", rawToCorrectedDurationPerCoordUs));
 
     // Calculate mapping errors after round trip
     float totalErrorSq = 0;
@@ -296,9 +296,9 @@
     }
 
     float rmsError = std::sqrt(totalErrorSq / randCoords.size());
-    test->RecordProperty("RmsError", base::StringPrintf("%f", rmsError));
+    test->RecordProperty("RmsError", fmt::sprintf("%f", rmsError));
     for (size_t i = 0; i < histogram.size(); i++) {
-        std::string label = base::StringPrintf("HistogramBin[%f,%f)",
+        std::string label = fmt::sprintf("HistogramBin[%f,%f)",
                 (float)i/bucketsPerPixel, (float)(i + 1)/bucketsPerPixel);
         test->RecordProperty(label, histogram[i]);
     }
diff --git a/services/camera/libcameraservice/utils/CameraServiceProxyWrapper.cpp b/services/camera/libcameraservice/utils/CameraServiceProxyWrapper.cpp
index b58975f..d07bf6d 100644
--- a/services/camera/libcameraservice/utils/CameraServiceProxyWrapper.cpp
+++ b/services/camera/libcameraservice/utils/CameraServiceProxyWrapper.cpp
@@ -20,6 +20,8 @@
 
 #include <inttypes.h>
 #include <utils/Log.h>
+#include <utils/String16.h>
+#include <camera/StringUtils.h>
 #include <binder/IServiceManager.h>
 
 #include "CameraServiceProxyWrapper.h"
@@ -32,7 +34,7 @@
 
 namespace {
 // Sentinel value to be returned when extension session with a stale or invalid key is reported.
-const String16 POISON_EXT_STATS_KEY("poisoned_stats");
+const std::string POISON_EXT_STATS_KEY("poisoned_stats");
 } // anonymous namespace
 
 /**
@@ -100,7 +102,7 @@
     mSessionStats.mRequestCount = requestCount;
     mSessionStats.mResultErrorCount = resultErrorCount;
     mSessionStats.mDeviceError = deviceError;
-    mSessionStats.mUserTag = String16(userTag.c_str());
+    mSessionStats.mUserTag = userTag;
     mSessionStats.mVideoStabilizationMode = videoStabilizationMode;
     mSessionStats.mStreamStats = streamStats;
 
@@ -116,14 +118,14 @@
     return mSessionStats.mLogId;
 }
 
-String16 CameraServiceProxyWrapper::CameraSessionStatsWrapper::updateExtensionSessionStats(
+std::string CameraServiceProxyWrapper::CameraSessionStatsWrapper::updateExtensionSessionStats(
         const hardware::CameraExtensionSessionStats& extStats) {
     Mutex::Autolock l(mLock);
     CameraExtensionSessionStats& currStats = mSessionStats.mCameraExtensionSessionStats;
     if (currStats.key != extStats.key) {
         // Mismatched keys. Extensions stats likely reported for a closed session
         ALOGW("%s: mismatched extensions stats key: current='%s' reported='%s'. Dropping stats.",
-              __FUNCTION__, String8(currStats.key).c_str(), String8(extStats.key).c_str());
+              __FUNCTION__, toStdString(currStats.key).c_str(), toStdString(extStats.key).c_str());
         return POISON_EXT_STATS_KEY; // return poisoned key to so future calls are
                                      // definitely dropped.
     }
@@ -134,15 +136,15 @@
         ALOGV("%s: Overwriting extension session stats: %s", __FUNCTION__,
               extStats.toString().c_str());
         currStats = extStats;
-        return currStats.key;
+        return toStdString(currStats.key);
     }
 
     // Matching empty keys...
-    if (mSessionStats.mClientName != extStats.clientName) {
+    if (mSessionStats.mClientName != toStdString(extStats.clientName)) {
         ALOGW("%s: extension stats reported for unexpected package: current='%s' reported='%s'. "
               "Dropping stats.", __FUNCTION__,
-              String8(mSessionStats.mClientName).c_str(),
-              String8(extStats.clientName).c_str());
+              mSessionStats.mClientName.c_str(),
+              toStdString(extStats.clientName).c_str());
         return POISON_EXT_STATS_KEY;
     }
 
@@ -166,12 +168,12 @@
         key << mSessionStats.mSessionIndex << '/' << mSessionStats.mLogId;
         currStats.key = String16(key.str().c_str());
         ALOGV("%s: New extension session stats: %s", __FUNCTION__, currStats.toString().c_str());
-        return currStats.key;
+        return toStdString(currStats.key);
     }
 
     // Camera is closed. Probably a stale call.
     ALOGW("%s: extension stats reported for closed camera id '%s'. Dropping stats.",
-          __FUNCTION__, String8(mSessionStats.mCameraId).c_str());
+          __FUNCTION__, mSessionStats.mCameraId.c_str());
     return {};
 }
 
@@ -209,12 +211,13 @@
     proxyBinder->pingForUserUpdate();
 }
 
-int CameraServiceProxyWrapper::getRotateAndCropOverride(String16 packageName, int lensFacing,
-        int userId) {
+int CameraServiceProxyWrapper::getRotateAndCropOverride(const std::string &packageName,
+        int lensFacing, int userId) {
     sp<ICameraServiceProxy> proxyBinder = getCameraServiceProxy();
     if (proxyBinder == nullptr) return true;
     int ret = 0;
-    auto status = proxyBinder->getRotateAndCropOverride(packageName, lensFacing, userId, &ret);
+    auto status = proxyBinder->getRotateAndCropOverride(packageName, lensFacing,
+            userId, &ret);
     if (!status.isOk()) {
         ALOGE("%s: Failed during top activity orientation query: %s", __FUNCTION__,
                 status.exceptionMessage().c_str());
@@ -223,7 +226,7 @@
     return ret;
 }
 
-int CameraServiceProxyWrapper::getAutoframingOverride(const String16& packageName) {
+int CameraServiceProxyWrapper::getAutoframingOverride(const std::string& packageName) {
     sp<ICameraServiceProxy> proxyBinder = getCameraServiceProxy();
     if (proxyBinder == nullptr) {
         return ANDROID_CONTROL_AUTOFRAMING_OFF;
@@ -238,7 +241,7 @@
     return ret;
 }
 
-void CameraServiceProxyWrapper::logStreamConfigured(const String8& id,
+void CameraServiceProxyWrapper::logStreamConfigured(const std::string& id,
         int operatingMode, bool internalConfig, int32_t latencyMs) {
     std::shared_ptr<CameraSessionStatsWrapper> sessionStats;
     {
@@ -256,7 +259,7 @@
     sessionStats->onStreamConfigured(operatingMode, internalConfig, latencyMs);
 }
 
-void CameraServiceProxyWrapper::logActive(const String8& id, float maxPreviewFps) {
+void CameraServiceProxyWrapper::logActive(const std::string& id, float maxPreviewFps) {
     std::shared_ptr<CameraSessionStatsWrapper> sessionStats;
     {
         Mutex::Autolock l(mLock);
@@ -273,7 +276,7 @@
     sessionStats->onActive(proxyBinder, maxPreviewFps);
 }
 
-void CameraServiceProxyWrapper::logIdle(const String8& id,
+void CameraServiceProxyWrapper::logIdle(const std::string& id,
         int64_t requestCount, int64_t resultErrorCount, bool deviceError,
         const std::string& userTag, int32_t videoStabilizationMode,
         const std::vector<hardware::CameraStreamStats>& streamStats) {
@@ -304,8 +307,8 @@
             videoStabilizationMode, streamStats);
 }
 
-void CameraServiceProxyWrapper::logOpen(const String8& id, int facing,
-            const String16& clientPackageName, int effectiveApiLevel, bool isNdk,
+void CameraServiceProxyWrapper::logOpen(const std::string& id, int facing,
+            const std::string& clientPackageName, int effectiveApiLevel, bool isNdk,
             int32_t latencyMs) {
     std::shared_ptr<CameraSessionStatsWrapper> sessionStats;
     {
@@ -325,7 +328,7 @@
         int64_t logId = generateLogId(mRandomDevice);
 
         sessionStats = std::make_shared<CameraSessionStatsWrapper>(
-                String16(id), facing, CameraSessionStats::CAMERA_STATE_OPEN, clientPackageName,
+                id, facing, CameraSessionStats::CAMERA_STATE_OPEN, clientPackageName,
                 apiLevel, isNdk, latencyMs, logId);
         mSessionStatsMap.emplace(id, sessionStats);
         ALOGV("%s: Adding id %s", __FUNCTION__, id.c_str());
@@ -337,7 +340,8 @@
     sessionStats->onOpen(proxyBinder);
 }
 
-void CameraServiceProxyWrapper::logClose(const String8& id, int32_t latencyMs, bool deviceError) {
+void CameraServiceProxyWrapper::logClose(const std::string& id, int32_t latencyMs,
+        bool deviceError) {
     std::shared_ptr<CameraSessionStatsWrapper> sessionStats;
     {
         Mutex::Autolock l(mLock);
@@ -376,7 +380,7 @@
     return ret;
 }
 
-int64_t CameraServiceProxyWrapper::getCurrentLogIdForCamera(const String8& cameraId) {
+int64_t CameraServiceProxyWrapper::getCurrentLogIdForCamera(const std::string& cameraId) {
     std::shared_ptr<CameraSessionStatsWrapper> stats;
     {
         Mutex::Autolock _l(mLock);
@@ -403,10 +407,10 @@
     return ret;
 }
 
-String16 CameraServiceProxyWrapper::updateExtensionStats(
+std::string CameraServiceProxyWrapper::updateExtensionStats(
         const hardware::CameraExtensionSessionStats& extStats) {
     std::shared_ptr<CameraSessionStatsWrapper> stats;
-    String8 cameraId = String8(extStats.cameraId);
+    std::string cameraId = toStdString(extStats.cameraId);
     {
         Mutex::Autolock _l(mLock);
         if (mSessionStatsMap.count(cameraId) == 0) {
diff --git a/services/camera/libcameraservice/utils/CameraServiceProxyWrapper.h b/services/camera/libcameraservice/utils/CameraServiceProxyWrapper.h
index e32580c..1afe5b3 100644
--- a/services/camera/libcameraservice/utils/CameraServiceProxyWrapper.h
+++ b/services/camera/libcameraservice/utils/CameraServiceProxyWrapper.h
@@ -20,11 +20,10 @@
 #include <android/hardware/ICameraServiceProxy.h>
 
 #include <utils/Mutex.h>
-#include <utils/String8.h>
-#include <utils/String16.h>
 #include <utils/StrongPointer.h>
 #include <utils/Timers.h>
 #include <random>
+#include <string>
 
 #include <camera/CameraSessionStats.h>
 
@@ -49,8 +48,8 @@
         void updateProxyDeviceState(sp<hardware::ICameraServiceProxy>& proxyBinder);
 
       public:
-        CameraSessionStatsWrapper(const String16& cameraId, int facing, int newCameraState,
-                                  const String16& clientName, int apiLevel, bool isNdk,
+        CameraSessionStatsWrapper(const std::string& cameraId, int facing, int newCameraState,
+                                  const std::string& clientName, int apiLevel, bool isNdk,
                                   int32_t latencyMs, int64_t logId)
             : mSessionStats(cameraId, facing, newCameraState, clientName, apiLevel, isNdk,
                             latencyMs, logId) {}
@@ -65,7 +64,8 @@
                 const std::string& userTag, int32_t videoStabilizationMode,
                 const std::vector<hardware::CameraStreamStats>& streamStats);
 
-        String16 updateExtensionSessionStats(const hardware::CameraExtensionSessionStats& extStats);
+        std::string updateExtensionSessionStats(
+                const hardware::CameraExtensionSessionStats& extStats);
 
         // Returns the logId associated with this event.
         int64_t getLogId();
@@ -74,7 +74,7 @@
     // Lock for camera session stats map
     Mutex mLock;
     // Map from camera id to the camera's session statistics
-    std::map<String8, std::shared_ptr<CameraSessionStatsWrapper>> mSessionStatsMap;
+    std::map<std::string, std::shared_ptr<CameraSessionStatsWrapper>> mSessionStatsMap;
 
     std::random_device mRandomDevice;  // pulls 32-bit random numbers from /dev/urandom
 
@@ -93,22 +93,22 @@
     static sp<hardware::ICameraServiceProxy> getDefaultCameraServiceProxy();
 
     // Open
-    void logOpen(const String8& id, int facing,
-            const String16& clientPackageName, int apiLevel, bool isNdk,
+    void logOpen(const std::string& id, int facing,
+            const std::string& clientPackageName, int apiLevel, bool isNdk,
             int32_t latencyMs);
 
     // Close
-    void logClose(const String8& id, int32_t latencyMs, bool deviceError);
+    void logClose(const std::string& id, int32_t latencyMs, bool deviceError);
 
     // Stream configuration
-    void logStreamConfigured(const String8& id, int operatingMode, bool internalReconfig,
+    void logStreamConfigured(const std::string& id, int operatingMode, bool internalReconfig,
             int32_t latencyMs);
 
     // Session state becomes active
-    void logActive(const String8& id, float maxPreviewFps);
+    void logActive(const std::string& id, float maxPreviewFps);
 
     // Session state becomes idle
-    void logIdle(const String8& id,
+    void logIdle(const std::string& id,
             int64_t requestCount, int64_t resultErrorCount, bool deviceError,
             const std::string& userTag, int32_t videoStabilizationMode,
             const std::vector<hardware::CameraStreamStats>& streamStats);
@@ -117,10 +117,10 @@
     void pingCameraServiceProxy();
 
     // Return the current top activity rotate and crop override.
-    int getRotateAndCropOverride(String16 packageName, int lensFacing, int userId);
+    int getRotateAndCropOverride(const std::string &packageName, int lensFacing, int userId);
 
     // Return the current top activity autoframing.
-    int getAutoframingOverride(const String16& packageName);
+    int getAutoframingOverride(const std::string& packageName);
 
     // Detect if the camera is disabled by device policy.
     bool isCameraDisabled(int userId);
@@ -128,10 +128,10 @@
     // Returns the logId currently associated with the given cameraId. See 'mLogId' in
     // frameworks/av/camera/include/camera/CameraSessionStats.h for more details about this
     // identifier. Returns a non-0 value on success.
-    int64_t getCurrentLogIdForCamera(const String8& cameraId);
+    int64_t getCurrentLogIdForCamera(const std::string& cameraId);
 
     // Update the stored extension stats to the latest values
-    String16 updateExtensionStats(const hardware::CameraExtensionSessionStats& extStats);
+    std::string updateExtensionStats(const hardware::CameraExtensionSessionStats& extStats);
 };
 
 } // android
diff --git a/services/camera/libcameraservice/utils/CameraTraces.h b/services/camera/libcameraservice/utils/CameraTraces.h
index 71fa334..be8d393 100644
--- a/services/camera/libcameraservice/utils/CameraTraces.h
+++ b/services/camera/libcameraservice/utils/CameraTraces.h
@@ -18,7 +18,6 @@
 #define ANDROID_SERVERS_CAMERA_TRACES_H_
 
 #include <utils/Errors.h>
-#include <utils/String16.h>
 #include <utils/Vector.h>
 
 namespace android {
diff --git a/services/camera/libcameraservice/utils/LatencyHistogram.cpp b/services/camera/libcameraservice/utils/LatencyHistogram.cpp
index e2bdc43..a167068 100644
--- a/services/camera/libcameraservice/utils/LatencyHistogram.cpp
+++ b/services/camera/libcameraservice/utils/LatencyHistogram.cpp
@@ -16,8 +16,9 @@
 
 #define LOG_TAG "CameraLatencyHistogram"
 #include <inttypes.h>
+#include <android-base/stringprintf.h>
 #include <utils/Log.h>
-#include <utils/String8.h>
+#include <camera/StringUtils.h>
 
 #include "LatencyHistogram.h"
 
@@ -55,18 +56,18 @@
         return;
     }
 
-    String8 lines;
-    lines.appendFormat("%s (%" PRId64 ") samples\n", name, mTotalCount);
+    std::string lines;
+    lines += fmt::sprintf("%s (%" PRId64 ") samples\n", name, mTotalCount);
 
-    String8 lineBins, lineBinCounts;
+    std::string lineBins, lineBinCounts;
     formatHistogramText(lineBins, lineBinCounts);
 
-    lineBins.append("\n");
-    lineBinCounts.append("\n");
-    lines.append(lineBins);
-    lines.append(lineBinCounts);
+    lineBins += ("\n");
+    lineBinCounts += ("\n");
+    lines += lineBins;
+    lines += lineBinCounts;
 
-    write(fd, lines.string(), lines.size());
+    write(fd, lines.c_str(), lines.size());
 }
 
 void CameraLatencyHistogram::log(const char* fmt, ...) {
@@ -76,11 +77,12 @@
 
     va_list args;
     va_start(args, fmt);
-    String8 histogramName = String8::formatV(fmt, args);
-    ALOGI("%s (%" PRId64 ") samples:", histogramName.string(), mTotalCount);
+    std::string histogramName;
+    base::StringAppendV(&histogramName, fmt, args);
+    ALOGI("%s (%" PRId64 ") samples:", histogramName.c_str(), mTotalCount);
     va_end(args);
 
-    String8 lineBins, lineBinCounts;
+    std::string lineBins, lineBinCounts;
     formatHistogramText(lineBins, lineBinCounts);
 
     ALOGI("%s", lineBins.c_str());
@@ -88,19 +90,19 @@
 }
 
 void CameraLatencyHistogram::formatHistogramText(
-        String8& lineBins, String8& lineBinCounts) const {
+        std::string& lineBins, std::string& lineBinCounts) const {
     lineBins = "  ";
     lineBinCounts = "  ";
 
     for (int32_t i = 0; i < mBinCount; i++) {
         if (i == mBinCount - 1) {
-            lineBins.append("    inf (max ms)");
+            lineBins += "    inf (max ms)";
         } else {
-            lineBins.appendFormat("%7d", mBinSizeMs*(i+1));
+            lineBins += fmt::sprintf("%7d", mBinSizeMs*(i+1));
         }
-        lineBinCounts.appendFormat("   %02.2f", 100.0*mBins[i]/mTotalCount);
+        lineBinCounts += fmt::sprintf("   %02.2f", 100.0*mBins[i]/mTotalCount);
     }
-    lineBinCounts.append(" (%)");
+    lineBinCounts += " (%)";
 }
 
 }; //namespace android
diff --git a/services/camera/libcameraservice/utils/LatencyHistogram.h b/services/camera/libcameraservice/utils/LatencyHistogram.h
index bfd9b1b..89a9cc1 100644
--- a/services/camera/libcameraservice/utils/LatencyHistogram.h
+++ b/services/camera/libcameraservice/utils/LatencyHistogram.h
@@ -40,7 +40,7 @@
     std::vector<int64_t> mBins;
     uint64_t mTotalCount;
 
-    void formatHistogramText(String8& lineBins, String8& lineBinCounts) const;
+    void formatHistogramText(std::string& lineBins, std::string& lineBinCounts) const;
 }; // class CameraLatencyHistogram
 
 }; // namespace android
diff --git a/services/camera/libcameraservice/utils/SchedulingPolicyUtils.cpp b/services/camera/libcameraservice/utils/SchedulingPolicyUtils.cpp
new file mode 100644
index 0000000..92a1030
--- /dev/null
+++ b/services/camera/libcameraservice/utils/SchedulingPolicyUtils.cpp
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "SchedulingPolicyUtils.h"
+
+#include <errno.h>
+#include <pthread.h>
+#include <sched.h>
+
+#include "CameraThreadState.h"
+#include <private/android_filesystem_config.h>
+#include <processgroup/processgroup.h>
+#include <processgroup/sched_policy.h>
+#include <procinfo/process.h>
+#include <utils/Log.h>
+
+namespace android {
+namespace camera3 {
+namespace SchedulingPolicyUtils {
+
+int requestPriorityDirect(int pid, int tid, int prio) {
+    android::procinfo::ProcessInfo processInfo;
+    static const int kMinPrio = 1;
+    static const int kMaxPrio = 3;
+
+    if (!android::procinfo::GetProcessInfo(tid, &processInfo)) {
+       ALOGE("%s: Error getting process info", __FUNCTION__);
+       return -EPERM;
+    }
+
+    if (prio < kMinPrio || prio > kMaxPrio || processInfo.pid != pid) {
+        ALOGE("%s: Invalid parameter prio=%d pid=%d procinfo.pid=%d", __FUNCTION__, prio, pid,
+                processInfo.pid);
+        return -EPERM;
+    }
+
+    // Set the thread group as audio system thread group in consistent with the
+    // implementation in SchedulingPolicyService.java when isApp is false in
+    // requestPriority method.
+    if (!SetTaskProfiles(tid, {get_sched_policy_profile_name(SP_AUDIO_SYS)},
+            /*use_fd_cache*/ true)) {
+        ALOGE("%s:Error in  SetTaskProfiles", __FUNCTION__);
+        return -EPERM;
+    }
+
+    struct sched_param param;
+    param.sched_priority = prio;
+    return sched_setscheduler(tid, SCHED_FIFO | SCHED_RESET_ON_FORK, &param);
+}
+
+} // namespace SchedulingPolicyUtils
+} // namespace camera3
+} // namespace android
diff --git a/services/camera/libcameraservice/utils/SchedulingPolicyUtils.h b/services/camera/libcameraservice/utils/SchedulingPolicyUtils.h
new file mode 100644
index 0000000..f71fddf
--- /dev/null
+++ b/services/camera/libcameraservice/utils/SchedulingPolicyUtils.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef ANDROID_SERVICE_CAMERA_SCHEDULING_POLICY_UTILS_H
+#define ANDROID_SERVICE_CAMERA_SCHEDULING_POLICY_UTILS_H
+
+namespace android {
+namespace camera3 {
+namespace SchedulingPolicyUtils {
+
+/**
+ * Request elevated priority for thread tid, whose thread group leader must be pid.
+ * Instead of using scheduling policy service, this method uses direct system calls.
+ * The priority parameter is currently restricted from 1 to 3 matching
+ * scheduling policy service implementation.
+ */
+int requestPriorityDirect(int pid, int tid, int prio);
+
+} // SchedulingPolicyUtils
+} // camera3
+} // android
+
+#endif
diff --git a/services/camera/libcameraservice/utils/SessionConfigurationUtils.cpp b/services/camera/libcameraservice/utils/SessionConfigurationUtils.cpp
index 89e75b3..f7257e3 100644
--- a/services/camera/libcameraservice/utils/SessionConfigurationUtils.cpp
+++ b/services/camera/libcameraservice/utils/SessionConfigurationUtils.cpp
@@ -28,6 +28,7 @@
 #include "device3/hidl/HidlCamera3Device.h"
 #include "device3/Camera3OutputStream.h"
 #include "system/graphics-base-v1.1.h"
+#include <camera/StringUtils.h>
 #include <ui/PublicFormat.h>
 
 using android::camera3::OutputStreamInfo;
@@ -427,15 +428,15 @@
 binder::Status createSurfaceFromGbp(
         OutputStreamInfo& streamInfo, bool isStreamInfoValid,
         sp<Surface>& surface, const sp<IGraphicBufferProducer>& gbp,
-        const String8 &logicalCameraId, const CameraMetadata &physicalCameraMetadata,
+        const std::string &logicalCameraId, const CameraMetadata &physicalCameraMetadata,
         const std::vector<int32_t> &sensorPixelModesUsed, int64_t dynamicRangeProfile,
         int64_t streamUseCase, int timestampBase, int mirrorMode,
         int32_t colorSpace) {
     // bufferProducer must be non-null
     if (gbp == nullptr) {
-        String8 msg = String8::format("Camera %s: Surface is NULL", logicalCameraId.string());
-        ALOGW("%s: %s", __FUNCTION__, msg.string());
-        return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
+        std::string msg = fmt::sprintf("Camera %s: Surface is NULL", logicalCameraId.c_str());
+        ALOGW("%s: %s", __FUNCTION__, msg.c_str());
+        return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.c_str());
     }
     // HACK b/10949105
     // Query consumer usage bits to set async operation mode for
@@ -444,14 +445,14 @@
     uint64_t consumerUsage = 0;
     status_t err;
     if ((err = gbp->getConsumerUsage(&consumerUsage)) != OK) {
-        String8 msg = String8::format("Camera %s: Failed to query Surface consumer usage: %s (%d)",
-                logicalCameraId.string(), strerror(-err), err);
-        ALOGE("%s: %s", __FUNCTION__, msg.string());
-        return STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION, msg.string());
+        std::string msg = fmt::sprintf("Camera %s: Failed to query Surface consumer usage: %s (%d)",
+                logicalCameraId.c_str(), strerror(-err), err);
+        ALOGE("%s: %s", __FUNCTION__, msg.c_str());
+        return STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION, msg.c_str());
     }
     if (consumerUsage & GraphicBuffer::USAGE_HW_TEXTURE) {
         ALOGW("%s: Camera %s with consumer usage flag: %" PRIu64 ": Forcing asynchronous mode for"
-                "stream", __FUNCTION__, logicalCameraId.string(), consumerUsage);
+                "stream", __FUNCTION__, logicalCameraId.c_str(), consumerUsage);
         useAsync = true;
     }
 
@@ -469,38 +470,38 @@
     int width, height, format;
     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)",
-                 logicalCameraId.string(), strerror(-err), err);
-        ALOGE("%s: %s", __FUNCTION__, msg.string());
-        return STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION, msg.string());
+        std::string msg = fmt::sprintf("Camera %s: Failed to query Surface width: %s (%d)",
+                 logicalCameraId.c_str(), strerror(-err), err);
+        ALOGE("%s: %s", __FUNCTION__, msg.c_str());
+        return STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION, msg.c_str());
     }
     if ((err = anw->query(anw, NATIVE_WINDOW_HEIGHT, &height)) != OK) {
-        String8 msg = String8::format("Camera %s: Failed to query Surface height: %s (%d)",
-                logicalCameraId.string(), strerror(-err), err);
-        ALOGE("%s: %s", __FUNCTION__, msg.string());
-        return STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION, msg.string());
+        std::string msg = fmt::sprintf("Camera %s: Failed to query Surface height: %s (%d)",
+                logicalCameraId.c_str(), strerror(-err), err);
+        ALOGE("%s: %s", __FUNCTION__, msg.c_str());
+        return STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION, msg.c_str());
     }
     if ((err = anw->query(anw, NATIVE_WINDOW_FORMAT, &format)) != OK) {
-        String8 msg = String8::format("Camera %s: Failed to query Surface format: %s (%d)",
-                logicalCameraId.string(), strerror(-err), err);
-        ALOGE("%s: %s", __FUNCTION__, msg.string());
-        return STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION, msg.string());
+        std::string msg = fmt::sprintf("Camera %s: Failed to query Surface format: %s (%d)",
+                logicalCameraId.c_str(), strerror(-err), err);
+        ALOGE("%s: %s", __FUNCTION__, msg.c_str());
+        return STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION, msg.c_str());
     }
     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)",
-                logicalCameraId.string(), strerror(-err), err);
-        ALOGE("%s: %s", __FUNCTION__, msg.string());
-        return STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION, msg.string());
+        std::string msg = fmt::sprintf("Camera %s: Failed to query Surface dataspace: %s (%d)",
+                logicalCameraId.c_str(), strerror(-err), err);
+        ALOGE("%s: %s", __FUNCTION__, msg.c_str());
+        return STATUS_ERROR(CameraService::ERROR_INVALID_OPERATION, msg.c_str());
     }
 
     if (colorSpace != ANDROID_REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_UNSPECIFIED &&
             format != HAL_PIXEL_FORMAT_BLOB) {
         if (!dataSpaceFromColorSpace(&dataSpace, colorSpace)) {
-            String8 msg = String8::format("Camera %s: color space %d not supported, failed to "
-                    "convert to data space", logicalCameraId.string(), colorSpace);
-            ALOGE("%s: %s", __FUNCTION__, msg.string());
-            return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
+            std::string msg = fmt::sprintf("Camera %s: color space %d not supported, failed to "
+                    "convert to data space", logicalCameraId.c_str(), colorSpace);
+            ALOGE("%s: %s", __FUNCTION__, msg.c_str());
+            return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.c_str());
         }
     }
 
@@ -510,16 +511,16 @@
             ((consumerUsage & GRALLOC_USAGE_HW_MASK) &&
              ((consumerUsage & GRALLOC_USAGE_SW_READ_MASK) == 0))) {
         ALOGW("%s: Camera %s: Overriding format %#x to IMPLEMENTATION_DEFINED",
-                __FUNCTION__, logicalCameraId.string(), format);
+                __FUNCTION__, logicalCameraId.c_str(), format);
         format = HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
     }
     std::unordered_set<int32_t> overriddenSensorPixelModes;
     if (checkAndOverrideSensorPixelModesUsed(sensorPixelModesUsed, format, width, height,
             physicalCameraMetadata, &overriddenSensorPixelModes) != OK) {
-        String8 msg = String8::format("Camera %s: sensor pixel modes for stream with "
-                "format %#x are not valid",logicalCameraId.string(), format);
-        ALOGE("%s: %s", __FUNCTION__, msg.string());
-        return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
+        std::string msg = fmt::sprintf("Camera %s: sensor pixel modes for stream with "
+                "format %#x are not valid",logicalCameraId.c_str(), format);
+        ALOGE("%s: %s", __FUNCTION__, msg.c_str());
+        return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.c_str());
     }
     bool foundInMaxRes = false;
     if (overriddenSensorPixelModes.find(ANDROID_SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION) !=
@@ -532,58 +533,58 @@
             !SessionConfigurationUtils::roundBufferDimensionNearest(width, height,
             format, dataSpace, physicalCameraMetadata, foundInMaxRes, /*out*/&width,
             /*out*/&height)) {
-        String8 msg = String8::format("Camera %s: No supported stream configurations with "
+        std::string msg = fmt::sprintf("Camera %s: No supported stream configurations with "
                 "format %#x defined, failed to create output stream",
-                logicalCameraId.string(), format);
-        ALOGE("%s: %s", __FUNCTION__, msg.string());
-        return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
+                logicalCameraId.c_str(), format);
+        ALOGE("%s: %s", __FUNCTION__, msg.c_str());
+        return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.c_str());
     }
     if (!SessionConfigurationUtils::isDynamicRangeProfileSupported(dynamicRangeProfile,
                 physicalCameraMetadata)) {
-        String8 msg = String8::format("Camera %s: Dynamic range profile 0x%" PRIx64
-                " not supported,failed to create output stream", logicalCameraId.string(),
+        std::string msg = fmt::sprintf("Camera %s: Dynamic range profile 0x%" PRIx64
+                " not supported,failed to create output stream", logicalCameraId.c_str(),
                 dynamicRangeProfile);
-        ALOGE("%s: %s", __FUNCTION__, msg.string());
-        return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
+        ALOGE("%s: %s", __FUNCTION__, msg.c_str());
+        return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.c_str());
     }
     if (SessionConfigurationUtils::is10bitDynamicRangeProfile(dynamicRangeProfile) &&
             !SessionConfigurationUtils::is10bitCompatibleFormat(format, dataSpace)) {
-        String8 msg = String8::format("Camera %s: No 10-bit supported stream configurations with "
+        std::string msg = fmt::sprintf("Camera %s: No 10-bit supported stream configurations with "
                 "format %#x defined and profile %" PRIx64 ", failed to create output stream",
-                logicalCameraId.string(), format, dynamicRangeProfile);
-        ALOGE("%s: %s", __FUNCTION__, msg.string());
-        return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
+                logicalCameraId.c_str(), format, dynamicRangeProfile);
+        ALOGE("%s: %s", __FUNCTION__, msg.c_str());
+        return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.c_str());
     }
     if (colorSpace != ANDROID_REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_UNSPECIFIED &&
             SessionConfigurationUtils::deviceReportsColorSpaces(physicalCameraMetadata) &&
             !SessionConfigurationUtils::isColorSpaceSupported(colorSpace, format, dataSpace,
                     dynamicRangeProfile, physicalCameraMetadata)) {
-        String8 msg = String8::format("Camera %s: Color space %d not supported, failed to "
+        std::string msg = fmt::sprintf("Camera %s: Color space %d not supported, failed to "
                 "create output stream (pixel format %d dynamic range profile %" PRId64 ")",
-                logicalCameraId.string(), colorSpace, format, dynamicRangeProfile);
-        ALOGE("%s: %s", __FUNCTION__, msg.string());
-        return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
+                logicalCameraId.c_str(), colorSpace, format, dynamicRangeProfile);
+        ALOGE("%s: %s", __FUNCTION__, msg.c_str());
+        return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.c_str());
     }
     if (!SessionConfigurationUtils::isStreamUseCaseSupported(streamUseCase,
             physicalCameraMetadata)) {
-        String8 msg = String8::format("Camera %s: stream use case %" PRId64 " not supported,"
-                " failed to create output stream", logicalCameraId.string(), streamUseCase);
-        ALOGE("%s: %s", __FUNCTION__, msg.string());
-        return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
+        std::string msg = fmt::sprintf("Camera %s: stream use case %" PRId64 " not supported,"
+                " failed to create output stream", logicalCameraId.c_str(), streamUseCase);
+        ALOGE("%s: %s", __FUNCTION__, msg.c_str());
+        return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.c_str());
     }
     if (timestampBase < OutputConfiguration::TIMESTAMP_BASE_DEFAULT ||
             timestampBase > OutputConfiguration::TIMESTAMP_BASE_MAX) {
-        String8 msg = String8::format("Camera %s: invalid timestamp base %d",
-                logicalCameraId.string(), timestampBase);
-        ALOGE("%s: %s", __FUNCTION__, msg.string());
-        return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
+        std::string msg = fmt::sprintf("Camera %s: invalid timestamp base %d",
+                logicalCameraId.c_str(), timestampBase);
+        ALOGE("%s: %s", __FUNCTION__, msg.c_str());
+        return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.c_str());
     }
     if (mirrorMode < OutputConfiguration::MIRROR_MODE_AUTO ||
             mirrorMode > OutputConfiguration::MIRROR_MODE_V) {
-        String8 msg = String8::format("Camera %s: invalid mirroring mode %d",
-                logicalCameraId.string(), mirrorMode);
-        ALOGE("%s: %s", __FUNCTION__, msg.string());
-        return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
+        std::string msg = fmt::sprintf("Camera %s: invalid mirroring mode %d",
+                logicalCameraId.c_str(), mirrorMode);
+        ALOGE("%s: %s", __FUNCTION__, msg.c_str());
+        return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.c_str());
     }
 
     if (!isStreamInfoValid) {
@@ -601,45 +602,45 @@
         return binder::Status::ok();
     }
     if (width != streamInfo.width) {
-        String8 msg = String8::format("Camera %s:Surface width doesn't match: %d vs %d",
-                logicalCameraId.string(), width, streamInfo.width);
-        ALOGE("%s: %s", __FUNCTION__, msg.string());
-        return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
+        std::string msg = fmt::sprintf("Camera %s:Surface width doesn't match: %d vs %d",
+                logicalCameraId.c_str(), width, streamInfo.width);
+        ALOGE("%s: %s", __FUNCTION__, msg.c_str());
+        return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.c_str());
     }
     if (height != streamInfo.height) {
-        String8 msg = String8::format("Camera %s:Surface height doesn't match: %d vs %d",
-                 logicalCameraId.string(), height, streamInfo.height);
-        ALOGE("%s: %s", __FUNCTION__, msg.string());
-        return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
+        std::string msg = fmt::sprintf("Camera %s:Surface height doesn't match: %d vs %d",
+                 logicalCameraId.c_str(), height, streamInfo.height);
+        ALOGE("%s: %s", __FUNCTION__, msg.c_str());
+        return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.c_str());
     }
     if (format != streamInfo.format) {
-        String8 msg = String8::format("Camera %s:Surface format doesn't match: %d vs %d",
-                 logicalCameraId.string(), format, streamInfo.format);
-        ALOGE("%s: %s", __FUNCTION__, msg.string());
-        return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
+        std::string msg = fmt::sprintf("Camera %s:Surface format doesn't match: %d vs %d",
+                 logicalCameraId.c_str(), format, streamInfo.format);
+        ALOGE("%s: %s", __FUNCTION__, msg.c_str());
+        return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.c_str());
     }
     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",
-                    logicalCameraId.string(), dataSpace, streamInfo.dataSpace);
-            ALOGE("%s: %s", __FUNCTION__, msg.string());
-            return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
+            std::string msg = fmt::sprintf("Camera %s:Surface dataSpace doesn't match: %d vs %d",
+                    logicalCameraId.c_str(), dataSpace, streamInfo.dataSpace);
+            ALOGE("%s: %s", __FUNCTION__, msg.c_str());
+            return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.c_str());
         }
         //At the native side, there isn't a way to check whether 2 surfaces come from the same
         //surface class type. Use usage flag to approximate the comparison.
         if (consumerUsage != streamInfo.consumerUsage) {
-            String8 msg = String8::format(
+            std::string msg = fmt::sprintf(
                     "Camera %s:Surface usage flag doesn't match %" PRIu64 " vs %" PRIu64 "",
-                    logicalCameraId.string(), consumerUsage, streamInfo.consumerUsage);
-            ALOGE("%s: %s", __FUNCTION__, msg.string());
-            return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
+                    logicalCameraId.c_str(), consumerUsage, streamInfo.consumerUsage);
+            ALOGE("%s: %s", __FUNCTION__, msg.c_str());
+            return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.c_str());
         }
     }
     return binder::Status::ok();
 }
 
 void mapStreamInfo(const OutputStreamInfo &streamInfo,
-            camera3::camera_stream_rotation_t rotation, String8 physicalId,
+            camera3::camera_stream_rotation_t rotation, const std::string &physicalId,
             int32_t groupId, aidl::android::hardware::camera::device::Stream *stream /*out*/) {
     if (stream == nullptr) {
         return;
@@ -656,7 +657,7 @@
     stream->colorSpace = streamInfo.colorSpace;
     stream->rotation = AidlCamera3Device::mapToAidlStreamRotation(rotation);
     stream->id = -1; // Invalid stream id
-    stream->physicalCameraId = std::string(physicalId.string());
+    stream->physicalCameraId = physicalId;
     stream->bufferSize = 0;
     stream->groupId = groupId;
     stream->sensorPixelModesUsed.resize(streamInfo.sensorPixelModesUsed.size());
@@ -677,34 +678,35 @@
 binder::Status
 convertToHALStreamCombination(
         const SessionConfiguration& sessionConfiguration,
-        const String8 &logicalCameraId, const CameraMetadata &deviceInfo,
+        const std::string &logicalCameraId, const CameraMetadata &deviceInfo,
         bool isCompositeJpegRDisabled,
         metadataGetter getMetadata, const std::vector<std::string> &physicalCameraIds,
         aidl::android::hardware::camera::device::StreamConfiguration &streamConfiguration,
         bool overrideForPerfClass, bool *earlyExit) {
     using SensorPixelMode = aidl::android::hardware::camera::metadata::SensorPixelMode;
     auto operatingMode = sessionConfiguration.getOperatingMode();
-    binder::Status res = checkOperatingMode(operatingMode, deviceInfo, logicalCameraId);
+    binder::Status res = checkOperatingMode(operatingMode, deviceInfo,
+            logicalCameraId);
     if (!res.isOk()) {
         return res;
     }
 
     if (earlyExit == nullptr) {
-        String8 msg("earlyExit nullptr");
-        ALOGE("%s: %s", __FUNCTION__, msg.string());
-        return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
+        std::string msg("earlyExit nullptr");
+        ALOGE("%s: %s", __FUNCTION__, msg.c_str());
+        return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.c_str());
     }
     *earlyExit = false;
     auto ret = AidlCamera3Device::mapToAidlStreamConfigurationMode(
             static_cast<camera_stream_configuration_mode_t> (operatingMode),
             /*out*/ &streamConfiguration.operationMode);
     if (ret != OK) {
-        String8 msg = String8::format(
+        std::string msg = fmt::sprintf(
             "Camera %s: Failed mapping operating mode %d requested: %s (%d)",
-            logicalCameraId.string(), operatingMode, strerror(-ret), ret);
-        ALOGE("%s: %s", __FUNCTION__, msg.string());
+            logicalCameraId.c_str(), operatingMode, strerror(-ret), ret);
+        ALOGE("%s: %s", __FUNCTION__, msg.c_str());
         return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
-                msg.string());
+                msg.c_str());
     }
 
     bool isInputValid = (sessionConfiguration.getInputWidth() > 0) &&
@@ -749,7 +751,7 @@
         const std::vector<sp<IGraphicBufferProducer>>& bufferProducers =
             it.getGraphicBufferProducers();
         bool deferredConsumer = it.isDeferred();
-        String8 physicalCameraId = String8(it.getPhysicalCameraId());
+        const std::string &physicalCameraId = it.getPhysicalCameraId();
 
         int64_t dynamicRangeProfile = it.getDynamicRangeProfile();
         int32_t colorSpace = it.getColorSpace();
@@ -841,11 +843,11 @@
                     }
 
                     if (ret != OK) {
-                        String8 msg = String8::format(
+                        std::string msg = fmt::sprintf(
                                 "Camera %s: Failed adding composite streams: %s (%d)",
-                                logicalCameraId.string(), strerror(-ret), ret);
-                        ALOGE("%s: %s", __FUNCTION__, msg.string());
-                        return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.string());
+                                logicalCameraId.c_str(), strerror(-ret), ret);
+                        ALOGE("%s: %s", __FUNCTION__, msg.c_str());
+                        return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.c_str());
                     }
 
                     if (compositeStreams.size() == 0) {
@@ -877,17 +879,17 @@
 }
 
 binder::Status checkPhysicalCameraId(
-        const std::vector<std::string> &physicalCameraIds, const String8 &physicalCameraId,
-        const String8 &logicalCameraId) {
+        const std::vector<std::string> &physicalCameraIds, const std::string &physicalCameraId,
+        const std::string &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());
+        physicalCameraId) == physicalCameraIds.end()) {
+        std::string msg = fmt::sprintf("Camera %s: Camera doesn't support physicalCameraId %s.",
+                logicalCameraId.c_str(), physicalCameraId.c_str());
+        ALOGE("%s: %s", __FUNCTION__, msg.c_str());
+        return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT, msg.c_str());
     }
     return binder::Status::ok();
 }
@@ -915,13 +917,13 @@
 }
 
 binder::Status checkOperatingMode(int operatingMode,
-        const CameraMetadata &staticInfo, const String8 &cameraId) {
+        const CameraMetadata &staticInfo, const std::string &cameraId) {
     if (operatingMode < 0) {
-        String8 msg = String8::format(
-            "Camera %s: Invalid operating mode %d requested", cameraId.string(), operatingMode);
-        ALOGE("%s: %s", __FUNCTION__, msg.string());
+        std::string msg = fmt::sprintf(
+            "Camera %s: Invalid operating mode %d requested", cameraId.c_str(), operatingMode);
+        ALOGE("%s: %s", __FUNCTION__, msg.c_str());
         return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
-                msg.string());
+                msg.c_str());
     }
 
     bool isConstrainedHighSpeed = (operatingMode == ICameraDeviceUser::CONSTRAINED_HIGH_SPEED_MODE);
@@ -936,12 +938,12 @@
             }
         }
         if (!isConstrainedHighSpeedSupported) {
-            String8 msg = String8::format(
+            std::string msg = fmt::sprintf(
                 "Camera %s: Try to create a constrained high speed configuration on a device"
-                " that doesn't support it.", cameraId.string());
-            ALOGE("%s: %s", __FUNCTION__, msg.string());
+                " that doesn't support it.", cameraId.c_str());
+            ALOGE("%s: %s", __FUNCTION__, msg.c_str());
             return STATUS_ERROR(CameraService::ERROR_ILLEGAL_ARGUMENT,
-                    msg.string());
+                    msg.c_str());
         }
     }
 
diff --git a/services/camera/libcameraservice/utils/SessionConfigurationUtils.h b/services/camera/libcameraservice/utils/SessionConfigurationUtils.h
index dc143da..79d80ea 100644
--- a/services/camera/libcameraservice/utils/SessionConfigurationUtils.h
+++ b/services/camera/libcameraservice/utils/SessionConfigurationUtils.h
@@ -21,6 +21,7 @@
 #include <camera/camera2/OutputConfiguration.h>
 #include <camera/camera2/SessionConfiguration.h>
 #include <camera/camera2/SubmitInfo.h>
+#include <camera/StringUtils.h>
 #include <aidl/android/hardware/camera/device/ICameraDevice.h>
 #include <android/hardware/camera/device/3.4/ICameraDeviceSession.h>
 #include <android/hardware/camera/device/3.7/ICameraDeviceSession.h>
@@ -37,17 +38,18 @@
 
 #define STATUS_ERROR(errorCode, errorString) \
     binder::Status::fromServiceSpecificError(errorCode, \
-            String8::format("%s:%d: %s", __FUNCTION__, __LINE__, errorString))
+            fmt::sprintf("%s:%d: %s", __FUNCTION__, __LINE__, errorString).c_str())
 
 #define STATUS_ERROR_FMT(errorCode, errorString, ...) \
     binder::Status::fromServiceSpecificError(errorCode, \
-            String8::format("%s:%d: " errorString, __FUNCTION__, __LINE__, \
-                    __VA_ARGS__))
+            fmt::sprintf("%s:%d: " errorString, __FUNCTION__, __LINE__, \
+                    __VA_ARGS__).c_str())
 
 namespace android {
 namespace camera3 {
 
-typedef std::function<CameraMetadata (const String8 &, bool overrideForPerfClass)> metadataGetter;
+typedef std::function<CameraMetadata (const std::string &, bool overrideForPerfClass)>
+        metadataGetter;
 
 class StreamConfiguration {
 public:
@@ -96,7 +98,7 @@
 binder::Status createSurfaceFromGbp(
         camera3::OutputStreamInfo& streamInfo, bool isStreamInfoValid,
         sp<Surface>& surface, const sp<IGraphicBufferProducer>& gbp,
-        const String8 &logicalCameraId, const CameraMetadata &physicalCameraMetadata,
+        const std::string &logicalCameraId, const CameraMetadata &physicalCameraMetadata,
         const std::vector<int32_t> &sensorPixelModesUsed,  int64_t dynamicRangeProfile,
         int64_t streamUseCase, int timestampBase, int mirrorMode,
         int32_t colorSpace);
@@ -120,26 +122,27 @@
 bool isStreamUseCaseSupported(int64_t streamUseCase, const CameraMetadata &deviceInfo);
 
 void mapStreamInfo(const OutputStreamInfo &streamInfo,
-        camera3::camera_stream_rotation_t rotation, String8 physicalId,
+        camera3::camera_stream_rotation_t rotation, const std::string &physicalId,
         int32_t groupId, aidl::android::hardware::camera::device::Stream *stream /*out*/);
 
 // Check that the physicalCameraId passed in is spported by the camera
 // device.
 binder::Status checkPhysicalCameraId(
-const std::vector<std::string> &physicalCameraIds, const String8 &physicalCameraId,
-const String8 &logicalCameraId);
+const std::vector<std::string> &physicalCameraIds, const std::string &physicalCameraId,
+const std::string &logicalCameraId);
 
 binder::Status checkSurfaceType(size_t numBufferProducers,
 bool deferredConsumer, int surfaceType);
 
 binder::Status checkOperatingMode(int operatingMode,
-const CameraMetadata &staticInfo, const String8 &cameraId);
+const CameraMetadata &staticInfo, const std::string &cameraId);
 
 binder::Status
 convertToHALStreamCombination(
     const SessionConfiguration& sessionConfiguration,
-    const String8 &logicalCameraId, const CameraMetadata &deviceInfo, bool isCompositeJpegRDisabled,
-    metadataGetter getMetadata, const std::vector<std::string> &physicalCameraIds,
+    const std::string &logicalCameraId, const CameraMetadata &deviceInfo,
+    bool isCompositeJpegRDisabled, metadataGetter getMetadata,
+    const std::vector<std::string> &physicalCameraIds,
     aidl::android::hardware::camera::device::StreamConfiguration &streamConfiguration,
     bool overrideForPerfClass, bool *earlyExit);
 
diff --git a/services/camera/libcameraservice/utils/SessionConfigurationUtilsHidl.cpp b/services/camera/libcameraservice/utils/SessionConfigurationUtilsHidl.cpp
index 111c1bf..cf93d3b 100644
--- a/services/camera/libcameraservice/utils/SessionConfigurationUtilsHidl.cpp
+++ b/services/camera/libcameraservice/utils/SessionConfigurationUtilsHidl.cpp
@@ -105,7 +105,7 @@
 binder::Status
 convertToHALStreamCombination(
         const SessionConfiguration& sessionConfiguration,
-        const String8 &logicalCameraId, const CameraMetadata &deviceInfo,
+        const std::string &logicalCameraId, const CameraMetadata &deviceInfo,
         metadataGetter getMetadata, const std::vector<std::string> &physicalCameraIds,
         hardware::camera::device::V3_7::StreamConfiguration &streamConfiguration,
         bool overrideForPerfClass, bool *earlyExit) {
diff --git a/services/camera/libcameraservice/utils/SessionConfigurationUtilsHidl.h b/services/camera/libcameraservice/utils/SessionConfigurationUtilsHidl.h
index c47abe0..eae2e30 100644
--- a/services/camera/libcameraservice/utils/SessionConfigurationUtilsHidl.h
+++ b/services/camera/libcameraservice/utils/SessionConfigurationUtilsHidl.h
@@ -34,7 +34,7 @@
 // isn't valid.
 binder::Status
 convertToHALStreamCombination(const SessionConfiguration& sessionConfiguration,
-        const String8 &cameraId, const CameraMetadata &deviceInfo,
+        const std::string &cameraId, const CameraMetadata &deviceInfo,
         metadataGetter getMetadata, const std::vector<std::string> &physicalCameraIds,
         hardware::camera::device::V3_7::StreamConfiguration &streamConfiguration,
         bool overrideForPerfClass, bool *earlyExit);
diff --git a/services/camera/libcameraservice/utils/TagMonitor.cpp b/services/camera/libcameraservice/utils/TagMonitor.cpp
index d1e54ab..38de93a 100644
--- a/services/camera/libcameraservice/utils/TagMonitor.cpp
+++ b/services/camera/libcameraservice/utils/TagMonitor.cpp
@@ -18,11 +18,15 @@
 #define ATRACE_TAG ATRACE_TAG_CAMERA
 //#define LOG_NDEBUG 0
 
+#include <iostream>
+#include <sstream>
+
 #include "TagMonitor.h"
 
 #include <inttypes.h>
 #include <utils/Log.h>
 #include <camera/VendorTagDescriptor.h>
+#include <camera/StringUtils.h>
 #include <camera_metadata_hidden.h>
 #include <device3/Camera3Stream.h>
 
@@ -44,7 +48,7 @@
         mMonitoringEvents(other.mMonitoringEvents),
         mVendorTagId(other.mVendorTagId) {}
 
-const String16 TagMonitor::kMonitorOption = String16("-m");
+const std::string TagMonitor::kMonitorOption("-m");
 
 const char* TagMonitor::k3aTags =
         "android.control.aeMode, android.control.afMode, android.control.awbMode,"
@@ -56,17 +60,17 @@
         "android.control.effectMode, android.control.mode, android.control.sceneMode,"
         "android.control.videoStabilizationMode";
 
-void TagMonitor::parseTagsToMonitor(String8 tagNames) {
+void TagMonitor::parseTagsToMonitor(std::string tagNames) {
     std::lock_guard<std::mutex> lock(mMonitorMutex);
 
     // Expand shorthands
     ssize_t idx = tagNames.find("3a");
     if (idx != -1) {
         ssize_t end = tagNames.find(",", idx);
-        char* start = tagNames.lockBuffer(tagNames.size());
-        start[idx] = '\0';
-        char* rest = (end != -1) ? (start + end) : (start + tagNames.size());
-        tagNames = String8::format("%s%s%s", start, k3aTags, rest);
+        tagNames = tagNames.substr(0, idx) + k3aTags;
+        if (end != -1) {
+            tagNames += tagNames.substr(end);
+        }
     }
 
     sp<VendorTagDescriptor> vTags =
@@ -81,14 +85,13 @@
 
     bool gotTag = false;
 
-    char *tokenized = tagNames.lockBuffer(tagNames.size());
-    char *savePtr;
-    char *nextTagName = strtok_r(tokenized, ", ", &savePtr);
-    while (nextTagName != nullptr) {
+    std::istringstream iss(tagNames);
+    std::string nextTagName;
+    while (std::getline(iss, nextTagName, ',')) {
         uint32_t tag;
-        status_t res = CameraMetadata::getTagFromName(nextTagName, vTags.get(), &tag);
+        status_t res = CameraMetadata::getTagFromName(nextTagName.c_str(), vTags.get(), &tag);
         if (res != OK) {
-            ALOGW("%s: Unknown tag %s, ignoring", __FUNCTION__, nextTagName);
+            ALOGW("%s: Unknown tag %s, ignoring", __FUNCTION__, nextTagName.c_str());
         } else {
             if (!gotTag) {
                 mMonitoredTagList.clear();
@@ -96,11 +99,9 @@
             }
             mMonitoredTagList.push_back(tag);
         }
-        nextTagName = strtok_r(nullptr, ", ", &savePtr);
+        iss >> std::ws;
     }
 
-    tagNames.unlockBuffer();
-
     if (gotTag) {
         // Got at least one new tag
         mMonitoringEnabled = true;
@@ -269,7 +270,7 @@
 
     for (const auto& event : mMonitoringEvents) {
         int indentation = (event.source == REQUEST) ? 15 : 30;
-        String8 eventString = String8::format("f%d:%" PRId64 "ns:%*s%*s",
+        std::string eventString = fmt::sprintf("f%d:%" PRId64 "ns:%*s%*s",
                 event.frameNumber, event.timestamp,
                 2, event.cameraId.c_str(),
                 indentation,
@@ -278,20 +279,20 @@
         if (!event.outputStreamIds.empty()) {
             eventString += " output stream ids:";
             for (const auto& id : event.outputStreamIds) {
-                eventString.appendFormat(" %d", id);
+                eventString += fmt::sprintf(" %d", id);
             }
             eventString += "\n";
-            vec.emplace_back(eventString.string());
+            vec.emplace_back(eventString);
             continue;
         }
 
         if (event.inputStreamId != -1) {
-            eventString.appendFormat(" input stream id: %d\n", event.inputStreamId);
-            vec.emplace_back(eventString.string());
+            eventString += fmt::sprintf(" input stream id: %d\n", event.inputStreamId);
+            vec.emplace_back(eventString);
             continue;
         }
 
-        eventString += String8::format(
+        eventString += fmt::sprintf(
                 "%s.%s: ",
                 get_local_camera_metadata_section_name_vendor_id(event.tag, mVendorTagId),
                 get_local_camera_metadata_tag_name_vendor_id(event.tag, mVendorTagId));
@@ -303,14 +304,14 @@
                     event.newData.data(), event.tag, event.type,
                     event.newData.size() / camera_metadata_type_size[event.type], indentation + 18);
         }
-        vec.emplace_back(eventString.string());
+        vec.emplace_back(eventString);
     }
 }
 
 #define CAMERA_METADATA_ENUM_STRING_MAX_SIZE 29
 
-String8 TagMonitor::getEventDataString(const uint8_t* data_ptr, uint32_t tag, int type, int count,
-                                       int indentation) {
+std::string TagMonitor::getEventDataString(const uint8_t* data_ptr, uint32_t tag, int type,
+        int count, int indentation) {
     static int values_per_line[NUM_TYPES] = {
         [TYPE_BYTE]     = 16,
         [TYPE_INT32]    = 8,
@@ -327,11 +328,11 @@
     int lines = count / values_per_line[type];
     if (count % values_per_line[type] != 0) lines++;
 
-    String8 returnStr = String8();
+    std::ostringstream returnStr;
     int index = 0;
     int j, k;
     for (j = 0; j < lines; j++) {
-        returnStr.appendFormat("%*s[", (j != 0) ? indentation + 4 : 0, "");
+        returnStr << fmt::sprintf("%*s[", (j != 0) ? indentation + 4 : 0, "");
         for (k = 0;
              k < values_per_line[type] && count > 0;
              k++, count--, index += type_size) {
@@ -344,9 +345,9 @@
                                                      value_string_tmp,
                                                      sizeof(value_string_tmp))
                         == OK) {
-                        returnStr += value_string_tmp;
+                        returnStr << value_string_tmp;
                     } else {
-                        returnStr.appendFormat("%hhu ", *(data_ptr + index));
+                        returnStr << fmt::sprintf("%hhu ", *(data_ptr + index));
                     }
                     break;
                 case TYPE_INT32:
@@ -357,33 +358,33 @@
                                                      value_string_tmp,
                                                      sizeof(value_string_tmp))
                         == OK) {
-                        returnStr += value_string_tmp;
+                        returnStr << value_string_tmp;
                     } else {
-                        returnStr.appendFormat("%" PRId32 " ", *(int32_t*)(data_ptr + index));
+                        returnStr << fmt::sprintf("%" PRId32 " ", *(int32_t*)(data_ptr + index));
                     }
                     break;
                 case TYPE_FLOAT:
-                    returnStr.appendFormat("%0.8f ", *(float*)(data_ptr + index));
+                    returnStr << fmt::sprintf("%0.8f ", *(float*)(data_ptr + index));
                     break;
                 case TYPE_INT64:
-                    returnStr.appendFormat("%" PRId64 " ", *(int64_t*)(data_ptr + index));
+                    returnStr << fmt::sprintf("%" PRId64 " ", *(int64_t*)(data_ptr + index));
                     break;
                 case TYPE_DOUBLE:
-                    returnStr.appendFormat("%0.8f ", *(double*)(data_ptr + index));
+                    returnStr << fmt::sprintf("%0.8f ", *(double*)(data_ptr + index));
                     break;
                 case TYPE_RATIONAL: {
                     int32_t numerator = *(int32_t*)(data_ptr + index);
                     int32_t denominator = *(int32_t*)(data_ptr + index + 4);
-                    returnStr.appendFormat("(%d / %d) ", numerator, denominator);
+                    returnStr << fmt::sprintf("(%d / %d) ", numerator, denominator);
                     break;
                 }
                 default:
-                    returnStr += "??? ";
+                    returnStr << "??? ";
             }
         }
-        returnStr += "]\n";
+        returnStr << "]\n";
     }
-    return returnStr;
+    return std::move(returnStr.str());
 }
 
 template<typename T>
diff --git a/services/camera/libcameraservice/utils/TagMonitor.h b/services/camera/libcameraservice/utils/TagMonitor.h
index 9ded15d..bff4de0 100644
--- a/services/camera/libcameraservice/utils/TagMonitor.h
+++ b/services/camera/libcameraservice/utils/TagMonitor.h
@@ -21,9 +21,9 @@
 #include <atomic>
 #include <mutex>
 #include <unordered_map>
+#include <string>
 
 #include <utils/RefBase.h>
-#include <utils/String8.h>
 #include <utils/Timers.h>
 
 #include <media/RingBuffer.h>
@@ -42,7 +42,7 @@
   public:
 
     // Monitor argument
-    static const String16 kMonitorOption;
+    static const std::string kMonitorOption;
 
     enum eventSource {
         REQUEST,
@@ -59,7 +59,7 @@
     // If invalid, do nothing.
     // Recognizes "3a" as a shortcut for enabling tracking 3A state, mode, and
     // triggers
-    void parseTagsToMonitor(String8 tagNames);
+    void parseTagsToMonitor(std::string tagNames);
 
     // Disable monitoring; does not clear the event log
     void disableMonitoring();
@@ -85,8 +85,8 @@
     // function.
     void dumpMonitoredTagEventsToVectorLocked(std::vector<std::string> &out);
 
-    static String8 getEventDataString(const uint8_t* data_ptr, uint32_t tag, int type, int count,
-                                      int indentation);
+    static std::string getEventDataString(const uint8_t* data_ptr, uint32_t tag, int type,
+            int count, int indentation);
 
     void monitorSingleMetadata(TagMonitor::eventSource source, int64_t frameNumber,
             nsecs_t timestamp, const std::string& cameraId, uint32_t tag,
diff --git a/services/mediametrics/AudioAnalytics.cpp b/services/mediametrics/AudioAnalytics.cpp
index 59d1ae4..bd4ac38 100644
--- a/services/mediametrics/AudioAnalytics.cpp
+++ b/services/mediametrics/AudioAnalytics.cpp
@@ -242,6 +242,7 @@
     "channel_count_hardware",
     "sample_rate_hardware",
     "uid",
+    "sample_rate_client",
 };
 
 static constexpr const char * HeadTrackerDeviceEnabledFields[] {
@@ -1379,6 +1380,10 @@
 
     const auto uid = item->getUid();
 
+    int32_t sampleRateClient = 0;
+    mAudioAnalytics.mAnalyticsState->timeMachine().get(
+            key, AMEDIAMETRICS_PROP_SAMPLERATECLIENT, &sampleRateClient);
+
     LOG(LOG_LEVEL) << "key:" << key
             << " path:" << path
             << " direction:" << direction << "(" << directionStr << ")"
@@ -1402,7 +1407,8 @@
             << " format_hardware:" << formatHardware << "(" << formatHardwareStr << ")"
             << " channel_count_hardware:" << channelCountHardware
             << " sample_rate_hardware: " << sampleRateHardware
-            << " uid: " << uid;
+            << " uid: " << uid
+            << " sample_rate_client: " << sampleRateClient;
 
     if (mAudioAnalytics.mDeliverStatistics) {
         const stats::media_metrics::BytesField bf_serialized(
@@ -1431,6 +1437,7 @@
                 , channelCountHardware
                 , sampleRateHardware
                 , uid
+                , sampleRateClient
                 );
         std::stringstream ss;
         ss << "result:" << result;
@@ -1458,6 +1465,7 @@
                 , channelCountHardware
                 , sampleRateHardware
                 , uid
+                , sampleRateClient
                 );
         ss << " " << fieldsStr;
         std::string str = ss.str();
diff --git a/services/mediaresourcemanager/fuzzer/Android.bp b/services/mediaresourcemanager/fuzzer/Android.bp
index d98974f..f38a085 100644
--- a/services/mediaresourcemanager/fuzzer/Android.bp
+++ b/services/mediaresourcemanager/fuzzer/Android.bp
@@ -27,21 +27,18 @@
     default_applicable_licenses: ["frameworks_av_license"],
 }
 
-cc_fuzz {
-    name: "mediaresourcemanager_fuzzer",
-    srcs: [
-        "mediaresourcemanager_fuzzer.cpp",
+cc_defaults {
+    name: "mediaresourcemanager_fuzzer_defaults",
+    defaults: [
+        "service_fuzzer_defaults",
     ],
     static_libs: [
         "liblog",
         "libresourcemanagerservice",
     ],
     shared_libs: [
-        "libbinder",
-        "libbinder_ndk",
         "libmedia",
         "libmediautils",
-        "libutils",
         "libstats_media_metrics",
         "libstatspull",
         "libstatssocket",
@@ -54,3 +51,39 @@
         componentid: 155276,
     },
 }
+
+cc_fuzz {
+    name: "mediaresourcemanager_fuzzer",
+    defaults: [
+        "mediaresourcemanager_fuzzer_defaults",
+    ],
+    srcs: [
+        "mediaresourcemanager_fuzzer.cpp",
+    ],
+}
+
+cc_fuzz {
+    name: "resourcemanager_service_fuzzer",
+    defaults: [
+        "mediaresourcemanager_fuzzer_defaults",
+    ],
+    srcs: [
+        "resourcemanager_service_fuzzer.cpp",
+    ],
+}
+
+cc_fuzz {
+    name: "resourceobserver_service_fuzzer",
+    defaults: [
+        "mediaresourcemanager_fuzzer_defaults",
+    ],
+    static_libs: [
+        "resourceobserver_aidl_interface-V1-ndk",
+    ],
+    srcs: [
+        "resourceobserver_service_fuzzer.cpp",
+    ],
+    fuzz_config: {
+        triage_assignee: "waghpawan@google.com",
+    },
+}
diff --git a/services/mediaresourcemanager/fuzzer/resourcemanager_service_fuzzer.cpp b/services/mediaresourcemanager/fuzzer/resourcemanager_service_fuzzer.cpp
new file mode 100644
index 0000000..ca10d20
--- /dev/null
+++ b/services/mediaresourcemanager/fuzzer/resourcemanager_service_fuzzer.cpp
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android/binder_interface_utils.h>
+
+#include <fuzzbinder/libbinder_ndk_driver.h>
+#include <fuzzer/FuzzedDataProvider.h>
+
+#include "ResourceManagerService.h"
+
+using android::fuzzService;
+using android::ResourceManagerService;
+using ndk::SharedRefBase;
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+   auto service = SharedRefBase::make<ResourceManagerService>();
+   fuzzService(service->asBinder().get(), FuzzedDataProvider(data, size));
+   return 0;
+}
diff --git a/services/mediaresourcemanager/fuzzer/resourceobserver_service_fuzzer.cpp b/services/mediaresourcemanager/fuzzer/resourceobserver_service_fuzzer.cpp
new file mode 100644
index 0000000..e69368d
--- /dev/null
+++ b/services/mediaresourcemanager/fuzzer/resourceobserver_service_fuzzer.cpp
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android/binder_interface_utils.h>
+
+#include <fuzzbinder/libbinder_ndk_driver.h>
+#include <fuzzer/FuzzedDataProvider.h>
+
+#include "ResourceObserverService.h"
+
+using android::fuzzService;
+using android::ResourceObserverService;
+using ndk::SharedRefBase;
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+   auto service = SharedRefBase::make<ResourceObserverService>();
+   fuzzService(service->asBinder().get(), FuzzedDataProvider(data, size));
+   return 0;
+}
diff --git a/services/oboeservice/AAudioServiceEndpointMMAP.cpp b/services/oboeservice/AAudioServiceEndpointMMAP.cpp
index 7f228c7..2ef6fe5 100644
--- a/services/oboeservice/AAudioServiceEndpointMMAP.cpp
+++ b/services/oboeservice/AAudioServiceEndpointMMAP.cpp
@@ -45,6 +45,8 @@
 #define OUTPUT_ESTIMATED_HARDWARE_OFFSET_NANOS  (3 * AAUDIO_NANOS_PER_MILLISECOND)
 #define INPUT_ESTIMATED_HARDWARE_OFFSET_NANOS   (-1 * AAUDIO_NANOS_PER_MILLISECOND)
 
+#define AAUDIO_MAX_OPEN_ATTEMPTS    10
+
 using namespace android;  // TODO just import names needed
 using namespace aaudio;   // TODO just import names needed
 
@@ -77,14 +79,23 @@
         {AUDIO_FORMAT_PCM_24_BIT_PACKED, AUDIO_FORMAT_PCM_16_BIT}
 };
 
-audio_format_t getNextFormatToTry(audio_format_t curFormat, audio_format_t returnedFromAPM) {
-    if (returnedFromAPM != AUDIO_FORMAT_DEFAULT) {
-        return returnedFromAPM;
-    }
+audio_format_t getNextFormatToTry(audio_format_t curFormat) {
     const auto it = NEXT_FORMAT_TO_TRY.find(curFormat);
-    return it != NEXT_FORMAT_TO_TRY.end() ? it->second : AUDIO_FORMAT_DEFAULT;
+    return it != NEXT_FORMAT_TO_TRY.end() ? it->second : curFormat;
 }
 
+struct configComp {
+    bool operator() (const audio_config_base_t& lhs, const audio_config_base_t& rhs) const {
+        if (lhs.sample_rate != rhs.sample_rate) {
+            return lhs.sample_rate < rhs.sample_rate;
+        } else if (lhs.channel_mask != rhs.channel_mask) {
+            return lhs.channel_mask < rhs.channel_mask;
+        } else {
+            return lhs.format < rhs.format;
+        }
+    }
+};
+
 } // namespace
 
 aaudio_result_t AAudioServiceEndpointMMAP::open(const aaudio::AAudioStreamRequest &request) {
@@ -101,60 +112,66 @@
         legacy2aidl_pid_t_int32_t(IPCThreadState::self()->getCallingPid()));
 
     audio_format_t audioFormat = getFormat();
-    std::set<audio_format_t> formatsTried;
-    while (true) {
-        if (formatsTried.find(audioFormat) != formatsTried.end()) {
+    int32_t sampleRate = getSampleRate();
+    if (sampleRate == AAUDIO_UNSPECIFIED) {
+        sampleRate = AAUDIO_SAMPLE_RATE_DEFAULT;
+    }
+
+    const aaudio_direction_t direction = getDirection();
+    audio_config_base_t config;
+    config.format = audioFormat;
+    config.sample_rate = sampleRate;
+    config.channel_mask = AAudio_getChannelMaskForOpen(
+            getChannelMask(), getSamplesPerFrame(), direction == AAUDIO_DIRECTION_INPUT);
+
+    std::set<audio_config_base_t, configComp> configsTried;
+    int32_t numberOfAttempts = 0;
+    while (numberOfAttempts < AAUDIO_MAX_OPEN_ATTEMPTS) {
+        if (configsTried.find(config) != configsTried.end()) {
             // APM returning something that has already tried.
-            ALOGW("Have already tried to open with format=%#x, but failed before", audioFormat);
+            ALOGW("Have already tried to open with format=%#x and sr=%d, but failed before",
+                  config.format, config.sample_rate);
             break;
         }
-        formatsTried.insert(audioFormat);
+        configsTried.insert(config);
 
-        audio_format_t nextFormatToTry = AUDIO_FORMAT_DEFAULT;
-        result = openWithFormat(audioFormat, &nextFormatToTry);
+        audio_config_base_t previousConfig = config;
+        result = openWithConfig(&config);
         if (result != AAUDIO_ERROR_UNAVAILABLE) {
             // Return if it is successful or there is an error that is not
             // AAUDIO_ERROR_UNAVAILABLE happens.
-            ALOGI("Opened format=%#x with result=%d", audioFormat, result);
+            ALOGI("Opened format=%#x sr=%d, with result=%d", previousConfig.format,
+                    previousConfig.sample_rate, result);
             break;
         }
 
-        nextFormatToTry = getNextFormatToTry(audioFormat, nextFormatToTry);
-        ALOGD("%s() %#x failed, perhaps due to format. Try again with %#x",
-              __func__, audioFormat, nextFormatToTry);
-        audioFormat = nextFormatToTry;
-        if (audioFormat == AUDIO_FORMAT_DEFAULT) {
-            // Nothing else to try
-            break;
+        // Try other formats if the config from APM is the same as our current config.
+        // Some HALs may report its format support incorrectly.
+        if ((previousConfig.format == config.format) &&
+                (previousConfig.sample_rate == config.sample_rate)) {
+            config.format = getNextFormatToTry(config.format);
         }
+
+        ALOGD("%s() %#x %d failed, perhaps due to format or sample rate. Try again with %#x %d",
+                __func__, previousConfig.format, previousConfig.sample_rate, config.format,
+                config.sample_rate);
+        numberOfAttempts++;
     }
     return result;
 }
 
-aaudio_result_t AAudioServiceEndpointMMAP::openWithFormat(
-        audio_format_t audioFormat, audio_format_t* nextFormatToTry) {
+aaudio_result_t AAudioServiceEndpointMMAP::openWithConfig(
+        audio_config_base_t* config) {
     aaudio_result_t result = AAUDIO_OK;
-    audio_config_base_t config;
+    audio_config_base_t currentConfig = *config;
     audio_port_handle_t deviceId;
 
     const audio_attributes_t attributes = getAudioAttributesFrom(this);
 
     deviceId = mRequestedDeviceId;
 
-    // Fill in config
-    config.format = audioFormat;
-
-    int32_t aaudioSampleRate = getSampleRate();
-    if (aaudioSampleRate == AAUDIO_UNSPECIFIED) {
-        aaudioSampleRate = AAUDIO_SAMPLE_RATE_DEFAULT;
-    }
-    config.sample_rate = aaudioSampleRate;
-
     const aaudio_direction_t direction = getDirection();
 
-    config.channel_mask = AAudio_getChannelMaskForOpen(
-            getChannelMask(), getSamplesPerFrame(), direction == AAUDIO_DIRECTION_INPUT);
-
     if (direction == AAUDIO_DIRECTION_OUTPUT) {
         mHardwareTimeOffsetNanos = OUTPUT_ESTIMATED_HARDWARE_OFFSET_NANOS; // frames at DAC later
 
@@ -177,11 +194,11 @@
     // Open HAL stream. Set mMmapStream
     ALOGD("%s trying to open MMAP stream with format=%#x, "
           "sample_rate=%u, channel_mask=%#x, device=%d",
-          __func__, config.format, config.sample_rate,
-          config.channel_mask, deviceId);
+          __func__, config->format, config->sample_rate,
+          config->channel_mask, deviceId);
     const status_t status = MmapStreamInterface::openMmapStream(streamDirection,
                                                                 &attributes,
-                                                                &config,
+                                                                config,
                                                                 mMmapClient,
                                                                 &deviceId,
                                                                 &sessionId,
@@ -195,9 +212,9 @@
         // not match the hardware.
         ALOGD("%s() - openMmapStream() returned status=%d, suggested format=%#x, sample_rate=%u, "
               "channel_mask=%#x",
-              __func__, status, config.format, config.sample_rate, config.channel_mask);
-        *nextFormatToTry = config.format != audioFormat ? config.format
-                                                        : *nextFormatToTry;
+              __func__, status, config->format, config->sample_rate, config->channel_mask);
+        // Keep the channel mask of the current config
+        config->channel_mask = currentConfig.channel_mask;
         return AAUDIO_ERROR_UNAVAILABLE;
     }
 
@@ -217,7 +234,7 @@
     setSessionId(actualSessionId);
 
     ALOGD("%s(format = 0x%X) deviceId = %d, sessionId = %d",
-          __func__, audioFormat, getDeviceId(), getSessionId());
+          __func__, config->format, getDeviceId(), getSessionId());
 
     // Create MMAP/NOIRQ buffer.
     result = createMmapBuffer();
@@ -227,11 +244,11 @@
 
     // Get information about the stream and pass it back to the caller.
     setChannelMask(AAudioConvert_androidToAAudioChannelMask(
-            config.channel_mask, getDirection() == AAUDIO_DIRECTION_INPUT,
-            AAudio_isChannelIndexMask(config.channel_mask)));
+            config->channel_mask, getDirection() == AAUDIO_DIRECTION_INPUT,
+            AAudio_isChannelIndexMask(config->channel_mask)));
 
-    setFormat(config.format);
-    setSampleRate(config.sample_rate);
+    setFormat(config->format);
+    setSampleRate(config->sample_rate);
     setHardwareSampleRate(getSampleRate());
     setHardwareFormat(getFormat());
     setHardwareSamplesPerFrame(AAudioConvert_channelMaskToCount(getChannelMask()));
diff --git a/services/oboeservice/AAudioServiceEndpointMMAP.h b/services/oboeservice/AAudioServiceEndpointMMAP.h
index 38cf0ba..f19005c 100644
--- a/services/oboeservice/AAudioServiceEndpointMMAP.h
+++ b/services/oboeservice/AAudioServiceEndpointMMAP.h
@@ -97,7 +97,7 @@
 
 private:
 
-    aaudio_result_t openWithFormat(audio_format_t audioFormat, audio_format_t* nextFormatToTry);
+    aaudio_result_t openWithConfig(audio_config_base_t* config);
 
     aaudio_result_t createMmapBuffer();
 
diff --git a/services/oboeservice/AAudioServiceStreamBase.h b/services/oboeservice/AAudioServiceStreamBase.h
index bc7ccde..8f51ce4 100644
--- a/services/oboeservice/AAudioServiceStreamBase.h
+++ b/services/oboeservice/AAudioServiceStreamBase.h
@@ -220,18 +220,6 @@
         return mSuspended;
     }
 
-    bool isCloseNeeded() const {
-        return mCloseNeeded.load();
-    }
-
-    /**
-     * Mark this stream as needing to be closed.
-     * Once marked for closing, it cannot be unmarked.
-     */
-    void markCloseNeeded() {
-        mCloseNeeded.store(true);
-    }
-
     virtual const char *getTypeText() const { return "Base"; }
 
 protected:
@@ -419,12 +407,8 @@
     aaudio_handle_t         mHandle = -1;
     bool                    mFlowing = false;
 
-    // This indicates that a stream that is being referenced by a binder call
-    // and needs to closed.
-    std::atomic<bool>       mCloseNeeded{false}; // TODO remove
-
     // 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.
+    // for example a full message queue.
     std::atomic<bool>       mSuspended{false};
 
     bool                    mDisconnected GUARDED_BY(mLock) {false};
diff --git a/services/oboeservice/AAudioThread.cpp b/services/oboeservice/AAudioThread.cpp
index 549fa59..502d773 100644
--- a/services/oboeservice/AAudioThread.cpp
+++ b/services/oboeservice/AAudioThread.cpp
@@ -75,7 +75,9 @@
 
 aaudio_result_t AAudioThread::stop() {
     if (!mHasThread) {
-        ALOGE("stop() but no thread running");
+        // There can be cases that the thread is just created but not started.
+        // Logging as warning to attract attention but not too serious.
+        ALOGW("stop() but no thread running");
         return AAUDIO_ERROR_INVALID_STATE;
     }
 
diff --git a/services/oboeservice/Android.bp b/services/oboeservice/Android.bp
index c5080a4..3521979 100644
--- a/services/oboeservice/Android.bp
+++ b/services/oboeservice/Android.bp
@@ -78,12 +78,38 @@
 
 ]
 
+cc_defaults {
+    name: "libaaudioservice_dependencies",
 
-cc_library {
+    shared_libs: [
+        "libaaudio_internal",
+        "libaudioclient",
+        "libaudioutils",
+        "libmedia_helper",
+        "libmediametrics",
+        "libmediautils",
+        "libbase",
+        "libbinder",
+        "libcutils",
+        "liblog",
+        "libutils",
+        "aaudio-aidl-cpp",
+        "framework-permission-aidl-cpp",
+        "libaudioclient_aidl_conversion",
+        "packagemanager_aidl-cpp",
+    ],
+
+    static_libs: [
+        "libaudioflinger",
+    ]
+}
+
+cc_library_static {
 
     name: "libaaudioservice",
 
     defaults: [
+        "libaaudioservice_dependencies",
         "latest_android_media_audio_common_types_cpp_shared",
     ],
 
@@ -116,25 +142,6 @@
         "-Werror",
     ],
 
-    shared_libs: [
-        "libaaudio_internal",
-        "libaudioclient",
-        "libaudioflinger",
-        "libaudioutils",
-        "libmedia_helper",
-        "libmediametrics",
-        "libmediautils",
-        "libbase",
-        "libbinder",
-        "libcutils",
-        "liblog",
-        "libutils",
-        "aaudio-aidl-cpp",
-        "framework-permission-aidl-cpp",
-        "libaudioclient_aidl_conversion",
-        "packagemanager_aidl-cpp",
-    ],
-
     export_shared_lib_headers: [
         "libaaudio_internal",
         "framework-permission-aidl-cpp",
diff --git a/services/oboeservice/fuzzer/oboeservice_fuzzer.cpp b/services/oboeservice/fuzzer/oboeservice_fuzzer.cpp
index f047065..f5c2e6c 100644
--- a/services/oboeservice/fuzzer/oboeservice_fuzzer.cpp
+++ b/services/oboeservice/fuzzer/oboeservice_fuzzer.cpp
@@ -403,13 +403,6 @@
 
     request.getConfiguration().setBufferCapacity(fdp.ConsumeIntegral<int32_t>());
 
-    request.getConfiguration().setHardwareSampleRate(fdp.ConsumeIntegral<int32_t>());
-    request.getConfiguration().setHardwareSamplesPerFrame(fdp.ConsumeIntegral<int32_t>());
-    request.getConfiguration().setHardwareFormat((audio_format_t)(
-        fdp.ConsumeBool()
-            ? fdp.ConsumeIntegral<int32_t>()
-            : kAAudioFormats[fdp.ConsumeIntegralInRange<int32_t>(0, kNumAAudioFormats - 1)]));
-
     auto streamHandleInfo = mClient->openStream(request, configurationOutput);
     if (streamHandleInfo.getHandle() < 0) {
         // invalid request, stream not opened.
diff --git a/services/tuner/Android.bp b/services/tuner/Android.bp
index ea5139d..e29d520 100644
--- a/services/tuner/Android.bp
+++ b/services/tuner/Android.bp
@@ -86,6 +86,7 @@
         "android.hardware.tv.tuner@1.1",
         "android.hardware.tv.tuner-V2-ndk",
         "libbase",
+        "libcutils",
         "libbinder",
         "libfmq",
         "libhidlbase",
diff --git a/services/tuner/main_tunerservice.cpp b/services/tuner/main_tunerservice.cpp
index 90f1731..acfaf8a 100644
--- a/services/tuner/main_tunerservice.cpp
+++ b/services/tuner/main_tunerservice.cpp
@@ -17,6 +17,7 @@
 #include <android-base/logging.h>
 #include <binder/IPCThreadState.h>
 #include <binder/IServiceManager.h>
+#include <cutils/properties.h>
 #include <utils/Log.h>
 #include <hidl/HidlTransportSupport.h>
 
@@ -31,6 +32,11 @@
 int main() {
     ALOGD("Tuner service starting");
 
+    if (!property_get_bool("tuner.server.enable", false)) {
+        ALOGD("tuner is not enabled, terminating");
+        return 0;
+    }
+
     sp<ProcessState> proc(ProcessState::self());
     sp<IServiceManager> sm = defaultServiceManager();
     hardware::configureRpcThreadpool(16, true);