Merge "frameworks/av: Change url from google cloud to lorry" into main am: 52a2a799aa am: f1fc5f5932

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

Change-Id: Ibcabc94d5afd13f27a997e9771d7d6486a8fc95e
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/camera/ndk/Android.bp b/camera/ndk/Android.bp
index 24a11e3..921aab2 100644
--- a/camera/ndk/Android.bp
+++ b/camera/ndk/Android.bp
@@ -177,6 +177,7 @@
     shared_libs: [
         "libcamera2ndk_vendor",
         "libcamera_metadata",
+        "libhidlbase",
         "libmediandk",
         "libnativewindow",
         "libutils",
@@ -186,6 +187,7 @@
     ],
     static_libs: [
         "android.hardware.camera.common@1.0-helper",
+        "android.hidl.token@1.0",
     ],
     cflags: [
         "-D__ANDROID_VNDK__",
diff --git a/camera/ndk/include/camera/NdkCameraMetadataTags.h b/camera/ndk/include/camera/NdkCameraMetadataTags.h
index bd679e5..fe0ef67 100644
--- a/camera/ndk/include/camera/NdkCameraMetadataTags.h
+++ b/camera/ndk/include/camera/NdkCameraMetadataTags.h
@@ -584,6 +584,19 @@
      * <p>Only constrains auto-exposure (AE) algorithm, not
      * manual control of ACAMERA_SENSOR_EXPOSURE_TIME and
      * ACAMERA_SENSOR_FRAME_DURATION.</p>
+     * <p>Note that the actual achievable max framerate also depends on the minimum frame
+     * duration of the output streams. The max frame rate will be
+     * <code>min(aeTargetFpsRange.maxFps, 1 / max(individual stream min durations)</code>. For example,
+     * if the application sets this key to <code>{60, 60}</code>, but the maximum minFrameDuration among
+     * all configured streams is 33ms, the maximum framerate won't be 60fps, but will be
+     * 30fps.</p>
+     * <p>To start a CaptureSession with a target FPS range different from the
+     * capture request template's default value, the application
+     * is strongly recommended to call
+     * {@link ACameraDevice_createCaptureSessionWithSessionParameters }
+     * with the target fps range before creating the capture session. The aeTargetFpsRange is
+     * typically a session parameter. Specifying it at session creation time helps avoid
+     * session reconfiguration delays in cases like 60fps or high speed recording.</p>
      *
      * @see ACAMERA_SENSOR_EXPOSURE_TIME
      * @see ACAMERA_SENSOR_FRAME_DURATION
@@ -1128,6 +1141,12 @@
      * ACAMERA_CONTROL_VIDEO_STABILIZATION_MODE field will return
      * OFF if the recording output is not stabilized, or if there are no output
      * Surface types that can be stabilized.</p>
+     * <p>The application is strongly recommended to call
+     * {@link ACameraDevice_createCaptureSessionWithSessionParameters }
+     * with the desired video stabilization mode before creating the capture session.
+     * Video stabilization mode is a session parameter on many devices. Specifying
+     * it at session creation time helps avoid reconfiguration delay caused by difference
+     * between the default value and the first CaptureRequest.</p>
      * <p>If a camera device supports both this mode and OIS
      * (ACAMERA_LENS_OPTICAL_STABILIZATION_MODE), turning both modes on may
      * produce undesirable interaction, so it is recommended not to enable
@@ -5384,7 +5403,7 @@
      * <a href="https://developer.android.com/reference/android/hardware/camera2/CameraMetadata.html#SENSOR_PIXEL_MODE_DEFAULT">CameraMetadata#SENSOR_PIXEL_MODE_DEFAULT</a> mode.
      * They can be queried through
      * <a href="https://developer.android.com/reference/android/hardware/camera2/CameraCharacteristics.html#get">CameraCharacteristics#get</a> with
-     * <a href="https://developer.android.com/reference/CameraCharacteristics.html#SCALER_STREAM_CONFIGURATION_MAP_MAXIMUM_RESOLUTION)">CameraCharacteristics#SCALER_STREAM_CONFIGURATION_MAP_MAXIMUM_RESOLUTION)</a>.
+     * <a href="https://developer.android.com/reference/CameraCharacteristics.html#SCALER_STREAM_CONFIGURATION_MAP_MAXIMUM_RESOLUTION">CameraCharacteristics#SCALER_STREAM_CONFIGURATION_MAP_MAXIMUM_RESOLUTION</a>.
      * Unless reported by both
      * <a href="https://developer.android.com/reference/android/hardware/camera2/params/StreamConfigurationMap.html">StreamConfigurationMap</a>s, the outputs from
      * <code>android.scaler.streamConfigurationMapMaximumResolution</code> and
@@ -5399,13 +5418,12 @@
      * <ul>
      * <li>
      * <p>The mandatory stream combinations listed in
-     *   <a href="https://developer.android.com/reference/android/hardware/camera2/CameraCharacteristics/mandatoryMaximumResolutionStreamCombinations.html">mandatoryMaximumResolutionStreamCombinations</a>
-     *   would not apply.</p>
+     *   android.scaler.mandatoryMaximumResolutionStreamCombinations  would not apply.</p>
      * </li>
      * <li>
      * <p>The bayer pattern of {@code RAW} streams when
      *   <a href="https://developer.android.com/reference/android/hardware/camera2/CameraMetadata.html#SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION">CameraMetadata#SENSOR_PIXEL_MODE_MAXIMUM_RESOLUTION</a>
-     *   is selected will be the one listed in <a href="https://developer.android.com/reference/android/sensor/info/binningFactor.html">binningFactor</a>.</p>
+     *   is selected will be the one listed in ACAMERA_SENSOR_INFO_BINNING_FACTOR.</p>
      * </li>
      * <li>
      * <p>The following keys will always be present:</p>
@@ -5419,6 +5437,7 @@
      * </ul>
      *
      * @see ACAMERA_SENSOR_INFO_ACTIVE_ARRAY_SIZE_MAXIMUM_RESOLUTION
+     * @see ACAMERA_SENSOR_INFO_BINNING_FACTOR
      * @see ACAMERA_SENSOR_INFO_PIXEL_ARRAY_SIZE_MAXIMUM_RESOLUTION
      * @see ACAMERA_SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE_MAXIMUM_RESOLUTION
      */
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/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/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/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/libstagefright/rtsp/ARTPWriter.cpp b/media/libstagefright/rtsp/ARTPWriter.cpp
index 41e9aff..bc57ef7 100644
--- a/media/libstagefright/rtsp/ARTPWriter.cpp
+++ b/media/libstagefright/rtsp/ARTPWriter.cpp
@@ -105,6 +105,7 @@
 
     mRTCPAddr = mRTPAddr;
     mRTCPAddr.sin_port = htons(ntohs(mRTPAddr.sin_port) | 1);
+    mVPSBuf = NULL;
     mSPSBuf = NULL;
     mPPSBuf = NULL;
 
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 caee37d..7b19ac0 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/include/media/NdkImageReader.h b/media/ndk/include/media/NdkImageReader.h
index b6dcaae..b722b74 100644
--- a/media/ndk/include/media/NdkImageReader.h
+++ b/media/ndk/include/media/NdkImageReader.h
@@ -534,15 +534,22 @@
  * Get the native_handle_t corresponding to the ANativeWindow owned by the
  * AImageReader provided.
  *
+ * This is deprecated in API level 35 and will return AMEDIA_ERROR_UNKNOWN.
+ * The native_handle_t is no longer used with AIDL interfaces and
+ * ANativeWindow is used directly instead.
+ * Use AImageRead_getWindow to get the ANativeWindow and use that object.
+ *
  * @param reader The image reader of interest.
  * @param handle The output native_handle_t. This native handle is owned by
  *               this image reader.
  *
  * @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/services/audioflinger/Android.bp b/services/audioflinger/Android.bp
index 17e6d15..0cd6243 100644
--- a/services/audioflinger/Android.bp
+++ b/services/audioflinger/Android.bp
@@ -149,6 +149,7 @@
 
     srcs: [
         "AudioFlinger.cpp",
+        "Client.cpp",
         "DeviceEffectManager.cpp",
         "Effects.cpp",
         "MelReporter.cpp",
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 18ab3a7..0d539c0 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,43 @@
 #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 "AudioFlinger.h"
 
+//#define BUFLOG_NDEBUG 0
+#include <afutils/BufLog.h>
+#include <afutils/DumpTryLock.h>
+#include <afutils/Permission.h>
+#include <afutils/PropertyUtils.h>
+#include <afutils/TypedLogger.h>
 #include <android-base/stringprintf.h>
 #include <android/media/IAudioPolicyService.h>
-#include <android/os/IExternalVibratorService.h>
+#include <audiomanager/IAudioManager.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 <cutils/properties.h>
+#include <media/AidlConversion.h>
 #include <media/AudioParameter.h>
+#include <media/AudioValidator.h>
+#include <media/IMediaLogService.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"
-#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 <media/AidlConversion.h>
-#include <media/AudioValidator.h>
-#include <media/nbaio/Pipe.h>
-#include <media/nbaio/PipeReader.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 +95,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 +115,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 +221,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() {
@@ -314,26 +231,6 @@
 }
 
 AudioFlinger::AudioFlinger()
-    : mMediaLogNotifier(new AudioFlinger::MediaLogNotifier()),
-      mPrimaryHardwareDev(NULL),
-      mAudioHwDevs(NULL),
-      mHardwareStatus(AUDIO_HW_IDLE),
-      mMasterVolume(1.0f),
-      mMasterMute(false),
-      // mNextUniqueId(AUDIO_UNIQUE_ID_USE_MAX),
-      mMode(AUDIO_MODE_INVALID),
-      mBtNrecIsOff(false),
-      mIsLowRamDevice(true),
-      mIsDeviceTypeKnown(false),
-      mTotalMemory(0),
-      mClientSharedHeapSize(kMinimumClientSharedHeapSizeBytes),
-      mGlobalEffectEnableTime(0),
-      mPatchPanel(this),
-      mPatchCommandThread(sp<PatchCommandThread>::make()),
-      mDeviceEffectManager(sp<DeviceEffectManager>::make(*this)),
-      mMelReporter(sp<MelReporter>::make(*this)),
-      mSystemReady(false),
-      mBluetoothLatencyModesEnabled(true)
 {
     // Move the audio session unique ID generator start base as time passes to limit risk of
     // generating the same ID again after an audioserver restart.
@@ -370,9 +267,6 @@
     // in bad state, reset the state upon service start.
     BatteryNotifier::getInstance().noteResetAudio();
 
-    mDevicesFactoryHal = DevicesFactoryHalInterface::create();
-    mEffectsFactoryHal = audioflinger::EffectConfiguration::getEffectsFactoryHal();
-
     mMediaLogNotifier->run("MediaLogNotifier");
     std::vector<pid_t> halPids;
     mDevicesFactoryHal->getHalPids(&halPids);
@@ -386,26 +280,13 @@
 
 void AudioFlinger::onFirstRef()
 {
-    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));
-        }
-    }
+    audio_utils::lock_guard _l(mutex());
 
     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 +294,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) {
@@ -422,20 +306,20 @@
 
 status_t AudioFlinger::setVibratorInfos(
         const std::vector<media::AudioVibratorInfo>& vibratorInfos) {
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mutex());
     mAudioVibratorInfos = vibratorInfos;
     return NO_ERROR;
 }
 
 status_t AudioFlinger::updateSecondaryOutputs(
         const TrackSecondaryOutputsMap& trackSecondaryOutputs) {
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mutex());
     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();
+            audio_utils::lock_guard _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);
@@ -450,13 +334,13 @@
 
 status_t AudioFlinger::getMmapPolicyInfos(
             AudioMMapPolicyType policyType, std::vector<AudioMMapPolicyInfo> *policyInfos) {
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mutex());
     if (const auto it = mPolicyInfos.find(policyType); it != mPolicyInfos.end()) {
         *policyInfos = it->second;
         return NO_ERROR;
     }
     if (mDevicesFactoryHal->getHalVersion() > kMaxAAudioPropertyDeviceHalVersion) {
-        AutoMutex lock(mHardwareLock);
+        audio_utils::lock_guard lock(hardwareMutex());
         for (size_t i = 0; i < mAudioHwDevs.size(); ++i) {
             AudioHwDevice *dev = mAudioHwDevs.valueAt(i);
             std::vector<AudioMMapPolicyInfo> infos;
@@ -476,21 +360,21 @@
     return NO_ERROR;
 }
 
-int32_t AudioFlinger::getAAudioMixerBurstCount() {
-    Mutex::Autolock _l(mLock);
+int32_t AudioFlinger::getAAudioMixerBurstCount() const {
+    audio_utils::lock_guard _l(mutex());
     return mAAudioBurstsPerBuffer;
 }
 
-int32_t AudioFlinger::getAAudioHardwareBurstMinUsec() {
-    Mutex::Autolock _l(mLock);
+int32_t AudioFlinger::getAAudioHardwareBurstMinUsec() const {
+    audio_utils::lock_guard _l(mutex());
     return mAAudioHwBurstMinMicros;
 }
 
 status_t AudioFlinger::setDeviceConnectedState(const struct audio_port_v7 *port,
                                                media::DeviceConnectedState state) {
     status_t final_result = NO_INIT;
-    Mutex::Autolock _l(mLock);
-    AutoMutex lock(mHardwareLock);
+    audio_utils::lock_guard _l(mutex());
+    audio_utils::lock_guard lock(hardwareMutex());
     mHardwareStatus = AUDIO_HW_SET_CONNECTED_STATE;
     for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
         sp<DeviceHalInterface> dev = mAudioHwDevs.valueAt(i)->hwDevice();
@@ -510,8 +394,8 @@
 status_t AudioFlinger::setSimulateDeviceConnections(bool enabled) {
     bool at_least_one_succeeded = false;
     status_t last_error = INVALID_OPERATION;
-    Mutex::Autolock _l(mLock);
-    AutoMutex lock(mHardwareLock);
+    audio_utils::lock_guard _l(mutex());
+    audio_utils::lock_guard lock(hardwareMutex());
     mHardwareStatus = AUDIO_HW_SET_SIMULATE_CONNECTIONS;
     for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
         sp<DeviceHalInterface> dev = mAudioHwDevs.valueAt(i)->hwDevice();
@@ -527,7 +411,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 {};
     }
@@ -554,7 +438,7 @@
     }
 
     for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
-        // no mHardwareLock needed, as there are no other references to this
+        // no hardwareMutex() needed, as there are no other references to this
         delete mAudioHwDevs.valueAt(i);
     }
 
@@ -580,7 +464,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 +522,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) {
@@ -676,11 +560,14 @@
         return ret;
     }
 
+    // use unique_lock as we may selectively unlock.
+    audio_utils::unique_lock l(mutex());
+
     // 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;
@@ -688,12 +575,14 @@
         config->channel_mask = thread->channelMask();
         config->format = thread->format();
     } else {
+        l.unlock();
         if (direction == MmapStreamInterface::DIRECTION_OUTPUT) {
             AudioSystem::releaseOutput(portId);
         } else {
             AudioSystem::releaseInput(portId);
         }
         ret = NO_INIT;
+        // we don't reacquire the lock here as nothing left to do.
     }
 
     ALOGV("%s done status %d portId %d", __FUNCTION__, ret, portId);
@@ -701,37 +590,9 @@
     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);
+    audio_utils::lock_guard lock(hardwareMutex());
     AudioHwDevice *audioHwDevice = mAudioHwDevs.valueFor(device->ext.device.hw_module);
     if (audioHwDevice == nullptr) {
         return NO_INIT;
@@ -741,7 +602,7 @@
 
 status_t AudioFlinger::removeEffectFromHal(
         const struct audio_port_config *device, const sp<EffectHalInterface>& effect) {
-    AutoMutex lock(mHardwareLock);
+    audio_utils::lock_guard lock(hardwareMutex());
     AudioHwDevice *audioHwDevice = mAudioHwDevs.valueFor(device->ext.device.hw_module);
     if (audioHwDevice == nullptr) {
         return NO_INIT;
@@ -761,11 +622,11 @@
 {
     // if module is 0, the request comes from an old policy manager and we should load
     // well known modules
-    AutoMutex lock(mHardwareLock);
+    audio_utils::lock_guard lock(hardwareMutex());
     if (module == 0) {
         ALOGW("findSuitableHwDev_l() loading well know audio hw modules");
         for (size_t i = 0; i < arraysize(audio_interfaces); i++) {
-            loadHwModule_l(audio_interfaces[i]);
+            loadHwModule_ll(audio_interfaces[i]);
         }
         // then try to find a module supporting the requested device.
         for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
@@ -788,7 +649,7 @@
     return NULL;
 }
 
-void AudioFlinger::dumpClients(int fd, const Vector<String16>& args __unused)
+void AudioFlinger::dumpClients_ll(int fd, const Vector<String16>& args __unused)
 {
     String8 result;
 
@@ -822,17 +683,14 @@
 }
 
 
-void AudioFlinger::dumpInternals(int fd, const Vector<String16>& args __unused)
+void AudioFlinger::dumpInternals_l(int fd, const Vector<String16>& args __unused)
 {
     const size_t SIZE = 256;
     char buffer[SIZE];
     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.c_str(), result.size());
 
@@ -857,12 +715,6 @@
     write(fd, result.c_str(), 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,15 +722,15 @@
         dumpPermissionDenial(fd, args);
     } else {
         // get state of hardware lock
-        bool hardwareLocked = dumpTryLock(mHardwareLock);
+        const bool hardwareLocked = afutils::dumpTryLock(hardwareMutex());
         if (!hardwareLocked) {
             String8 result(kHardwareLockedString);
             write(fd, result.c_str(), result.size());
         } else {
-            mHardwareLock.unlock();
+            hardwareMutex().unlock();
         }
 
-        const bool locked = dumpTryLock(mLock);
+        const bool locked = afutils::dumpTryLock(mutex());
 
         // failed to lock - AudioFlinger is probably deadlocked
         if (!locked) {
@@ -886,7 +738,7 @@
             write(fd, result.c_str(), result.size());
         }
 
-        bool clientLocked = dumpTryLock(mClientLock);
+        const bool clientLocked = afutils::dumpTryLock(clientMutex());
         if (!clientLocked) {
             String8 result(kClientLockedString);
             write(fd, result.c_str(), result.size());
@@ -899,12 +751,12 @@
             write(fd, result.c_str(), result.size());
         }
 
-        dumpClients(fd, args);
+        dumpClients_ll(fd, args);
         if (clientLocked) {
-            mClientLock.unlock();
+            clientMutex().unlock();
         }
 
-        dumpInternals(fd, args);
+        dumpInternals_l(fd, args);
 
         // dump playback threads
         for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
@@ -934,7 +786,7 @@
             dev->dump(fd, args);
         }
 
-        mPatchPanel.dump(fd);
+        mPatchPanel->dump(fd);
 
         mDeviceEffectManager->dump(fd);
 
@@ -959,7 +811,7 @@
         BUFLOG_RESET;
 
         if (locked) {
-            mLock.unlock();
+            mutex().unlock();
         }
 
 #ifdef TEE_SINK
@@ -1029,14 +881,14 @@
     return NO_ERROR;
 }
 
-sp<AudioFlinger::Client> AudioFlinger::registerPid(pid_t pid)
+sp<Client> AudioFlinger::registerPid(pid_t pid)
 {
-    Mutex::Autolock _cl(mClientLock);
+    audio_utils::lock_guard _cl(clientMutex());
     // If pid is already in the mClients wp<> map, then use that entry
     // (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);
     }
 
@@ -1054,7 +906,7 @@
     // If allocation fails, consult the vector of previously unregistered writers
     // and garbage-collect one or more them until an allocation succeeds
     if (shared == 0) {
-        Mutex::Autolock _l(mUnregisteredWritersLock);
+        audio_utils::lock_guard _l(unregisteredWritersMutex());
         for (size_t count = mUnregisteredWriters.size(); count > 0; count--) {
             {
                 // Pick the oldest stale writer to garbage-collect
@@ -1094,7 +946,7 @@
     }
     // Rather than removing the writer immediately, append it to a queue of old writers to
     // be garbage-collected later.  This allows us to continue to view old logs for a while.
-    Mutex::Autolock _l(mUnregisteredWritersLock);
+    audio_utils::lock_guard _l(unregisteredWritersMutex());
     mUnregisteredWriters.push(writer);
 }
 
@@ -1107,8 +959,7 @@
     CreateTrackInput input = VALUE_OR_RETURN_STATUS(CreateTrackInput::fromAidl(_input));
     CreateTrackOutput output;
 
-    sp<PlaybackThread::Track> track;
-    sp<TrackHandle> trackHandle;
+    sp<IAfTrack> track;
     sp<Client> client;
     status_t lStatus;
     audio_stream_type_t streamType;
@@ -1145,7 +996,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,8 +1042,8 @@
     }
 
     {
-        Mutex::Autolock _l(mLock);
-        PlaybackThread *thread = checkPlaybackThread_l(output.outputId);
+        audio_utils::lock_guard _l(mutex());
+        IAfPlaybackThread* thread = checkPlaybackThread_l(output.outputId);
         if (thread == NULL) {
             ALOGE("no playback thread found for output handle %d", output.outputId);
             lStatus = BAD_VALUE;
@@ -1201,14 +1052,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,8 +1093,8 @@
         output.portId = portId;
 
         if (lStatus == NO_ERROR) {
-            // no risk of deadlock because AudioFlinger::mLock is held
-            Mutex::Autolock _dl(thread->mLock);
+            // no risk of deadlock because AudioFlinger::mutex() is held
+            audio_utils::lock_guard _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.
@@ -1251,8 +1102,9 @@
             // 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);
-                if (moveEffectChain_l(sessionId, effectThread, thread) == NO_ERROR) {
+                // No thread safety analysis: double lock on a thread capability.
+                audio_utils::lock_guard_no_thread_safety_analysis _sl(effectThread->mutex());
+                if (moveEffectChain_ll(sessionId, effectThread, thread) == NO_ERROR) {
                     effectThreadId = thread->id();
                     effectIds = thread->getEffectIds_l(sessionId);
                 }
@@ -1281,11 +1133,11 @@
 
     if (lStatus != NO_ERROR) {
         // remove local strong reference to Client before deleting the Track so that the
-        // Client destructor is called by the TrackBase destructor with mClientLock held
-        // Don't hold mClientLock when releasing the reference on the track as the
+        // Client destructor is called by the TrackBase destructor with clientMutex() held
+        // Don't hold clientMutex() when releasing the reference on the track as the
         // destructor will acquire it.
         {
-            Mutex::Autolock _cl(mClientLock);
+            audio_utils::lock_guard _cl(clientMutex());
             client.clear();
         }
         track.clear();
@@ -1298,7 +1150,7 @@
         AudioSystem::moveEffectsToIo(effectIds, effectThreadId);
     }
 
-    output.audioTrack = new TrackHandle(track);
+    output.audioTrack = IAfTrack::createIAudioTrackAdapter(track);
     _output = VALUE_OR_FATAL(output.toAidl());
 
 Exit:
@@ -1310,8 +1162,8 @@
 
 uint32_t AudioFlinger::sampleRate(audio_io_handle_t ioHandle) const
 {
-    Mutex::Autolock _l(mLock);
-    ThreadBase *thread = checkThread_l(ioHandle);
+    audio_utils::lock_guard _l(mutex());
+    IAfThreadBase* const thread = checkThread_l(ioHandle);
     if (thread == NULL) {
         ALOGW("sampleRate() unknown thread %d", ioHandle);
         return 0;
@@ -1321,8 +1173,8 @@
 
 audio_format_t AudioFlinger::format(audio_io_handle_t output) const
 {
-    Mutex::Autolock _l(mLock);
-    PlaybackThread *thread = checkPlaybackThread_l(output);
+    audio_utils::lock_guard _l(mutex());
+    IAfPlaybackThread* const thread = checkPlaybackThread_l(output);
     if (thread == NULL) {
         ALOGW("format() unknown thread %d", output);
         return AUDIO_FORMAT_INVALID;
@@ -1332,8 +1184,8 @@
 
 size_t AudioFlinger::frameCount(audio_io_handle_t ioHandle) const
 {
-    Mutex::Autolock _l(mLock);
-    ThreadBase *thread = checkThread_l(ioHandle);
+    audio_utils::lock_guard _l(mutex());
+    IAfThreadBase* const thread = checkThread_l(ioHandle);
     if (thread == NULL) {
         ALOGW("frameCount() unknown thread %d", ioHandle);
         return 0;
@@ -1345,8 +1197,8 @@
 
 size_t AudioFlinger::frameCountHAL(audio_io_handle_t ioHandle) const
 {
-    Mutex::Autolock _l(mLock);
-    ThreadBase *thread = checkThread_l(ioHandle);
+    audio_utils::lock_guard _l(mutex());
+    IAfThreadBase* const thread = checkThread_l(ioHandle);
     if (thread == NULL) {
         ALOGW("frameCountHAL() unknown thread %d", ioHandle);
         return 0;
@@ -1356,8 +1208,8 @@
 
 uint32_t AudioFlinger::latency(audio_io_handle_t output) const
 {
-    Mutex::Autolock _l(mLock);
-    PlaybackThread *thread = checkPlaybackThread_l(output);
+    audio_utils::lock_guard _l(mutex());
+    IAfPlaybackThread* const thread = checkPlaybackThread_l(output);
     if (thread == NULL) {
         ALOGW("latency(): no playback thread found for output handle %d", output);
         return 0;
@@ -1377,12 +1229,12 @@
         return PERMISSION_DENIED;
     }
 
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mutex());
     mMasterVolume = value;
 
     // Set master volume in the HALs which support it.
     {
-        AutoMutex lock(mHardwareLock);
+        audio_utils::lock_guard lock(hardwareMutex());
         for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
             AudioHwDevice *dev = mAudioHwDevs.valueAt(i);
 
@@ -1424,7 +1276,7 @@
         return BAD_VALUE;
     }
 
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mutex());
 
     // short cut.
     if (mMasterBalance == balance) return NO_ERROR;
@@ -1458,18 +1310,18 @@
     }
 
     { // scope for the lock
-        AutoMutex lock(mHardwareLock);
+        audio_utils::lock_guard lock(hardwareMutex());
         if (mPrimaryHardwareDev == nullptr) {
             return INVALID_OPERATION;
         }
-        sp<DeviceHalInterface> dev = mPrimaryHardwareDev->hwDevice();
+        sp<DeviceHalInterface> dev = mPrimaryHardwareDev.load()->hwDevice();
         mHardwareStatus = AUDIO_HW_SET_MODE;
         ret = dev->setMode(mode);
         mHardwareStatus = AUDIO_HW_IDLE;
     }
 
     if (NO_ERROR == ret) {
-        Mutex::Autolock _l(mLock);
+        audio_utils::lock_guard _l(mutex());
         mMode = mode;
         for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
             mPlaybackThreads.valueAt(i)->setMode(mode);
@@ -1495,11 +1347,11 @@
         return PERMISSION_DENIED;
     }
 
-    AutoMutex lock(mHardwareLock);
+    audio_utils::lock_guard lock(hardwareMutex());
     if (mPrimaryHardwareDev == nullptr) {
         return INVALID_OPERATION;
     }
-    sp<DeviceHalInterface> primaryDev = mPrimaryHardwareDev->hwDevice();
+    sp<DeviceHalInterface> primaryDev = mPrimaryHardwareDev.load()->hwDevice();
     if (primaryDev == nullptr) {
         ALOGW("%s: no primary HAL device", __func__);
         return INVALID_OPERATION;
@@ -1523,11 +1375,11 @@
     if (ret != NO_ERROR) {
         return false;
     }
-    AutoMutex lock(mHardwareLock);
+    audio_utils::lock_guard lock(hardwareMutex());
     if (mPrimaryHardwareDev == nullptr) {
         return false;
     }
-    sp<DeviceHalInterface> primaryDev = mPrimaryHardwareDev->hwDevice();
+    sp<DeviceHalInterface> primaryDev = mPrimaryHardwareDev.load()->hwDevice();
     if (primaryDev == nullptr) {
         ALOGW("%s: no primary HAL device", __func__);
         return false;
@@ -1544,7 +1396,7 @@
 {
     ALOGV("AudioFlinger::setRecordSilenced(portId:%d, silenced:%d)", portId, silenced);
 
-    AutoMutex lock(mLock);
+    audio_utils::lock_guard lock(mutex());
     for (size_t i = 0; i < mRecordThreads.size(); i++) {
         mRecordThreads[i]->setRecordSilenced(portId, silenced);
     }
@@ -1565,12 +1417,12 @@
         return PERMISSION_DENIED;
     }
 
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mutex());
     mMasterMute = muted;
 
     // Set master mute in the HALs which support it.
     {
-        AutoMutex lock(mHardwareLock);
+        audio_utils::lock_guard lock(hardwareMutex());
         for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
             AudioHwDevice *dev = mAudioHwDevs.valueAt(i);
 
@@ -1586,7 +1438,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);
     }
@@ -1596,20 +1448,20 @@
 
 float AudioFlinger::masterVolume() const
 {
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mutex());
     return masterVolume_l();
 }
 
 status_t AudioFlinger::getMasterBalance(float *balance) const
 {
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mutex());
     *balance = getMasterBalance_l();
     return NO_ERROR; // if called through binder, may return a transactional error
 }
 
 bool AudioFlinger::masterMute() const
 {
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mutex());
     return masterMute_l();
 }
 
@@ -1628,7 +1480,8 @@
     return mMasterMute;
 }
 
-status_t AudioFlinger::checkStreamType(audio_stream_type_t stream) const
+/* static */
+status_t AudioFlinger::checkStreamType(audio_stream_type_t stream)
 {
     if (uint32_t(stream) >= AUDIO_STREAM_CNT) {
         ALOGW("checkStreamType() invalid stream %d", stream);
@@ -1661,8 +1514,8 @@
     LOG_ALWAYS_FATAL_IF(stream == AUDIO_STREAM_PATCH && value != 1.0f,
                         "AUDIO_STREAM_PATCH must have full scale volume");
 
-    AutoMutex lock(mLock);
-    VolumeInterface *volumeInterface = getVolumeInterface_l(output);
+    audio_utils::lock_guard lock(mutex());
+    sp<VolumeInterface> volumeInterface = getVolumeInterface_l(output);
     if (volumeInterface == NULL) {
         return BAD_VALUE;
     }
@@ -1676,8 +1529,8 @@
     if (output == AUDIO_IO_HANDLE_NONE) {
         return BAD_VALUE;
     }
-    AutoMutex lock(mLock);
-    PlaybackThread *thread = checkPlaybackThread_l(output);
+    audio_utils::lock_guard lock(mutex());
+    IAfPlaybackThread* const thread = checkPlaybackThread_l(output);
     if (thread == nullptr) {
         return BAD_VALUE;
     }
@@ -1685,12 +1538,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);
+    audio_utils::lock_guard lock(mutex());
+    IAfPlaybackThread* const thread = checkPlaybackThread_l(output);
     if (thread == nullptr) {
         return BAD_VALUE;
     }
@@ -1698,7 +1551,7 @@
 }
 
 status_t AudioFlinger::setBluetoothVariableLatencyEnabled(bool enabled) {
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mutex());
     status_t status = INVALID_OPERATION;
     for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
         // Success if at least one PlaybackThread supports Bluetooth latency modes
@@ -1712,7 +1565,7 @@
     return status;
 }
 
-status_t AudioFlinger::isBluetoothVariableLatencyEnabled(bool *enabled) {
+status_t AudioFlinger::isBluetoothVariableLatencyEnabled(bool* enabled) const {
     if (enabled == nullptr) {
         return BAD_VALUE;
     }
@@ -1720,11 +1573,11 @@
     return NO_ERROR;
 }
 
-status_t AudioFlinger::supportsBluetoothVariableLatency(bool* support) {
+status_t AudioFlinger::supportsBluetoothVariableLatency(bool* support) const {
     if (support == nullptr) {
         return BAD_VALUE;
     }
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(hardwareMutex());
     *support = false;
     for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
         if (mAudioHwDevs.valueAt(i)->supportsBluetoothVariableLatency()) {
@@ -1736,7 +1589,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;
     }
@@ -1763,9 +1616,9 @@
         return BAD_VALUE;
     }
 
-    AutoMutex lock(mLock);
+    audio_utils::lock_guard lock(mutex());
     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,8 +1636,8 @@
         return 0.0f;
     }
 
-    AutoMutex lock(mLock);
-    VolumeInterface *volumeInterface = getVolumeInterface_l(output);
+    audio_utils::lock_guard lock(mutex());
+    sp<VolumeInterface> volumeInterface = getVolumeInterface_l(output);
     if (volumeInterface == NULL) {
         return 0.0f;
     }
@@ -1799,7 +1652,7 @@
         return true;
     }
 
-    AutoMutex lock(mLock);
+    audio_utils::lock_guard lock(mutex());
     return streamMute_l(stream);
 }
 
@@ -1818,17 +1671,18 @@
     }
 }
 
-// forwardAudioHwSyncToDownstreamPatches_l() must be called with AudioFlinger::mLock held
+// forwardAudioHwSyncToDownstreamPatches_l() must be called with AudioFlinger::mutex() 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);
         }
@@ -1840,7 +1694,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;
         }
@@ -1922,11 +1776,11 @@
 
     // AUDIO_IO_HANDLE_NONE means the parameters are global to the audio hardware interface
     if (ioHandle == AUDIO_IO_HANDLE_NONE) {
-        Mutex::Autolock _l(mLock);
+        audio_utils::lock_guard _l(mutex());
         // result will remain NO_INIT if no audio device is present
         status_t final_result = NO_INIT;
         {
-            AutoMutex lock(mHardwareLock);
+            audio_utils::lock_guard lock(hardwareMutex());
             mHardwareStatus = AUDIO_HW_SET_PARAMETER;
             for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
                 sp<DeviceHalInterface> dev = mAudioHwDevs.valueAt(i)->hwDevice();
@@ -1954,8 +1808,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;
@@ -1963,9 +1817,9 @@
 
     // 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);
+        audio_utils::lock_guard _l(mutex());
         thread = checkPlaybackThread_l(ioHandle);
         if (thread == 0) {
             thread = checkRecordThread_l(ioHandle);
@@ -1984,6 +1838,7 @@
     }
     if (thread != 0) {
         status_t result = thread->setParameters(filteredKeyValuePairs);
+        audio_utils::lock_guard _l(mutex());
         forwardParametersToDownstreamPatches_l(thread->id(), filteredKeyValuePairs);
         return result;
     }
@@ -1995,12 +1850,12 @@
     ALOGVV("getParameters() io %d, keys %s, calling pid %d",
             ioHandle, keys.c_str(), IPCThreadState::self()->getCallingPid());
 
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mutex());
 
     if (ioHandle == AUDIO_IO_HANDLE_NONE) {
         String8 out_s8;
 
-        AutoMutex lock(mHardwareLock);
+        audio_utils::lock_guard lock(hardwareMutex());
         for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
             String8 s;
             mHardwareStatus = AUDIO_HW_GET_PARAMETER;
@@ -2012,11 +1867,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("");
             }
@@ -2038,13 +1893,13 @@
         return 0;
     }
 
-    AutoMutex lock(mHardwareLock);
+    audio_utils::lock_guard lock(hardwareMutex());
     if (mPrimaryHardwareDev == nullptr) {
         return 0;
     }
     mHardwareStatus = AUDIO_HW_GET_INPUT_BUFFER_SIZE;
 
-    sp<DeviceHalInterface> dev = mPrimaryHardwareDev->hwDevice();
+    sp<DeviceHalInterface> dev = mPrimaryHardwareDev.load()->hwDevice();
 
     std::vector<audio_channel_mask_t> channelMasks = {channelMask};
     if (channelMask != AUDIO_CHANNEL_IN_MONO) {
@@ -2110,9 +1965,9 @@
 
 uint32_t AudioFlinger::getInputFramesLost(audio_io_handle_t ioHandle) const
 {
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mutex());
 
-    RecordThread *recordThread = checkRecordThread_l(ioHandle);
+    IAfRecordThread* const recordThread = checkRecordThread_l(ioHandle);
     if (recordThread != NULL) {
         return recordThread->getInputFramesLost();
     }
@@ -2131,11 +1986,11 @@
         return PERMISSION_DENIED;
     }
 
-    AutoMutex lock(mHardwareLock);
+    audio_utils::lock_guard lock(hardwareMutex());
     if (mPrimaryHardwareDev == nullptr) {
         return INVALID_OPERATION;
     }
-    sp<DeviceHalInterface> dev = mPrimaryHardwareDev->hwDevice();
+    sp<DeviceHalInterface> dev = mPrimaryHardwareDev.load()->hwDevice();
     mHardwareStatus = AUDIO_HW_SET_VOICE_VOLUME;
     ret = dev->setVoiceVolume(value);
     mHardwareStatus = AUDIO_HW_IDLE;
@@ -2150,9 +2005,9 @@
 status_t AudioFlinger::getRenderPosition(uint32_t *halFrames, uint32_t *dspFrames,
         audio_io_handle_t output) const
 {
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mutex());
 
-    PlaybackThread *playbackThread = checkPlaybackThread_l(output);
+    IAfPlaybackThread* const playbackThread = checkPlaybackThread_l(output);
     if (playbackThread != NULL) {
         return playbackThread->getRenderPosition(halFrames, dspFrames);
     }
@@ -2162,14 +2017,14 @@
 
 void AudioFlinger::registerClient(const sp<media::IAudioFlingerClient>& client)
 {
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mutex());
     if (client == 0) {
         return;
     }
     pid_t pid = IPCThreadState::self()->getCallingPid();
     const uid_t uid = IPCThreadState::self()->getCallingUid();
     {
-        Mutex::Autolock _cl(mClientLock);
+        audio_utils::lock_guard _cl(clientMutex());
         if (mNotificationClients.indexOfKey(pid) < 0) {
             sp<NotificationClient> notificationClient = new NotificationClient(this,
                                                                                 client,
@@ -2185,9 +2040,10 @@
         }
     }
 
-    // mClientLock should not be held here because ThreadBase::sendIoConfigEvent() will lock the
-    // ThreadBase mutex and the locking order is ThreadBase::mLock then AudioFlinger::mClientLock.
-    // the config change is always sent from playback or record threads to avoid deadlock
+    // clientMutex() should not be held here because ThreadBase::sendIoConfigEvent()
+    // will lock the ThreadBase::mutex() and the locking order is
+    // ThreadBase::mutex() then AudioFlinger::clientMutex().
+    // The config change is always sent from playback or record threads to avoid deadlock
     // with AudioSystem::gLock
     for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
         mPlaybackThreads.valueAt(i)->sendIoConfigEvent(AUDIO_OUTPUT_REGISTERED, pid);
@@ -2200,11 +2056,11 @@
 
 void AudioFlinger::removeNotificationClient(pid_t pid)
 {
-    std::vector< sp<AudioFlinger::EffectModule> > removedEffects;
+    std::vector<sp<IAfEffectModule>> removedEffects;
     {
-        Mutex::Autolock _l(mLock);
+        audio_utils::lock_guard _l(mutex());
         {
-            Mutex::Autolock _cl(mClientLock);
+            audio_utils::lock_guard _cl(clientMutex());
             mNotificationClients.removeItem(pid);
         }
 
@@ -2241,7 +2097,7 @@
     media::AudioIoDescriptor descAidl = VALUE_OR_FATAL(
             legacy2aidl_AudioIoDescriptor_AudioIoDescriptor(ioDesc));
 
-    Mutex::Autolock _l(mClientLock);
+    audio_utils::lock_guard _l(clientMutex());
     size_t size = mNotificationClients.size();
     for (size_t i = 0; i < size; i++) {
         if ((pid == 0) || (mNotificationClients.keyAt(i) == pid)) {
@@ -2258,7 +2114,7 @@
                 convertContainer<std::vector<media::audio::common::AudioLatencyMode>>(
                         modes, legacy2aidl_audio_latency_mode_t_AudioLatencyMode));
 
-    Mutex::Autolock _l(mClientLock);
+    audio_utils::lock_guard _l(clientMutex());
     size_t size = mNotificationClients.size();
     for (size_t i = 0; i < size; i++) {
         mNotificationClients.valueAt(i)->audioFlingerClient()
@@ -2266,7 +2122,7 @@
     }
 }
 
-// removeClient_l() must be called with AudioFlinger::mClientLock held
+// removeClient_l() must be called with AudioFlinger::clientMutex() held
 void AudioFlinger::removeClient_l(pid_t pid)
 {
     ALOGV("removeClient_l() pid %d, calling pid %d", pid,
@@ -2274,11 +2130,11 @@
     mClients.removeItem(pid);
 }
 
-// getEffectThread_l() must be called with AudioFlinger::mLock held
-sp<AudioFlinger::ThreadBase> AudioFlinger::getEffectThread_l(audio_session_t sessionId,
+// getEffectThread_l() must be called with AudioFlinger::mutex() held
+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) {
@@ -2307,27 +2163,6 @@
     return thread;
 }
 
-
-
-// ----------------------------------------------------------------------------
-
-AudioFlinger::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
-AudioFlinger::Client::~Client()
-{
-    mAudioFlinger->removeClient_l(mPid);
-}
-
-AllocatorFactory::ClientAllocator& AudioFlinger::Client::allocator()
-{
-    return mClientAllocator;
-}
-
 // ----------------------------------------------------------------------------
 
 AudioFlinger::NotificationClient::NotificationClient(const sp<AudioFlinger>& audioFlinger,
@@ -2354,9 +2189,9 @@
 
 
 void AudioFlinger::MediaLogNotifier::requestMerge() {
-    AutoMutex _l(mMutex);
+    audio_utils::lock_guard _l(mMutex);
     mPendingRequests = true;
-    mCond.signal();
+    mCondition.notify_one();
 }
 
 bool AudioFlinger::MediaLogNotifier::threadLoop() {
@@ -2366,10 +2201,10 @@
     }
     // Wait until there are pending requests
     {
-        AutoMutex _l(mMutex);
+        audio_utils::unique_lock _l(mMutex);
         mPendingRequests = false; // to ignore past requests
         while (!mPendingRequests) {
-            mCond.wait(mMutex);
+            mCondition.wait(_l);
             // TODO may also need an exitPending check
         }
         mPendingRequests = false;
@@ -2392,8 +2227,7 @@
     CreateRecordInput input = VALUE_OR_RETURN_STATUS(CreateRecordInput::fromAidl(_input));
     CreateRecordOutput output;
 
-    sp<RecordThread::RecordTrack> recordTrack;
-    sp<RecordHandle> recordHandle;
+    sp<IAfRecordTrack> recordTrack;
     sp<Client> client;
     status_t lStatus;
     audio_session_t sessionId = input.sessionId;
@@ -2425,7 +2259,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)) {
@@ -2481,8 +2315,8 @@
     }
 
     {
-        Mutex::Autolock _l(mLock);
-        RecordThread *thread = checkRecordThread_l(output.inputId);
+        audio_utils::lock_guard _l(mutex());
+        IAfRecordThread* const thread = checkRecordThread_l(output.inputId);
         if (thread == NULL) {
             ALOGW("createRecord() checkRecordThread_l failed, input handle %d", output.inputId);
             lStatus = FAILED_TRANSACTION;
@@ -2536,9 +2370,9 @@
 
         // Check if one effect chain was awaiting for an AudioRecord to be created on this
         // session and move it to this thread.
-        sp<EffectChain> chain = getOrphanEffectChain_l(sessionId);
+        sp<IAfEffectChain> chain = getOrphanEffectChain_l(sessionId);
         if (chain != 0) {
-            Mutex::Autolock _l2(thread->mLock);
+            audio_utils::lock_guard _l2(thread->mutex());
             thread->addEffectChain_l(chain);
         }
         break;
@@ -2551,17 +2385,17 @@
     output.buffers = recordTrack->getBuffers();
     output.portId = portId;
 
-    output.audioRecord = new RecordHandle(recordTrack);
+    output.audioRecord = IAfRecordTrack::createIAudioRecordAdapter(recordTrack);
     _output = VALUE_OR_FATAL(output.toAidl());
 
 Exit:
     if (lStatus != NO_ERROR) {
         // remove local strong reference to Client before deleting the RecordTrack so that the
-        // Client destructor is called by the TrackBase destructor with mClientLock held
-        // Don't hold mClientLock when releasing the reference on the track as the
+        // Client destructor is called by the TrackBase destructor with clientMutex() held
+        // Don't hold clientMutex() when releasing the reference on the track as the
         // destructor will acquire it.
         {
-            Mutex::Autolock _cl(mClientLock);
+            audio_utils::lock_guard _cl(clientMutex());
             client.clear();
         }
         recordTrack.clear();
@@ -2582,8 +2416,8 @@
     if (config == nullptr) {
         return BAD_VALUE;
     }
-    Mutex::Autolock _l(mLock);
-    AutoMutex lock(mHardwareLock);
+    audio_utils::lock_guard _l(mutex());
+    audio_utils::lock_guard lock(hardwareMutex());
     RETURN_STATUS_IF_ERROR(
             mDevicesFactoryHal->getSurroundSoundConfig(&config->surroundSoundConfig));
     RETURN_STATUS_IF_ERROR(mDevicesFactoryHal->getEngineConfig(&config->engineConfig));
@@ -2591,7 +2425,7 @@
     RETURN_STATUS_IF_ERROR(mDevicesFactoryHal->getDeviceNames(&hwModuleNames));
     std::set<AudioMode> allSupportedModes;
     for (const auto& name : hwModuleNames) {
-        AudioHwDevice* module = loadHwModule_l(name.c_str());
+        AudioHwDevice* module = loadHwModule_ll(name.c_str());
         if (module == nullptr) continue;
         media::AudioHwModule aidlModule;
         if (module->hwDevice()->getAudioPorts(&aidlModule.ports) == OK &&
@@ -2626,14 +2460,15 @@
     if (!settingsAllowed()) {
         return AUDIO_MODULE_HANDLE_NONE;
     }
-    Mutex::Autolock _l(mLock);
-    AutoMutex lock(mHardwareLock);
-    AudioHwDevice* module = loadHwModule_l(name);
+    audio_utils::lock_guard _l(mutex());
+    audio_utils::lock_guard lock(hardwareMutex());
+    AudioHwDevice* module = loadHwModule_ll(name);
     return module != nullptr ? module->handle() : AUDIO_MODULE_HANDLE_NONE;
 }
 
-// loadHwModule_l() must be called with AudioFlinger::mLock and AudioFlinger::mHardwareLock held
-AudioHwDevice* AudioFlinger::loadHwModule_l(const char *name)
+// loadHwModule_l() must be called with AudioFlinger::mutex()
+// and AudioFlinger::hardwareMutex() held
+AudioHwDevice* AudioFlinger::loadHwModule_ll(const char *name)
 {
     for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
         if (strncmp(mAudioHwDevs.valueAt(i)->moduleName(), name, strlen(name)) == 0) {
@@ -2712,7 +2547,7 @@
     if (strcmp(name, AUDIO_HARDWARE_MODULE_ID_PRIMARY) == 0) {
         mPrimaryHardwareDev = audioDevice;
         mHardwareStatus = AUDIO_HW_SET_MODE;
-        mPrimaryHardwareDev->hwDevice()->setMode(mMode);
+        mPrimaryHardwareDev.load()->hwDevice()->setMode(mMode);
         mHardwareStatus = AUDIO_HW_IDLE;
     }
 
@@ -2737,17 +2572,17 @@
 
 // ----------------------------------------------------------------------------
 
-uint32_t AudioFlinger::getPrimaryOutputSamplingRate()
+uint32_t AudioFlinger::getPrimaryOutputSamplingRate() const
 {
-    Mutex::Autolock _l(mLock);
-    PlaybackThread *thread = fastPlaybackThread_l();
+    audio_utils::lock_guard _l(mutex());
+    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();
+    audio_utils::lock_guard _l(mutex());
+    IAfPlaybackThread* const thread = fastPlaybackThread_l();
     return thread != NULL ? thread->frameCountHAL() : 0;
 }
 
@@ -2759,7 +2594,7 @@
     if (!isAudioServerOrSystemServerUid(uid)) {
         return PERMISSION_DENIED;
     }
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mutex());
     if (mIsDeviceTypeKnown) {
         return INVALID_OPERATION;
     }
@@ -2817,8 +2652,8 @@
         module = config->ext.mix.hw_module;
     }
 
-    Mutex::Autolock _l(mLock);
-    AutoMutex lock(mHardwareLock);
+    audio_utils::lock_guard _l(mutex());
+    audio_utils::lock_guard lock(hardwareMutex());
     ssize_t index = mAudioHwDevs.indexOfKey(module);
     if (index < 0) {
         ALOGW("%s() bad hw module %d", __func__, module);
@@ -2831,7 +2666,7 @@
 
 audio_hw_sync_t AudioFlinger::getAudioHwSyncForSession(audio_session_t sessionId)
 {
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mutex());
 
     ssize_t index = mHwAvSyncIds.indexOfKey(sessionId);
     if (index >= 0) {
@@ -2842,11 +2677,11 @@
 
     sp<DeviceHalInterface> dev;
     {
-        AutoMutex lock(mHardwareLock);
+        audio_utils::lock_guard lock(hardwareMutex());
         if (mPrimaryHardwareDev == nullptr) {
             return AUDIO_HW_SYNC_INVALID;
         }
-        dev = mPrimaryHardwareDev->hwDevice();
+        dev = mPrimaryHardwareDev.load()->hwDevice();
     }
     if (dev == nullptr) {
         return AUDIO_HW_SYNC_INVALID;
@@ -2872,15 +2707,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;
         }
     }
@@ -2891,7 +2726,7 @@
 
 status_t AudioFlinger::systemReady()
 {
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mutex());
     ALOGI("%s", __FUNCTION__);
     if (mSystemReady) {
         ALOGW("%s called twice", __FUNCTION__);
@@ -2899,15 +2734,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();
     }
 
@@ -2932,9 +2767,9 @@
     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);
+    audio_utils::lock_guard lock(hardwareMutex());
     status_t status = INVALID_OPERATION;
 
     for (size_t i = 0; i < mAudioHwDevs.size(); i++) {
@@ -2958,8 +2793,9 @@
     return status;
 }
 
-// setAudioHwSyncForSession_l() must be called with AudioFlinger::mLock held
-void AudioFlinger::setAudioHwSyncForSession_l(PlaybackThread *thread, audio_session_t sessionId)
+// setAudioHwSyncForSession_l() must be called with AudioFlinger::mutex() held
+void AudioFlinger::setAudioHwSyncForSession_l(
+        IAfPlaybackThread* const thread, audio_session_t sessionId)
 {
     ssize_t index = mHwAvSyncIds.indexOfKey(sessionId);
     if (index >= 0) {
@@ -2970,7 +2806,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(); });
     }
 }
 
@@ -2978,7 +2814,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,
@@ -3001,28 +2837,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,
@@ -3036,43 +2850,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,14 +2932,14 @@
         return BAD_VALUE;
     }
 
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mutex());
 
-    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
@@ -3131,18 +2947,17 @@
 
             // the first primary output opened designates the primary hw device if no HW module
             // named "primary" was already loaded.
-            AutoMutex lock(mHardwareLock);
+            audio_utils::lock_guard lock(hardwareMutex());
             if ((mPrimaryHardwareDev == nullptr) && (flags & AUDIO_OUTPUT_FLAG_PRIMARY)) {
                 ALOGI("Using module %d as the primary audio interface", module);
                 mPrimaryHardwareDev = playbackThread->getOutput()->audioHwDev;
 
                 mHardwareStatus = AUDIO_HW_SET_MODE;
-                mPrimaryHardwareDev->hwDevice()->setMode(mMode);
+                mPrimaryHardwareDev.load()->hwDevice()->setMode(mMode);
                 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(
@@ -3159,9 +2974,9 @@
 audio_io_handle_t AudioFlinger::openDuplicateOutput(audio_io_handle_t output1,
         audio_io_handle_t output2)
 {
-    Mutex::Autolock _l(mLock);
-    MixerThread *thread1 = checkMixerThread_l(output1);
-    MixerThread *thread2 = checkMixerThread_l(output2);
+    audio_utils::lock_guard _l(mutex());
+    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,
@@ -3170,7 +2985,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
@@ -3187,22 +3003,22 @@
 {
     // 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);
+        audio_utils::lock_guard _l(mutex());
         playbackThread = checkPlaybackThread_l(output);
         if (playbackThread != NULL) {
             ALOGV("closeOutput() %d", output);
 
             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());
                     }
                 }
             }
@@ -3211,20 +3027,22 @@
             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);
-                    Vector< sp<EffectChain> > effectChains = playbackThread->getEffectChains_l();
+                    // Use scoped_lock to avoid deadlock order issues with duplicating threads.
+                    audio_utils::scoped_lock sl(dstThread->mutex(), 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(),
+                        moveEffectChain_ll(effectChains[i]->sessionId(), playbackThread.get(),
                                 dstThread);
                     }
                 }
             }
         } 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;
             }
@@ -3233,10 +3051,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();
@@ -3254,7 +3072,8 @@
     return NO_ERROR;
 }
 
-void AudioFlinger::closeOutputFinish(const sp<PlaybackThread>& thread)
+/* static */
+void AudioFlinger::closeOutputFinish(const sp<IAfPlaybackThread>& thread)
 {
     AudioStreamOut *out = thread->clearOutput();
     ALOG_ASSERT(out != NULL, "out shouldn't be NULL");
@@ -3262,17 +3081,17 @@
     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);
 }
 
 status_t AudioFlinger::suspendOutput(audio_io_handle_t output)
 {
-    Mutex::Autolock _l(mLock);
-    PlaybackThread *thread = checkPlaybackThread_l(output);
+    audio_utils::lock_guard _l(mutex());
+    IAfPlaybackThread* const thread = checkPlaybackThread_l(output);
 
     if (thread == NULL) {
         return BAD_VALUE;
@@ -3286,8 +3105,8 @@
 
 status_t AudioFlinger::restoreOutput(audio_io_handle_t output)
 {
-    Mutex::Autolock _l(mLock);
-    PlaybackThread *thread = checkPlaybackThread_l(output);
+    audio_utils::lock_guard _l(mutex());
+    IAfPlaybackThread* const thread = checkPlaybackThread_l(output);
 
     if (thread == NULL) {
         return BAD_VALUE;
@@ -3303,7 +3122,7 @@
 status_t AudioFlinger::openInput(const media::OpenInputRequest& request,
                                  media::OpenInputResponse* response)
 {
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mutex());
 
     AudioDeviceTypeAddr device = VALUE_OR_RETURN_STATUS(
             aidl2legacy_AudioDeviceTypeAddress(request.device));
@@ -3316,7 +3135,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,
@@ -3340,7 +3159,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,
@@ -3406,17 +3225,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;
@@ -3436,10 +3256,10 @@
 {
     // 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);
+        audio_utils::lock_guard _l(mutex());
         recordThread = checkRecordThread_l(input);
         if (recordThread != 0) {
             ALOGV("closeInput() %d", input);
@@ -3450,10 +3270,10 @@
             // on at least one effect. We must either move the chain to an existing thread with the
             // same session ID or put it aside in case a new record thread is opened for a
             // new capture on the same session
-            sp<EffectChain> chain;
+            sp<IAfEffectChain> chain;
             {
-                Mutex::Autolock _sl(recordThread->mLock);
-                Vector< sp<EffectChain> > effectChains = recordThread->getEffectChains_l();
+                audio_utils::lock_guard _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];
@@ -3465,12 +3285,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);
+                        audio_utils::lock_guard _l2(t->mutex());
                         ALOGV("closeInput() found thread %d for effect session %d",
                               t->id(), chain->sessionId());
                         t->addEffectChain_l(chain);
@@ -3484,7 +3304,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;
             }
@@ -3493,7 +3314,7 @@
         }
         ioConfigChanged(AUDIO_INPUT_CLOSED, sp<AudioIoDescriptor>::make(input));
     }
-    // FIXME: calling thread->exit() without mLock held should not be needed anymore now that
+    // FIXME: calling thread->exit() without mutex() held should not be needed anymore now that
     // we have a different lock for notification client
     if (recordThread != 0) {
         closeInputFinish(recordThread);
@@ -3507,7 +3328,7 @@
     return NO_ERROR;
 }
 
-void AudioFlinger::closeInputFinish(const sp<RecordThread>& thread)
+void AudioFlinger::closeInputFinish(const sp<IAfRecordThread>& thread)
 {
     thread->exit();
     AudioStreamIn *in = thread->clearInput();
@@ -3516,19 +3337,19 @@
     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);
 }
 
 status_t AudioFlinger::invalidateTracks(const std::vector<audio_port_handle_t> &portIds) {
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mutex());
     ALOGV("%s", __func__);
 
     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;
@@ -3558,7 +3379,7 @@
 void AudioFlinger::acquireAudioSessionId(
         audio_session_t audioSession, pid_t pid, uid_t uid)
 {
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mutex());
     pid_t caller = IPCThreadState::self()->getCallingPid();
     ALOGV("acquiring %d from %d, for %d", audioSession, caller, pid);
     const uid_t callerUid = IPCThreadState::self()->getCallingUid();
@@ -3570,7 +3391,7 @@
     }
 
     {
-        Mutex::Autolock _cl(mClientLock);
+        audio_utils::lock_guard _cl(clientMutex());
         // Ignore requests received from processes not known as notification client. The request
         // is likely proxied by mediaserver (e.g CameraService) and releaseAudioSessionId() can be
         // called from a different pid leaving a stale session reference.  Also we don't know how
@@ -3596,9 +3417,9 @@
 
 void AudioFlinger::releaseAudioSessionId(audio_session_t audioSession, pid_t pid)
 {
-    std::vector< sp<EffectModule> > removedEffects;
+    std::vector<sp<IAfEffectModule>> removedEffects;
     {
-        Mutex::Autolock _l(mLock);
+        audio_utils::lock_guard _l(mutex());
         pid_t caller = IPCThreadState::self()->getCallingPid();
         ALOGV("releasing %d from %d for %d", audioSession, caller, pid);
         const uid_t callerUid = IPCThreadState::self()->getCallingUid();
@@ -3614,7 +3435,7 @@
                 if (ref->mCnt == 0) {
                     mAudioSessionRefs.removeAt(i);
                     delete ref;
-                    std::vector< sp<EffectModule> > effects = purgeStaleEffects_l();
+                    std::vector<sp<IAfEffectModule>> effects = purgeStaleEffects_l();
                     removedEffects.insert(removedEffects.end(), effects.begin(), effects.end());
                 }
                 goto Exit;
@@ -3644,18 +3465,19 @@
     return false;
 }
 
-std::vector<sp<AudioFlinger::EffectModule>> AudioFlinger::purgeStaleEffects_l() {
+std::vector<sp<IAfEffectModule>> AudioFlinger::purgeStaleEffects_l() {
 
     ALOGV("purging stale effects");
 
-    Vector< sp<EffectChain> > chains;
-    std::vector< sp<EffectModule> > removedEffects;
+    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<EffectChain> ec = t->mEffectChains[j];
+        sp<IAfPlaybackThread> t = mPlaybackThreads.valueAt(i);
+        audio_utils::lock_guard _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);
             }
@@ -3663,28 +3485,30 @@
     }
 
     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<EffectChain> ec = t->mEffectChains[j];
+        sp<IAfRecordThread> t = mRecordThreads.valueAt(i);
+        audio_utils::lock_guard _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<EffectChain> ec = t->mEffectChains[j];
+        const sp<IAfMmapThread> t = mMmapThreads.valueAt(i);
+        audio_utils::lock_guard _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 < chains.size(); i++) {
          // clang-tidy suggests const ref
-        sp<EffectChain> ec = chains[i];  // NOLINT(performance-unnecessary-copy-initialization)
+        sp<IAfEffectChain> ec = chains[i];  // NOLINT(performance-unnecessary-copy-initialization)
         int sessionid = ec->sessionId();
-        sp<ThreadBase> t = ec->thread().promote();
+        const auto t = ec->thread().promote();
         if (t == 0) {
             continue;
         }
@@ -3700,10 +3524,10 @@
             }
         }
         if (!found) {
-            Mutex::Autolock _l(t->mLock);
+            audio_utils::lock_guard _l(t->mutex());
             // remove all effects from the chain
-            while (ec->mEffects.size()) {
-                sp<EffectModule> effect = ec->mEffects[0];
+            while (ec->numberOfEffects()) {
+                sp<IAfEffectModule> effect = ec->getEffectModule(0);
                 effect->unPin();
                 t->removeEffect_l(effect, /*release*/ true);
                 if (effect->purgeHandles()) {
@@ -3716,8 +3540,8 @@
     return removedEffects;
 }
 
-// dumpToThreadLog_l() must be called with AudioFlinger::mLock held
-void AudioFlinger::dumpToThreadLog_l(const sp<ThreadBase> &thread)
+// dumpToThreadLog_l() must be called with AudioFlinger::mutex() held
+void AudioFlinger::dumpToThreadLog_l(const sp<IAfThreadBase> &thread)
 {
     constexpr int THREAD_DUMP_TIMEOUT_MS = 2;
     audio_utils::FdToString fdToString("- ", THREAD_DUMP_TIMEOUT_MS);
@@ -3728,10 +3552,10 @@
     }
 }
 
-// checkThread_l() must be called with AudioFlinger::mLock held
-AudioFlinger::ThreadBase *AudioFlinger::checkThread_l(audio_io_handle_t ioHandle) const
+// checkThread_l() must be called with AudioFlinger::mutex() held
+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:
@@ -3747,56 +3571,56 @@
     return thread;
 }
 
-// checkOutputThread_l() must be called with AudioFlinger::mLock held
-sp<AudioFlinger::ThreadBase> AudioFlinger::checkOutputThread_l(audio_io_handle_t ioHandle) const
+// checkOutputThread_l() must be called with AudioFlinger::mutex() held
+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);
     }
     return thread;
 }
 
-// checkPlaybackThread_l() must be called with AudioFlinger::mLock held
-AudioFlinger::PlaybackThread *AudioFlinger::checkPlaybackThread_l(audio_io_handle_t output) const
+// checkPlaybackThread_l() must be called with AudioFlinger::mutex() held
+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
+// checkMixerThread_l() must be called with AudioFlinger::mutex() held
+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
+// checkRecordThread_l() must be called with AudioFlinger::mutex() held
+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
+// checkMmapThread_l() must be called with AudioFlinger::mutex() held
+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
+// checkPlaybackThread_l() must be called with AudioFlinger::mutex() held
+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;
             }
         }
@@ -3804,17 +3628,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;
@@ -3841,14 +3665,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);
+    audio_utils::lock_guard lock(hardwareMutex());
     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;
         }
@@ -3862,7 +3686,7 @@
 
 DeviceTypeSet AudioFlinger::primaryOutputDevice_l() const
 {
-    PlaybackThread *thread = primaryPlaybackThread_l();
+    IAfPlaybackThread* const thread = primaryPlaybackThread_l();
 
     if (thread == NULL) {
         return {};
@@ -3871,12 +3695,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 ||
@@ -3890,9 +3714,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;
         }
@@ -3901,12 +3725,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;
@@ -3932,10 +3756,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);
+                    [&] { audio_utils::lock_guard _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);
@@ -3948,7 +3772,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(),
@@ -3968,7 +3792,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(),
@@ -3998,9 +3822,9 @@
                                     audio_session_t triggerSession,
                                     audio_session_t listenerSession,
                                     const audioflinger::SyncEventCallback& callBack,
-                                    const wp<RefBase>& cookie)
+                                    const wp<IAfTrackBase>& cookie)
 {
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mutex());
 
     auto event = sp<audioflinger::SyncEvent>::make(
             type, triggerSession, listenerSession, callBack, cookie);
@@ -4037,7 +3861,7 @@
 
 status_t AudioFlinger::queryNumberEffects(uint32_t *numEffects) const
 {
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mutex());
     if (mEffectsFactoryHal.get()) {
         return mEffectsFactoryHal->queryNumberEffects(numEffects);
     } else {
@@ -4047,7 +3871,7 @@
 
 status_t AudioFlinger::queryEffect(uint32_t index, effect_descriptor_t *descriptor) const
 {
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mutex());
     if (mEffectsFactoryHal.get()) {
         return mEffectsFactoryHal->getDescriptor(index, descriptor);
     } else {
@@ -4064,7 +3888,7 @@
         return BAD_VALUE;
     }
 
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mutex());
 
     if (!mEffectsFactoryHal.get()) {
         return -ENODEV;
@@ -4140,7 +3964,7 @@
             aidl2legacy_EffectDescriptor_effect_descriptor_t(request.desc));
     const bool probe = request.probe;
 
-    sp<EffectHandle> handle;
+    sp<IAfEffectHandle> handle;
     effect_descriptor_t descOut;
     int enabledOut = 0;
     int idOut = -1;
@@ -4159,7 +3983,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,
@@ -4184,7 +4008,11 @@
             lStatus = BAD_VALUE;
             goto Exit;
         }
-        PlaybackThread *thread = checkPlaybackThread_l(io);
+        IAfPlaybackThread* thread;
+        {
+            audio_utils::lock_guard l(mutex());
+            thread = checkPlaybackThread_l(io);
+        }
         if (thread == nullptr) {
             ALOGE("%s: invalid output %d specified for AUDIO_SESSION_OUTPUT_STAGE", __func__, io);
             lStatus = BAD_VALUE;
@@ -4248,7 +4076,7 @@
             goto Exit;
         }
 
-        const bool hapticPlaybackRequired = EffectModule::isHapticGenerator(&descOut.type);
+        const bool hapticPlaybackRequired = IAfEffectModule::isHapticGenerator(&descOut.type);
         if (hapticPlaybackRequired
                 && (sessionId == AUDIO_SESSION_DEVICE
                         || sessionId == AUDIO_SESSION_OUTPUT_MIX
@@ -4275,17 +4103,17 @@
             ALOGV("createEffect got output %d", io);
         }
 
-        Mutex::Autolock _l(mLock);
+        audio_utils::lock_guard _l(mutex());
 
         if (sessionId == AUDIO_SESSION_DEVICE) {
             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
-                Mutex::Autolock _cl(mClientLock);
+                // remove local strong reference to Client with clientMutex() held
+                audio_utils::lock_guard _cl(clientMutex());
                 client.clear();
             } else {
                 // handle must be valid here, but check again to be safe.
@@ -4353,7 +4181,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");
@@ -4362,7 +4190,7 @@
                 }
             }
         }
-        ThreadBase *thread = checkRecordThread_l(io);
+        IAfThreadBase* thread = checkRecordThread_l(io);
         if (thread == NULL) {
             thread = checkPlaybackThread_l(io);
             if (thread == NULL) {
@@ -4376,9 +4204,9 @@
         } else {
             // Check if one effect chain was awaiting for an effect to be created on this
             // session and used it instead of creating a new one.
-            sp<EffectChain> chain = getOrphanEffectChain_l(sessionId);
+            sp<IAfEffectChain> chain = getOrphanEffectChain_l(sessionId);
             if (chain != 0) {
-                Mutex::Autolock _l2(thread->mLock);
+                audio_utils::lock_guard _l2(thread->mutex());
                 thread->addEffectChain_l(chain);
             }
         }
@@ -4387,9 +4215,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;
@@ -4405,8 +4233,8 @@
                                         &descOut, &enabledOut, &lStatus, pinned, probe,
                                         request.notifyFramesProcessed);
         if (lStatus != NO_ERROR && lStatus != ALREADY_EXISTS) {
-            // remove local strong reference to Client with mClientLock held
-            Mutex::Autolock _cl(mClientLock);
+            // remove local strong reference to Client with clientMutex() held
+            audio_utils::lock_guard _cl(clientMutex());
             client.clear();
         } else {
             // handle must be valid here, but check again to be safe.
@@ -4428,7 +4256,7 @@
             response->alreadyExists = false;
         }
         // Check CPU and memory usage
-        sp<EffectBase> effect = handle->effect().promote();
+        sp<IAfEffectBase> effect = handle->effect().promote();
         if (effect != nullptr) {
             status_t rStatus = effect->updatePolicyState();
             if (rStatus != NO_ERROR) {
@@ -4441,7 +4269,7 @@
 
     response->id = idOut;
     response->enabled = enabledOut != 0;
-    response->effect = handle;
+    response->effect = handle->asIEffect();
     response->desc = VALUE_OR_RETURN_STATUS(
             legacy2aidl_effect_descriptor_t_EffectDescriptor(descOut));
 
@@ -4452,27 +4280,26 @@
 status_t AudioFlinger::moveEffects(audio_session_t sessionId, audio_io_handle_t srcOutput,
         audio_io_handle_t dstOutput)
 {
-    ALOGV("moveEffects() session %d, srcOutput %d, dstOutput %d",
-            sessionId, srcOutput, dstOutput);
-    Mutex::Autolock _l(mLock);
+    ALOGV("%s() session %d, srcOutput %d, dstOutput %d",
+            __func__, sessionId, srcOutput, dstOutput);
+    audio_utils::lock_guard _l(mutex());
     if (srcOutput == dstOutput) {
-        ALOGW("moveEffects() same dst and src outputs %d", dstOutput);
+        ALOGW("%s() same dst and src outputs %d", __func__, dstOutput);
         return NO_ERROR;
     }
-    PlaybackThread *srcThread = checkPlaybackThread_l(srcOutput);
-    if (srcThread == NULL) {
-        ALOGW("moveEffects() bad srcOutput %d", srcOutput);
+    IAfPlaybackThread* const srcThread = checkPlaybackThread_l(srcOutput);
+    if (srcThread == nullptr) {
+        ALOGW("%s() bad srcOutput %d", __func__, srcOutput);
         return BAD_VALUE;
     }
-    PlaybackThread *dstThread = checkPlaybackThread_l(dstOutput);
-    if (dstThread == NULL) {
-        ALOGW("moveEffects() bad dstOutput %d", dstOutput);
+    IAfPlaybackThread* const dstThread = checkPlaybackThread_l(dstOutput);
+    if (dstThread == nullptr) {
+        ALOGW("%s() bad dstOutput %d", __func__, dstOutput);
         return BAD_VALUE;
     }
 
-    Mutex::Autolock _dl(dstThread->mLock);
-    Mutex::Autolock _sl(srcThread->mLock);
-    return moveEffectChain_l(sessionId, srcThread, dstThread);
+    audio_utils::scoped_lock _ll(dstThread->mutex(), srcThread->mutex());
+    return moveEffectChain_ll(sessionId, srcThread, dstThread);
 }
 
 
@@ -4480,39 +4307,38 @@
                                 audio_session_t sessionId,
                                 bool suspended)
 {
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mutex());
 
-    sp<ThreadBase> thread = getEffectThread_l(sessionId, effectId);
+    sp<IAfThreadBase> thread = getEffectThread_l(sessionId, effectId);
     if (thread == nullptr) {
       return;
     }
-    Mutex::Autolock _sl(thread->mLock);
-    sp<EffectModule> effect = thread->getEffect_l(sessionId, effectId);
+    audio_utils::lock_guard _sl(thread->mutex());
+    sp<IAfEffectModule> effect = thread->getEffect_l(sessionId, effectId);
     thread->setEffectSuspended_l(&effect->desc().type, suspended, sessionId);
 }
 
 
-// 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)
-NO_THREAD_SAFETY_ANALYSIS // requires srcThread and dstThread locks
+// moveEffectChain_ll must be called with the AudioFlinger::mutex()
+// and both srcThread and dstThread mutex()s held
+status_t AudioFlinger::moveEffectChain_ll(audio_session_t sessionId,
+        IAfPlaybackThread* srcThread, IAfPlaybackThread* dstThread)
 {
-    ALOGV("moveEffectChain_l() session %d from thread %p to thread %p",
-            sessionId, srcThread, dstThread);
+    ALOGV("%s: session %d from thread %p to thread %p",
+            __func__, sessionId, srcThread, dstThread);
 
-    sp<EffectChain> chain = srcThread->getEffectChain_l(sessionId);
+    sp<IAfEffectChain> chain = srcThread->getEffectChain_l(sessionId);
     if (chain == 0) {
-        ALOGW("moveEffectChain_l() effect chain for session %d not on source thread %p",
-                sessionId, srcThread);
+        ALOGW("%s: effect chain for session %d not on source thread %p",
+                __func__, sessionId, srcThread);
         return INVALID_OPERATION;
     }
 
     // Check whether the destination thread and all effects in the chain are compatible
     if (!chain->isCompatibleWithThread_l(dstThread)) {
-        ALOGW("moveEffectChain_l() effect chain failed because"
+        ALOGW("%s: effect chain failed because"
                 " destination thread %p is not compatible with effects in the chain",
-                dstThread);
+                __func__, dstThread);
         return INVALID_OPERATION;
     }
 
@@ -4525,16 +4351,16 @@
 
     // transfer all effects one by one so that new effect chain is created on new thread with
     // correct buffer sizes and audio parameters and effect engines reconfigured accordingly
-    sp<EffectChain> dstChain;
-    Vector< sp<EffectModule> > removed;
+    sp<IAfEffectChain> dstChain;
+    Vector<sp<IAfEffectModule>> removed;
     status_t status = NO_ERROR;
     std::string errorString;
     // process effects one by one.
-    for (sp<EffectModule> effect = chain->getEffectFromId_l(0); effect != nullptr;
+    for (sp<IAfEffectModule> effect = chain->getEffectFromId_l(0); effect != nullptr;
             effect = chain->getEffectFromId_l(0)) {
         srcThread->removeEffect_l(effect);
         removed.add(effect);
-        status = dstThread->addEffect_l(effect);
+        status = dstThread->addEffect_ll(effect);
         if (status != NO_ERROR) {
             errorString = StringPrintf(
                     "cannot add effect %p to destination thread", effect.get());
@@ -4560,7 +4386,7 @@
         for (const auto& effect : removed) {
             dstThread->removeEffect_l(effect); // Note: Depending on error location, the last
                                                // effect may not have been placed on dstThread.
-            if (srcThread->addEffect_l(effect) == NO_ERROR) {
+            if (srcThread->addEffect_ll(effect) == NO_ERROR) {
                 ++restored;
                 if (dstChain == nullptr) {
                     dstChain = effect->getCallback()->chain().promote();
@@ -4576,15 +4402,15 @@
         // If we do not take the dstChain lock, it is possible that processing is ongoing
         // while we are starting the effect.  This can cause glitches with volume,
         // see b/202360137.
-        dstChain->lock();
+        dstChain->mutex().lock();
         for (const auto& effect : removed) {
-            if (effect->state() == EffectModule::ACTIVE ||
-                    effect->state() == EffectModule::STOPPING) {
+            if (effect->state() == IAfEffectModule::ACTIVE ||
+                    effect->state() == IAfEffectModule::STOPPING) {
                 ++started;
                 effect->start();
             }
         }
-        dstChain->unlock();
+        dstChain->mutex().unlock();
     }
 
     if (status != NO_ERROR) {
@@ -4605,45 +4431,43 @@
 }
 
 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());
+    audio_utils::lock_guard _l(mutex());
+    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);
-        sp<EffectChain> srcChain = thread->getEffectChain_l(AUDIO_SESSION_OUTPUT_MIX);
-        sp<EffectChain> dstChain;
+        audio_utils::scoped_lock _ll(dstThread->mutex(), thread->mutex());
+        sp<IAfEffectChain> srcChain = thread->getEffectChain_l(AUDIO_SESSION_OUTPUT_MIX);
+        sp<IAfEffectChain> dstChain;
         if (srcChain == 0) {
             return INVALID_OPERATION;
         }
 
-        sp<EffectModule> effect = srcChain->getEffectFromId_l(EffectId);
+        sp<IAfEffectModule> effect = srcChain->getEffectFromId_l(EffectId);
         if (effect == 0) {
             return INVALID_OPERATION;
         }
         thread->removeEffect_l(effect);
-        status = dstThread->addEffect_l(effect);
+        status = dstThread->addEffect_ll(effect);
         if (status != NO_ERROR) {
-            thread->addEffect_l(effect);
+            thread->addEffect_ll(effect);
             status = INVALID_OPERATION;
             goto Exit;
         }
 
         dstChain = effect->getCallback()->chain().promote();
         if (dstChain == 0) {
-            thread->addEffect_l(effect);
+            thread->addEffect_ll(effect);
             status = INVALID_OPERATION;
         }
 
 Exit:
         // removeEffect_l() has stopped the effect if it was active so it must be restarted
-        if (effect->state() == EffectModule::ACTIVE ||
-            effect->state() == EffectModule::STOPPING) {
+        if (effect->state() == IAfEffectModule::ACTIVE ||
+            effect->state() == IAfEffectModule::STOPPING) {
             effect->start();
         }
     }
@@ -4654,8 +4478,7 @@
     return status;
 }
 
-bool AudioFlinger::isNonOffloadableGlobalEffectEnabled_l()
-NO_THREAD_SAFETY_ANALYSIS  // thread lock for getEffectChain_l.
+bool AudioFlinger::isNonOffloadableGlobalEffectEnabled_l() const
 {
     if (mGlobalEffectEnableTime != 0 &&
             ((systemTime() - mGlobalEffectEnableTime) < kMinGlobalEffectEnabletimeNs)) {
@@ -4663,7 +4486,7 @@
     }
 
     for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
-        sp<EffectChain> ec =
+        sp<IAfEffectChain> ec =
                 mPlaybackThreads.valueAt(i)->getEffectChain_l(AUDIO_SESSION_OUTPUT_MIX);
         if (ec != 0 && ec->isNonOffloadableEnabled()) {
             return true;
@@ -4674,20 +4497,20 @@
 
 void AudioFlinger::onNonOffloadableGlobalEffectEnable()
 {
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mutex());
 
     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);
         }
     }
 
 }
 
-status_t AudioFlinger::putOrphanEffectChain_l(const sp<AudioFlinger::EffectChain>& chain)
+status_t AudioFlinger::putOrphanEffectChain_l(const sp<IAfEffectChain>& chain)
 {
     // clear possible suspended state before parking the chain so that it starts in default state
     // when attached to a new record thread
@@ -4705,9 +4528,9 @@
     return NO_ERROR;
 }
 
-sp<AudioFlinger::EffectChain> AudioFlinger::getOrphanEffectChain_l(audio_session_t session)
+sp<IAfEffectChain> AudioFlinger::getOrphanEffectChain_l(audio_session_t session)
 {
-    sp<EffectChain> chain;
+    sp<IAfEffectChain> chain;
     ssize_t index = mOrphanEffectChains.indexOfKey(session);
     ALOGV("getOrphanEffectChain_l session %d index %zd", session, index);
     if (index >= 0) {
@@ -4717,14 +4540,14 @@
     return chain;
 }
 
-bool AudioFlinger::updateOrphanEffectChains(const sp<AudioFlinger::EffectModule>& effect)
+bool AudioFlinger::updateOrphanEffectChains(const sp<IAfEffectModule>& effect)
 {
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mutex());
     audio_session_t session = effect->sessionId();
     ssize_t index = mOrphanEffectChains.indexOfKey(session);
     ALOGV("updateOrphanEffectChains session %d index %zd", session, index);
     if (index >= 0) {
-        sp<EffectChain> chain = mOrphanEffectChains.valueAt(index);
+        sp<IAfEffectChain> chain = mOrphanEffectChains.valueAt(index);
         if (chain->removeEffect_l(effect, true) == 0) {
             ALOGV("updateOrphanEffectChains removing effect chain at index %zd", index);
             mOrphanEffectChains.removeItemsAt(index);
@@ -4734,6 +4557,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
+{
+    audio_utils::lock_guard _l(mutex());
+    return mPatchPanel->listAudioPorts_l(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;
+    }
+
+    audio_utils::lock_guard _l(mutex());
+    return mPatchPanel->getAudioPort_l(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;
+    }
+
+    audio_utils::lock_guard _l(mutex());
+    return mPatchPanel->createAudioPatch_l(patch, handle);
+}
+
+/* Disconnect a patch */
+status_t AudioFlinger::releaseAudioPatch(audio_patch_handle_t handle)
+{
+    audio_utils::lock_guard _l(mutex());
+    return mPatchPanel->releaseAudioPatch_l(handle);
+}
+
+/* List connected audio ports and they attributes */
+status_t AudioFlinger::listAudioPatches(
+        unsigned int* num_patches, struct audio_patch* patches) const
+{
+    audio_utils::lock_guard _l(mutex());
+    return mPatchPanel->listAudioPatches_l(num_patches, patches);
+}
 
 // ----------------------------------------------------------------------------
 
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index 8b1d70b..2c34144 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -15,325 +15,395 @@
 ** 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 "EffectConfiguration.h"
+#include "IAfEffect.h"
+#include "IAfPatchPanel.h"
+#include "IAfThread.h"
+#include "IAfTrack.h"
+#include "MelReporter.h"
+#include "PatchCommandThread.h"
+
+// External classes
+#include <audio_utils/mutex.h>
+#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/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"
 
 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>;
 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 EXCLUDES_AudioFlinger_Mutex;
+
     status_t createTrack(const media::CreateTrackRequest& input,
-                         media::CreateTrackResponse& output) override;
+            media::CreateTrackResponse& output) final EXCLUDES_AudioFlinger_Mutex;
 
     status_t createRecord(const media::CreateRecordRequest& input,
-                          media::CreateRecordResponse& output) override;
+            media::CreateRecordResponse& output) final EXCLUDES_AudioFlinger_Mutex;
 
-    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 EXCLUDES_AudioFlinger_Mutex;
+    audio_format_t format(audio_io_handle_t output) const final EXCLUDES_AudioFlinger_Mutex;
+    size_t frameCount(audio_io_handle_t ioHandle) const final EXCLUDES_AudioFlinger_Mutex;
+    size_t frameCountHAL(audio_io_handle_t ioHandle) const final EXCLUDES_AudioFlinger_Mutex;
+    uint32_t latency(audio_io_handle_t output) const final EXCLUDES_AudioFlinger_Mutex;
 
-    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 EXCLUDES_AudioFlinger_Mutex;
+    status_t setMasterMute(bool muted) final EXCLUDES_AudioFlinger_Mutex;
+    float masterVolume() const final EXCLUDES_AudioFlinger_Mutex;
+    bool masterMute() const final EXCLUDES_AudioFlinger_Mutex;
 
     // 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 EXCLUDES_AudioFlinger_Mutex;
+    status_t getMasterBalance(float* balance) const final EXCLUDES_AudioFlinger_Mutex;
 
-    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 EXCLUDES_AudioFlinger_Mutex;
+    status_t setStreamMute(audio_stream_type_t stream, bool muted) final
+            EXCLUDES_AudioFlinger_Mutex;
 
-    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 EXCLUDES_AudioFlinger_Mutex;
+    bool streamMute(audio_stream_type_t stream) const final EXCLUDES_AudioFlinger_Mutex;
 
-    virtual     status_t    setMode(audio_mode_t mode);
+    status_t setMode(audio_mode_t mode) final EXCLUDES_AudioFlinger_Mutex;
 
-    virtual     status_t    setMicMute(bool state);
-    virtual     bool        getMicMute() const;
+    status_t setMicMute(bool state) final EXCLUDES_AudioFlinger_Mutex;
+    bool getMicMute() const final EXCLUDES_AudioFlinger_Mutex;
 
-    virtual     void        setRecordSilenced(audio_port_handle_t portId, bool silenced);
+    void setRecordSilenced(audio_port_handle_t portId, bool silenced) final
+            EXCLUDES_AudioFlinger_Mutex;
 
-    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
+            EXCLUDES_AudioFlinger_Mutex;
+    String8 getParameters(audio_io_handle_t ioHandle, const String8& keys) const final
+            EXCLUDES_AudioFlinger_Mutex;
 
-    virtual     void        registerClient(const sp<media::IAudioFlingerClient>& client);
+    void registerClient(const sp<media::IAudioFlingerClient>& client) final
+            EXCLUDES_AudioFlinger_Mutex;
+    size_t getInputBufferSize(uint32_t sampleRate, audio_format_t format,
+            audio_channel_mask_t channelMask) const final EXCLUDES_AudioFlinger_Mutex;
 
-    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 EXCLUDES_AudioFlinger_Mutex;
 
-    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 EXCLUDES_AudioFlinger_Mutex;
 
-    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 EXCLUDES_AudioFlinger_Mutex;
 
-    virtual status_t closeOutput(audio_io_handle_t output);
+    status_t suspendOutput(audio_io_handle_t output) final EXCLUDES_AudioFlinger_Mutex;
 
-    virtual status_t suspendOutput(audio_io_handle_t output);
+    status_t restoreOutput(audio_io_handle_t output) final EXCLUDES_AudioFlinger_Mutex;
 
-    virtual status_t restoreOutput(audio_io_handle_t output);
+    status_t openInput(const media::OpenInputRequest& request,
+            media::OpenInputResponse* response) final EXCLUDES_AudioFlinger_Mutex;
 
-    virtual status_t openInput(const media::OpenInputRequest& request,
-                               media::OpenInputResponse* response);
+    status_t closeInput(audio_io_handle_t input) final EXCLUDES_AudioFlinger_Mutex;
 
-    virtual status_t closeInput(audio_io_handle_t input);
+    status_t setVoiceVolume(float volume) final EXCLUDES_AudioFlinger_Mutex;
 
-    virtual status_t setVoiceVolume(float volume);
+    status_t getRenderPosition(uint32_t* halFrames, uint32_t* dspFrames,
+            audio_io_handle_t output) const final EXCLUDES_AudioFlinger_Mutex;
 
-    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
+            EXCLUDES_AudioFlinger_Mutex;
 
     // 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
+            EXCLUDES_AudioFlinger_Mutex;
 
-    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
+            EXCLUDES_AudioFlinger_Mutex;
 
-    virtual void releaseAudioSessionId(audio_session_t audioSession, pid_t pid);
+    void releaseAudioSessionId(audio_session_t audioSession, pid_t pid) final
+            EXCLUDES_AudioFlinger_Mutex;
 
-    virtual status_t queryNumberEffects(uint32_t *numEffects) const;
+    status_t queryNumberEffects(uint32_t* numEffects) const final EXCLUDES_AudioFlinger_Mutex;
 
-    virtual status_t queryEffect(uint32_t index, effect_descriptor_t *descriptor) const;
+    status_t queryEffect(uint32_t index, effect_descriptor_t* descriptor) const final
+            EXCLUDES_AudioFlinger_Mutex;
 
-    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 EXCLUDES_AudioFlinger_Mutex;
 
-    virtual status_t createEffect(const media::CreateEffectRequest& request,
-                                  media::CreateEffectResponse* response);
+    status_t createEffect(const media::CreateEffectRequest& request,
+            media::CreateEffectResponse* response) final EXCLUDES_AudioFlinger_Mutex;
 
-    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 EXCLUDES_AudioFlinger_Mutex;
 
-            void setEffectSuspended(int effectId,
-                                    audio_session_t sessionId,
-                                    bool suspended) override;
+    void setEffectSuspended(int effectId,
+            audio_session_t sessionId,
+            bool suspended) final EXCLUDES_AudioFlinger_Mutex;
 
-    virtual audio_module_handle_t loadHwModule(const char *name);
+    audio_module_handle_t loadHwModule(const char* name) final EXCLUDES_AudioFlinger_Mutex;
 
-    virtual uint32_t getPrimaryOutputSamplingRate();
-    virtual size_t getPrimaryOutputFrameCount();
+    uint32_t getPrimaryOutputSamplingRate() const final EXCLUDES_AudioFlinger_Mutex;
+    size_t getPrimaryOutputFrameCount() const final EXCLUDES_AudioFlinger_Mutex;
 
-    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
+            EXCLUDES_AudioFlinger_Mutex;
 
     /* 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 EXCLUDES_AudioFlinger_Mutex;
 
     /* 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 EXCLUDES_AudioFlinger_Mutex;
 
     /* Release an audio patch */
-    virtual status_t releaseAudioPatch(audio_patch_handle_t handle);
+    status_t releaseAudioPatch(audio_patch_handle_t handle) final EXCLUDES_AudioFlinger_Mutex;
 
     /* 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 EXCLUDES_AudioFlinger_Mutex;
 
     /* Set audio port configuration */
-    virtual status_t setAudioPortConfig(const struct audio_port_config *config);
+    status_t setAudioPortConfig(const struct audio_port_config* config) final
+            EXCLUDES_AudioFlinger_Mutex;
 
     /* 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
+            EXCLUDES_AudioFlinger_Mutex;
 
     /* 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 EXCLUDES_AudioFlinger_Mutex;
+    status_t audioPolicyReady() final { mAudioPolicyReady.store(true); return NO_ERROR; }
 
+    status_t getMicrophones(std::vector<media::MicrophoneInfoFw>* microphones) const final
+            EXCLUDES_AudioFlinger_Mutex;
 
-    virtual status_t getMicrophones(std::vector<media::MicrophoneInfoFw> *microphones);
+    status_t setAudioHalPids(const std::vector<pid_t>& pids) final
+            EXCLUDES_AudioFlinger_Mutex;
 
-    virtual status_t setAudioHalPids(const std::vector<pid_t>& pids);
+    status_t setVibratorInfos(const std::vector<media::AudioVibratorInfo>& vibratorInfos) final
+            EXCLUDES_AudioFlinger_Mutex;
 
-    virtual status_t setVibratorInfos(const std::vector<media::AudioVibratorInfo>& vibratorInfos);
+    status_t updateSecondaryOutputs(
+            const TrackSecondaryOutputsMap& trackSecondaryOutputs) final
+            EXCLUDES_AudioFlinger_Mutex;
 
-    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
+            EXCLUDES_AudioFlinger_Mutex;
 
-    virtual int32_t getAAudioMixerBurstCount();
+    int32_t getAAudioMixerBurstCount() const final EXCLUDES_AudioFlinger_Mutex;
 
-    virtual int32_t getAAudioHardwareBurstMinUsec();
+    int32_t getAAudioHardwareBurstMinUsec() const final EXCLUDES_AudioFlinger_Mutex;
 
-    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 EXCLUDES_AudioFlinger_Mutex;
 
-    virtual status_t setSimulateDeviceConnections(bool enabled);
+    status_t setSimulateDeviceConnections(bool enabled) final EXCLUDES_AudioFlinger_Mutex;
 
-    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
+            EXCLUDES_AudioFlinger_Mutex;
 
-    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 EXCLUDES_AudioFlinger_Mutex;
 
-    virtual status_t setBluetoothVariableLatencyEnabled(bool enabled);
+    status_t setBluetoothVariableLatencyEnabled(bool enabled) final EXCLUDES_AudioFlinger_Mutex;
 
-    virtual status_t isBluetoothVariableLatencyEnabled(bool* enabled);
+    status_t isBluetoothVariableLatencyEnabled(bool* enabled) const final
+            EXCLUDES_AudioFlinger_Mutex;
 
-    virtual status_t supportsBluetoothVariableLatency(bool* support);
+    status_t supportsBluetoothVariableLatency(bool* support) const final
+            EXCLUDES_AudioFlinger_Mutex;
 
-    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 EXCLUDES_AudioFlinger_Mutex;
 
-    status_t invalidateTracks(const std::vector<audio_port_handle_t>& portIds) override;
+    status_t invalidateTracks(const std::vector<audio_port_handle_t>& portIds) final
+            EXCLUDES_AudioFlinger_Mutex;
 
-    virtual status_t getAudioPolicyConfig(media::AudioPolicyConfig* config);
+    status_t getAudioPolicyConfig(media::AudioPolicyConfig* config) final
+            EXCLUDES_AudioFlinger_Mutex;
 
     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 EXCLUDES_AudioFlinger_Mutex;
 
-    // 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
+
+    audio_utils::mutex& clientMutex() const final
+            RETURN_CAPABILITY(audio_utils::AudioFlinger_ClientMutex) {
+        return mClientMutex;
+    }
+    void removeClient_l(pid_t pid) REQUIRES(clientMutex()) final;
+    void removeNotificationClient(pid_t pid) final EXCLUDES_AudioFlinger_Mutex;
+    status_t moveAuxEffectToIo(
+            int effectId,
+            const sp<IAfPlaybackThread>& dstThread,
+            sp<IAfPlaybackThread>* srcThread) final EXCLUDES_AudioFlinger_Mutex;
+
+    // ---- 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
+            EXCLUDES_AudioFlinger_HardwareMutex;
+    status_t removeEffectFromHal(
+            const struct audio_port_config* device, const sp<EffectHalInterface>& effect) final
+            EXCLUDES_AudioFlinger_HardwareMutex;
+
+    // ---- end of IAfDeviceEffectManagerCallback interface
+
+    // ---- begin IAfMelReporterCallback interface
+
+    // below also used by IAfThreadCallback
+    audio_utils::mutex& mutex() const final
+            RETURN_CAPABILITY(audio_utils::AudioFlinger_Mutex)
+            EXCLUDES_BELOW_AudioFlinger_Mutex { return mMutex; }
+    sp<IAfThreadBase> checkOutputThread_l(audio_io_handle_t ioHandle) const final
+            REQUIRES(mutex());
+
+    // ---- end of IAfMelReporterCallback interface
+
+    // ---- begin IAfPatchPanelCallback interface
+
+    void closeThreadInternal_l(const sp<IAfPlaybackThread>& thread) final REQUIRES(mutex());
+    void closeThreadInternal_l(const sp<IAfRecordThread>& thread) final REQUIRES(mutex());
+    // return thread associated with primary hardware device, or NULL
+    IAfPlaybackThread* primaryPlaybackThread_l() const final  REQUIRES(mutex());
+    IAfPlaybackThread* checkPlaybackThread_l(audio_io_handle_t output) const final
+            REQUIRES(mutex());
+    IAfRecordThread* checkRecordThread_l(audio_io_handle_t input) const final  REQUIRES(mutex());
+    IAfMmapThread* checkMmapThread_l(audio_io_handle_t io) const final REQUIRES(mutex());
+    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 REQUIRES(mutex());
+    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 REQUIRES(mutex());
+    const DefaultKeyedVector<audio_module_handle_t, AudioHwDevice*>&
+            getAudioHwDevs_l() const final REQUIRES(mutex()) { return mAudioHwDevs; }
+    void updateDownStreamPatches_l(const struct audio_patch* patch,
+            const std::set<audio_io_handle_t>& streams) final REQUIRES(mutex());
+    void updateOutDevicesForRecordThreads_l(const DeviceDescriptorBaseVector& devices) final
+            REQUIRES(mutex());
+
+    // ---- end of IAfPatchPanelCallback interface
+
+    // ----- begin IAfThreadCallback interface
+
+    bool isNonOffloadableGlobalEffectEnabled_l() const final REQUIRES(mutex());
+    bool btNrecIsOff() const final { return mBtNrecIsOff.load(); }
+    float masterVolume_l() const final REQUIRES(mutex());
+    bool masterMute_l() const final REQUIRES(mutex());
+    float getMasterBalance_l() const REQUIRES(mutex());
+    // no range check, AudioFlinger::mutex() held
+    bool streamMute_l(audio_stream_type_t stream) const final REQUIRES(mutex()) {
+        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
+            REQUIRES(mutex());
+    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
+            EXCLUDES_AudioFlinger_Mutex;
+
+    status_t moveEffectChain_ll(audio_session_t sessionId,
+            IAfPlaybackThread* srcThread, IAfPlaybackThread* dstThread) final
+            REQUIRES(mutex(), audio_utils::ThreadBase_Mutex);
+
+    // 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 REQUIRES(mutex());
+    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 EXCLUDES_AudioFlinger_Mutex;
+
+    void ioConfigChanged(audio_io_config_event_t event,
+            const sp<AudioIoDescriptor>& ioDesc,
+            pid_t pid = 0) final EXCLUDES_AudioFlinger_ClientMutex;
+    void onNonOffloadableGlobalEffectEnable() final EXCLUDES_AudioFlinger_Mutex;
+    void onSupportedLatencyModesChanged(
+            audio_io_handle_t output, const std::vector<audio_latency_mode_t>& modes) final
+            EXCLUDES_AudioFlinger_ClientMutex;
+
+    // ---- end of IAfThreadCallback interface
+
+    /* List available audio ports and their attributes */
+    status_t listAudioPorts(unsigned int* num_ports, struct audio_port* ports) const
+            EXCLUDES_AudioFlinger_Mutex;
+
     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,
@@ -342,22 +412,7 @@
                             audio_session_t *sessionId,
                             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();
-
+            audio_port_handle_t *handle) EXCLUDES_AudioFlinger_Mutex;
 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;
@@ -365,145 +420,33 @@
     // When a log writer is unregistered, it is done lazily so that media.log can continue to see it
     // for as long as possible.  The memory is only freed when it is needed for another log writer.
     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; }
+    audio_utils::mutex& unregisteredWritersMutex() const { return mUnregisteredWritersMutex; }
+    mutable audio_utils::mutex mUnregisteredWritersMutex;
 
                             AudioFlinger() ANDROID_API;
-    virtual                 ~AudioFlinger();
+    ~AudioFlinger() override;
 
     // call in any IAudioFlinger method that accesses mPrimaryHardwareDev
-    status_t                initCheck() const { return mPrimaryHardwareDev == NULL ?
+    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;
+            audio_devices_t deviceType) REQUIRES(mutex());
 
     // 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 mutex().
+    std::atomic_uint32_t mScreenState{};
 
-    // Internal dump utilities.
-    static const int kDumpLockTimeoutNs = 1 * NANOS_PER_SECOND;
-    static bool dumpTryLock(Mutex& mutex);
     void dumpPermissionDenial(int fd, const Vector<String16>& args);
-    void dumpClients(int fd, const Vector<String16>& args);
-    void dumpInternals(int fd, const Vector<String16>& args);
+    void dumpClients_ll(int fd, const Vector<String16>& args) REQUIRES(mutex(), clientMutex());
+    void dumpInternals_l(int fd, const Vector<String16>& args) REQUIRES(mutex());
 
     SimpleLog mThreadLog{16}; // 16 Thread history limit
 
-    class ThreadBase;
-    void dumpToThreadLog_l(const sp<ThreadBase> &thread);
-
-    // --- Client ---
-    class Client : public RefBase {
-      public:
-        Client(const sp<AudioFlinger>& audioFlinger, pid_t pid);
-        virtual             ~Client();
-        AllocatorFactory::ClientAllocator& allocator();
-        pid_t               pid() const { return mPid; }
-        sp<AudioFlinger>    audioFlinger() const { return mAudioFlinger; }
-
-    private:
-        DISALLOW_COPY_AND_ASSIGN(Client);
-
-        const sp<AudioFlinger>    mAudioFlinger;
-        const pid_t         mPid;
-        AllocatorFactory::ClientAllocator mClientAllocator;
-    };
+    void dumpToThreadLog_l(const sp<IAfThreadBase>& thread) REQUIRES(mutex());
 
     // --- Notification Client ---
     class NotificationClient : public IBinder::DeathRecipient {
@@ -550,92 +493,29 @@
         bool mPendingRequests;
 
         // Mutex and condition variable around mPendingRequests' value
-        Mutex       mMutex;
-        Condition   mCond;
+        audio_utils::mutex mMutex;
+        audio_utils::condition_variable mCondition;
 
         // Duration of the sleep period after a processed request
         static const int kPostTriggerSleepPeriod = 1000000;
     };
 
-    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();
-
-    class TrackHandle;
-    class RecordHandle;
-    class RecordThread;
-    class PlaybackThread;
-    class MixerThread;
-    class DirectOutputThread;
-    class OffloadThread;
-    class DuplicatingThread;
-    class AsyncCallbackThread;
-    class BitPerfectThread;
-    class Track;
-    class RecordTrack;
-    class EffectBase;
-    class EffectModule;
-    class EffectHandle;
-    class EffectChain;
-    class DeviceEffectProxy;
-    class DeviceEffectManager;
-    class PatchPanel;
-    class DeviceEffectManagerCallback;
-
-    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 "Effects.h"
-
-#include "DeviceEffectManager.h"
-
-#include "MelReporter.h"
+    const sp<MediaLogNotifier> mMediaLogNotifier = sp<MediaLogNotifier>::make();
 
     // Find io handle by session id.
     // Preference is given to an io handle with a matching effect chain to session id.
     // If none found, AUDIO_IO_HANDLE_NONE is returned.
     template <typename T>
     static audio_io_handle_t findIoHandleBySessionId_l(
-            audio_session_t sessionId, const T& threads) {
+            audio_session_t sessionId, const T& threads)
+            REQUIRES(audio_utils::AudioFlinger_Mutex) {
         audio_io_handle_t io = AUDIO_IO_HANDLE_NONE;
 
         for (size_t i = 0; i < threads.size(); i++) {
             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.
                 }
             }
@@ -643,130 +523,15 @@
         return io;
     }
 
-    // server side of the client's IAudioTrack
-    class TrackHandle : public android::media::BnAudioTrack {
-    public:
-        explicit            TrackHandle(const sp<PlaybackThread::Track>& track);
-        virtual             ~TrackHandle();
+    IAfThreadBase* checkThread_l(audio_io_handle_t ioHandle) const REQUIRES(mutex());
+    IAfPlaybackThread* checkMixerThread_l(audio_io_handle_t output) const REQUIRES(mutex());
 
-        binder::Status getCblk(std::optional<media::SharedFileRegion>* _aidl_return) override;
-        binder::Status start(int32_t* _aidl_return) override;
-        binder::Status stop() override;
-        binder::Status flush() override;
-        binder::Status pause() override;
-        binder::Status attachAuxEffect(int32_t effectId, int32_t* _aidl_return) override;
-        binder::Status setParameters(const std::string& keyValuePairs,
-                                     int32_t* _aidl_return) override;
-        binder::Status selectPresentation(int32_t presentationId, int32_t programId,
-                                          int32_t* _aidl_return) override;
-        binder::Status getTimestamp(media::AudioTimestampInternal* timestamp,
-                                    int32_t* _aidl_return) override;
-        binder::Status signal() override;
-        binder::Status applyVolumeShaper(const media::VolumeShaperConfiguration& configuration,
-                                         const media::VolumeShaperOperation& operation,
-                                         int32_t* _aidl_return) override;
-        binder::Status getVolumeShaperState(
-                int32_t id,
-                std::optional<media::VolumeShaperState>* _aidl_return) override;
-        binder::Status getDualMonoMode(
-                media::audio::common::AudioDualMonoMode* _aidl_return) override;
-        binder::Status setDualMonoMode(
-                media::audio::common::AudioDualMonoMode mode) override;
-        binder::Status getAudioDescriptionMixLevel(float* _aidl_return) override;
-        binder::Status setAudioDescriptionMixLevel(float leveldB) override;
-        binder::Status getPlaybackRateParameters(
-                media::audio::common::AudioPlaybackRate* _aidl_return) override;
-        binder::Status setPlaybackRateParameters(
-                const media::audio::common::AudioPlaybackRate& playbackRate) override;
+    sp<VolumeInterface> getVolumeInterface_l(audio_io_handle_t output) const REQUIRES(mutex());
+    std::vector<sp<VolumeInterface>> getAllVolumeInterfaces_l() const REQUIRES(mutex());
 
-    private:
-        const sp<PlaybackThread::Track> mTrack;
-    };
 
-    // server side of the client's IAudioRecord
-    class RecordHandle : public android::media::BnAudioRecord {
-    public:
-        explicit RecordHandle(const sp<RecordThread::RecordTrack>& recordTrack);
-        virtual             ~RecordHandle();
-        virtual binder::Status    start(int /*AudioSystem::sync_event_t*/ event,
-                int /*audio_session_t*/ triggerSession);
-        virtual binder::Status   stop();
-        virtual binder::Status   getActiveMicrophones(
-                std::vector<media::MicrophoneInfoFw>* activeMicrophones);
-        virtual binder::Status   setPreferredMicrophoneDirection(
-                int /*audio_microphone_direction_t*/ direction);
-        virtual binder::Status   setPreferredMicrophoneFieldDimension(float zoom);
-        virtual binder::Status   shareAudioHistory(const std::string& sharedAudioPackageName,
-                                                   int64_t sharedAudioStartMs);
-
-    private:
-        const sp<RecordThread::RecordTrack> mRecordTrack;
-
-        // for use from destructor
-        void                stop_nonvirtual();
-    };
-
-    // 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();
-
-        // 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;
-
-    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);
+    static 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),
@@ -779,38 +544,26 @@
               //       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);
-
-              status_t moveEffectChain_l(audio_session_t sessionId,
-                                     PlaybackThread *srcThread,
-                                     PlaybackThread *dstThread);
-
-              status_t moveAuxEffectToIo(int EffectId,
-                                         const sp<PlaybackThread>& dstThread,
-                                         sp<PlaybackThread> *srcThread);
+    // used by IAfDeviceEffectManagerCallback, IAfPatchPanelCallback, IAfThreadCallback
+    audio_unique_id_t nextUniqueId(audio_unique_id_use_t use) final;
 
               // return thread associated with primary hardware device, or NULL
-              PlaybackThread *primaryPlaybackThread_l() const;
-              DeviceTypeSet primaryOutputDevice_l() const;
+    DeviceTypeSet primaryOutputDevice_l() const REQUIRES(mutex());
 
               // return the playback thread with smallest HAL buffer size, and prefer fast
-              PlaybackThread *fastPlaybackThread_l() const;
+    IAfPlaybackThread* fastPlaybackThread_l() const REQUIRES(mutex());
 
-              sp<ThreadBase> getEffectThread_l(audio_session_t sessionId, int effectId);
+    sp<IAfThreadBase> getEffectThread_l(audio_session_t sessionId, int effectId)
+            REQUIRES(mutex());
 
-              ThreadBase *hapticPlaybackThread_l() const;
+    IAfThreadBase* hapticPlaybackThread_l() const REQUIRES(mutex());
 
               void updateSecondaryOutputsForTrack_l(
-                      PlaybackThread::Track* track,
-                      PlaybackThread* thread,
-                      const std::vector<audio_io_handle_t>& secondaryOutputs) const;
+                      IAfTrack* track,
+                      IAfPlaybackThread* thread,
+            const std::vector<audio_io_handle_t>& secondaryOutputs) const REQUIRES(mutex());
 
-
-                void        removeClient_l(pid_t pid);
-                void        removeNotificationClient(pid_t pid);
-                bool isNonOffloadableGlobalEffectEnabled_l();
-                void onNonOffloadableGlobalEffectEnable();
-                bool isSessionAcquired_l(audio_session_t audioSession);
+    bool isSessionAcquired_l(audio_session_t audioSession) REQUIRES(mutex());
 
                 // Store an effect chain to mOrphanEffectChains keyed vector.
                 // Called when a thread exits and effects are still attached to it.
@@ -819,51 +572,18 @@
                 // return ALREADY_EXISTS if a chain with the same session already exists in
                 // mOrphanEffectChains. Note that this should never happen as there is only one
                 // chain for a given session and it is attached to only one thread at a time.
-                status_t        putOrphanEffectChain_l(const sp<EffectChain>& chain);
+    status_t putOrphanEffectChain_l(const sp<IAfEffectChain>& chain) REQUIRES(mutex());
                 // 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<EffectChain> 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.
-                bool            updateOrphanEffectChains(const sp<EffectModule>& effect);
+    sp<IAfEffectChain> getOrphanEffectChain_l(audio_session_t session) REQUIRES(mutex());
 
-                std::vector< sp<EffectModule> > purgeStaleEffects_l();
+    std::vector< sp<IAfEffectModule> > purgeStaleEffects_l() REQUIRES(mutex());
 
-                void broadcastParametersToRecordThreads_l(const String8& keyValuePairs);
-                void updateOutDevicesForRecordThreads_l(const DeviceDescriptorBaseVector& devices);
-                void forwardParametersToDownstreamPatches_l(
+    void broadcastParametersToRecordThreads_l(const String8& keyValuePairs) REQUIRES(mutex());
+    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)
+            REQUIRES(mutex());
 
     // for mAudioSessionRefs only
     struct AudioSessionRef {
@@ -875,25 +595,28 @@
         int         mCnt;
     };
 
-    mutable     Mutex                               mLock;
+    mutable audio_utils::mutex mMutex;
                 // 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.
-    mutable     Mutex                               mClientLock;
-                // protected by mClientLock
-                DefaultKeyedVector< pid_t, wp<Client> >     mClients;   // see ~Client()
+                // must be locked after mutex() and ThreadBase::mutex() if both must be locked
+                // avoids acquiring AudioFlinger::mutex() from inside thread loop.
 
-                mutable     Mutex                   mHardwareLock;
-                // NOTE: If both mLock and mHardwareLock mutexes must be held,
-                // always take mLock before mHardwareLock
+    mutable audio_utils::mutex mClientMutex;
 
-                // guarded by mHardwareLock
-                AudioHwDevice* mPrimaryHardwareDev;
-                DefaultKeyedVector<audio_module_handle_t, AudioHwDevice*>  mAudioHwDevs;
+    DefaultKeyedVector<pid_t, wp<Client>> mClients GUARDED_BY(clientMutex());   // see ~Client()
 
-                // These two fields are immutable after onFirstRef(), so no lock needed to access
-                sp<DevicesFactoryHalInterface> mDevicesFactoryHal;
-                sp<DevicesFactoryHalCallback> mDevicesFactoryHalCallback;
+    audio_utils::mutex& hardwareMutex() const { return mHardwareMutex; }
+
+    mutable audio_utils::mutex mHardwareMutex;
+    // NOTE: If both mMutex and mHardwareMutex mutexes must be held,
+    // always take mMutex before mHardwareMutex
+
+    std::atomic<AudioHwDevice*> mPrimaryHardwareDev = nullptr;
+    DefaultKeyedVector<audio_module_handle_t, AudioHwDevice*> mAudioHwDevs
+            GUARDED_BY(hardwareMutex()) {nullptr /* defValue */};
+
+     const sp<DevicesFactoryHalInterface> mDevicesFactoryHal =
+             DevicesFactoryHalInterface::create();
+     /* const */ sp<DevicesFactoryHalCallback> mDevicesFactoryHalCallback;  // set onFirstRef().
 
     // for dump, indicates which hardware operation is currently in progress (but not stream ops)
     enum hardware_call_state {
@@ -923,131 +646,110 @@
         AUDIO_HW_SET_SIMULATE_CONNECTIONS, // setSimulateDeviceConnections
     };
 
-    mutable     hardware_call_state                 mHardwareStatus;    // for dump only
+    mutable hardware_call_state mHardwareStatus = AUDIO_HW_IDLE;  // for dump only
+    DefaultKeyedVector<audio_io_handle_t, sp<IAfPlaybackThread>> mPlaybackThreads
+            GUARDED_BY(mutex());
+    stream_type_t mStreamTypes[AUDIO_STREAM_CNT] GUARDED_BY(mutex());
 
+    float mMasterVolume GUARDED_BY(mutex()) = 1.f;
+    bool mMasterMute GUARDED_BY(mutex()) = false;
+    float mMasterBalance GUARDED_BY(mutex()) = 0.f;
 
-                DefaultKeyedVector< audio_io_handle_t, sp<PlaybackThread> >  mPlaybackThreads;
-                stream_type_t                       mStreamTypes[AUDIO_STREAM_CNT];
+    DefaultKeyedVector<audio_io_handle_t, sp<IAfRecordThread>> mRecordThreads GUARDED_BY(mutex());
 
-                // member variables below are protected by mLock
-                float                               mMasterVolume;
-                bool                                mMasterMute;
-                float                               mMasterBalance = 0.f;
-                // end of variables protected by mLock
-
-                DefaultKeyedVector< audio_io_handle_t, sp<RecordThread> >    mRecordThreads;
-
-                // protected by mClientLock
-                DefaultKeyedVector< pid_t, sp<NotificationClient> >    mNotificationClients;
+    DefaultKeyedVector<pid_t, sp<NotificationClient>> mNotificationClients
+            GUARDED_BY(clientMutex());
 
                 // updated by atomic_fetch_add_explicit
-                volatile atomic_uint_fast32_t       mNextUniqueIds[AUDIO_UNIQUE_ID_USE_MAX];
+    volatile atomic_uint_fast32_t mNextUniqueIds[AUDIO_UNIQUE_ID_USE_MAX];  // ctor init
 
-                audio_mode_t                        mMode;
-                std::atomic_bool                    mBtNrecIsOff;
+    std::atomic<audio_mode_t> mMode = AUDIO_MODE_INVALID;
+    std::atomic<bool> mBtNrecIsOff = false;
 
-                // protected by mLock
-                Vector<AudioSessionRef*> mAudioSessionRefs;
+    Vector<AudioSessionRef*> mAudioSessionRefs GUARDED_BY(mutex());
 
-                float       masterVolume_l() const;
-                float       getMasterBalance_l() const;
-                bool        masterMute_l() const;
-                AudioHwDevice* loadHwModule_l(const char *name);
+    AudioHwDevice* loadHwModule_ll(const char *name) REQUIRES(mutex(), hardwareMutex());
 
                 // sync events awaiting for a session to be created.
-                std::list<sp<audioflinger::SyncEvent>> mPendingSyncEvents;
+    std::list<sp<audioflinger::SyncEvent>> mPendingSyncEvents GUARDED_BY(mutex());
 
                 // Effect chains without a valid thread
-                DefaultKeyedVector< audio_session_t , sp<EffectChain> > mOrphanEffectChains;
+    DefaultKeyedVector<audio_session_t, sp<IAfEffectChain>> mOrphanEffectChains
+            GUARDED_BY(mutex());
 
                 // list of sessions for which a valid HW A/V sync ID was retrieved from the HAL
-                DefaultKeyedVector< audio_session_t , audio_hw_sync_t >mHwAvSyncIds;
+    DefaultKeyedVector<audio_session_t, audio_hw_sync_t> mHwAvSyncIds GUARDED_BY(mutex());
 
                 // 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 GUARDED_BY(mutex());
 
-private:
-    sp<Client>  registerPid(pid_t pid);    // always returns non-0
+    sp<Client> registerPid(pid_t pid) EXCLUDES_AudioFlinger_ClientMutex; // 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);
+    status_t closeOutput_nonvirtual(audio_io_handle_t output) EXCLUDES_AudioFlinger_Mutex;
+    status_t closeInput_nonvirtual(audio_io_handle_t input) EXCLUDES_AudioFlinger_Mutex;
+    void setAudioHwSyncForSession_l(IAfPlaybackThread* thread, audio_session_t sessionId)
+            REQUIRES(mutex());
 
-    status_t    checkStreamType(audio_stream_type_t stream) const;
+    static status_t checkStreamType(audio_stream_type_t stream);
 
+    // no mutex needed.
     void        filterReservedParameters(String8& keyValuePairs, uid_t callingUid);
     void        logFilteredParameters(size_t originalKVPSize, const String8& originalKVPs,
                                       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;
-    std::atomic<size_t> mClientSharedHeapSize;
+    std::atomic<bool> mIsLowRamDevice = true;
+    bool mIsDeviceTypeKnown GUARDED_BY(mutex()) = false;
+    int64_t mTotalMemory GUARDED_BY(mutex()) = 0;
+    std::atomic<size_t> mClientSharedHeapSize = kMinimumClientSharedHeapSizeBytes;
     static constexpr size_t kMinimumClientSharedHeapSizeBytes = 1024 * 1024; // 1MB
 
-    nsecs_t mGlobalEffectEnableTime;  // when a global effect was last enabled
+    // when a global effect was last enabled
+    nsecs_t mGlobalEffectEnableTime GUARDED_BY(mutex()) = 0;
 
-    // protected by mLock
-    PatchPanel mPatchPanel;
-    sp<EffectsFactoryHalInterface> mEffectsFactoryHal;
+    /* const */ sp<IAfPatchPanel> mPatchPanel;
 
-    const sp<PatchCommandThread> mPatchCommandThread;
-    sp<DeviceEffectManager> mDeviceEffectManager;
-    sp<MelReporter> mMelReporter;
+    const sp<EffectsFactoryHalInterface> mEffectsFactoryHal =
+            audioflinger::EffectConfiguration::getEffectsFactoryHal();
 
-    bool       mSystemReady;
-    std::atomic_bool mAudioPolicyReady{};
+    const sp<PatchCommandThread> mPatchCommandThread = sp<PatchCommandThread>::make();
+    /* const */ sp<DeviceEffectManager> mDeviceEffectManager;  // set onFirstRef
+    /* const */ sp<MelReporter> mMelReporter;  // set onFirstRef
 
-    mediautils::UidInfo mUidInfo;
+    bool mSystemReady GUARDED_BY(mutex()) = false;
+    std::atomic<bool> mAudioPolicyReady = false;
 
+    mediautils::UidInfo mUidInfo GUARDED_BY(mutex());
+
+    // no mutex needed.
     SimpleLog  mRejectedSetParameterLog;
     SimpleLog  mAppSetParameterLog;
     SimpleLog  mSystemSetParameterLog;
 
-    std::vector<media::AudioVibratorInfo> mAudioVibratorInfos;
+    std::vector<media::AudioVibratorInfo> mAudioVibratorInfos GUARDED_BY(mutex());
 
     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;
-    int32_t mAAudioHwBurstMinMicros = 0;
+             std::vector<media::audio::common::AudioMMapPolicyInfo>> mPolicyInfos
+             GUARDED_BY(mutex());
+    int32_t mAAudioBurstsPerBuffer GUARDED_BY(mutex()) = 0;
+    int32_t mAAudioHwBurstMinMicros GUARDED_BY(mutex()) = 0;
 
     /** Interface for interacting with the AudioService. */
-    mediautils::atomic_sp<IAudioManager>       mAudioManager;
+    mediautils::atomic_sp<IAudioManager> mAudioManager;
 
     // Bluetooth Variable latency control logic is enabled or disabled
-    std::atomic_bool mBluetoothLatencyModesEnabled;
+    std::atomic<bool> mBluetoothLatencyModesEnabled = true;
 };
 
-#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
new file mode 100644
index 0000000..ff0d751
--- /dev/null
+++ b/services/audioflinger/Client.h
@@ -0,0 +1,62 @@
+/*
+ * 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 <afutils/AllocatorFactory.h>
+#include <audio_utils/mutex.h>
+#include <android-base/macros.h>  // DISALLOW_COPY_AND_ASSIGN
+#include <utils/RefBase.h>        // avoid transitive dependency
+
+// TODO(b/291318727) Move to nested namespace
+namespace android {
+
+class IAfPlaybackThread;
+
+class IAfClientCallback : public virtual RefBase {
+public:
+    virtual audio_utils::mutex& clientMutex() const
+            RETURN_CAPABILITY(audio_utils::AudioFlinger_ClientMutex) = 0;
+    virtual void removeClient_l(pid_t pid) REQUIRES(clientMutex()) = 0;
+    virtual void removeNotificationClient(pid_t pid) EXCLUDES_AudioFlinger_Mutex = 0;
+
+    // used indirectly by clients.
+    virtual status_t moveAuxEffectToIo(
+            int effectId,
+            const sp<IAfPlaybackThread>& dstThread,
+            sp<IAfPlaybackThread>* srcThread) EXCLUDES_AudioFlinger_Mutex = 0;
+};
+
+class Client : public RefBase {
+public:
+    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; }
+    const auto& afClientCallback() const { return mAfClientCallback; }
+
+private:
+    DISALLOW_COPY_AND_ASSIGN(Client);
+
+    const sp<IAfClientCallback> mAfClientCallback;
+    const pid_t mPid;
+    AllocatorFactory::ClientAllocator mClientAllocator;
+};
+
+} // namespace android
diff --git a/services/audioflinger/DeviceEffectManager.cpp b/services/audioflinger/DeviceEffectManager.cpp
index f996157..0a7be75 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,12 +35,31 @@
 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(sp<DeviceEffectManagerCallback>::make(*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);
+    audio_utils::lock_guard _l(mutex());
     for (auto& effect : mDeviceEffects) {
         status_t status = effect.second->onCreatePatch(handle, patch);
         ALOGV("%s Effect onCreatePatch status %d", __func__, status);
@@ -47,27 +67,27 @@
     }
 }
 
-void AudioFlinger::DeviceEffectManager::onReleaseAudioPatch(audio_patch_handle_t handle) {
+void DeviceEffectManager::onReleaseAudioPatch(audio_patch_handle_t handle) {
     ALOGV("%s", __func__);
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mutex());
     for (auto& effect : mDeviceEffects) {
         effect.second->onReleasePatch(handle);
     }
 }
 
-// DeviceEffectManager::createEffect_l() must be called with AudioFlinger::mLock held
-sp<AudioFlinger::EffectHandle> AudioFlinger::DeviceEffectManager::createEffect_l(
+// DeviceEffectManager::createEffect_l() must be called with AudioFlinger::mutex() held
+sp<IAfEffectHandle> DeviceEffectManager::createEffect_l(
         effect_descriptor_t *descriptor,
         const AudioDeviceTypeAddr& device,
-        const sp<AudioFlinger::Client>& client,
+        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<DeviceEffectProxy> effect;
-    sp<EffectHandle> handle;
+    sp<IAfDeviceEffectProxy> effect;
+    sp<IAfEffectHandle> handle;
     status_t lStatus;
 
     lStatus = checkEffectCompatibility(descriptor);
@@ -77,18 +97,19 @@
     }
 
     {
-        Mutex::Autolock _l(mLock);
+        audio_utils::lock_guard _l(mutex());
         auto iter = mDeviceEffects.find(device);
         if (iter != mDeviceEffects.end()) {
             effect = iter->second;
         } else {
-            effect = new DeviceEffectProxy(device, mMyCallback,
-                    descriptor, mAudioFlinger.nextUniqueId(AUDIO_UNIQUE_ID_USE_EFFECT),
+            effect = IAfDeviceEffectProxy::create(device, mMyCallback,
+                    descriptor,
+                    mAfDeviceEffectManagerCallback->nextUniqueId(AUDIO_UNIQUE_ID_USE_EFFECT),
                     notifyFramesProcessed);
         }
         // create effect handle and connect it to effect module
-        handle = new EffectHandle(effect, client, effectClient, 0 /*priority*/,
-                                  notifyFramesProcessed);
+        handle = IAfEffectHandle::create(
+                effect, client, effectClient, 0 /*priority*/, notifyFramesProcessed);
         lStatus = handle->initCheck();
         if (lStatus == NO_ERROR) {
             lStatus = effect->addHandle(handle.get());
@@ -110,7 +131,8 @@
     return handle;
 }
 
-status_t AudioFlinger::DeviceEffectManager::checkEffectCompatibility(
+/* static */
+status_t DeviceEffectManager::checkEffectCompatibility(
         const effect_descriptor_t *desc) {
     const sp<EffectsFactoryHalInterface> effectsFactory =
             audioflinger::EffectConfiguration::getEffectsFactoryHal();
@@ -136,7 +158,8 @@
     return NO_ERROR;
 }
 
-status_t AudioFlinger::DeviceEffectManager::createEffectHal(
+/* static */
+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 +172,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(mutex());
     if (!locked) {
         String8 result("DeviceEffectManager may be deadlocked\n");
         write(fd, result.c_str(), result.size());
@@ -165,30 +188,29 @@
         outStr.appendFormat("%*sEffect for device %s address %s:\n", 2, "",
                 ::android::toString(iter.first.mType).c_str(), iter.first.getAddress());
         write(fd, outStr.c_str(), outStr.size());
-        iter.second->dump(fd, 4);
+        iter.second->dump2(fd, 4);
     }
 
     if (locked) {
-        mLock.unlock();
+        mutex().unlock();
     }
 }
 
-
-size_t AudioFlinger::DeviceEffectManager::removeEffect(const sp<DeviceEffectProxy>& effect)
+size_t DeviceEffectManager::removeEffect(const sp<IAfDeviceEffectProxy>& effect)
 {
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mutex());
     mDeviceEffects.erase(effect->device());
     return mDeviceEffects.size();
 }
 
-bool AudioFlinger::DeviceEffectManagerCallback::disconnectEffectHandle(
-        EffectHandle *handle, bool unpinIfLast) {
-    sp<EffectBase> effectBase = handle->effect().promote();
+bool DeviceEffectManagerCallback::disconnectEffectHandle(
+        IAfEffectHandle *handle, bool unpinIfLast) {
+    sp<IAfEffectBase> effectBase = handle->effect().promote();
     if (effectBase == nullptr) {
         return false;
     }
 
-    sp<DeviceEffectProxy> effect = effectBase->asDeviceEffectProxy();
+    sp<IAfDeviceEffectProxy> effect = effectBase->asDeviceEffectProxy();
     if (effect == nullptr) {
         return false;
     }
@@ -203,4 +225,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 b87f830..6a5c889 100644
--- a/services/audioflinger/DeviceEffectManager.h
+++ b/services/audioflinger/DeviceEffectManager.h
@@ -15,61 +15,77 @@
 ** 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"
+
+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)
+            EXCLUDES_AudioFlinger_HardwareMutex = 0;
+    virtual status_t removeEffectFromHal(
+            const struct audio_port_config* device, const sp<EffectHalInterface>& effect)
+            EXCLUDES_AudioFlinger_HardwareMutex= 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<EffectHandle> createEffect_l(effect_descriptor_t *descriptor,
+    sp<IAfEffectHandle> createEffect_l(effect_descriptor_t *descriptor,
                 const AudioDeviceTypeAddr& device,
-                const sp<AudioFlinger::Client>& client,
+                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,
-                bool notifyFramesProcessed);
+                bool notifyFramesProcessed) REQUIRES(audio_utils::AudioFlinger_Mutex);
 
-    size_t removeEffect(const sp<DeviceEffectProxy>& effect);
-    status_t createEffectHal(const effect_uuid_t *pEffectUuid,
+    size_t removeEffect(const sp<IAfDeviceEffectProxy>& effect);
+    static status_t createEffectHal(const effect_uuid_t *pEffectUuid,
            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
+            EXCLUDES_DeviceEffectManager_Mutex;
+    void onReleaseAudioPatch(audio_patch_handle_t handle) final
+            EXCLUDES_DeviceEffectManager_Mutex;
 
 private:
-    status_t checkEffectCompatibility(const effect_descriptor_t *desc);
+    static status_t checkEffectCompatibility(const effect_descriptor_t *desc);
 
-    Mutex mLock;
-    AudioFlinger &mAudioFlinger;
+    audio_utils::mutex& mutex() const RETURN_CAPABILITY(audio_utils::DeviceEffectManager_Mutex) {
+       return mMutex;
+   }
+    mutable audio_utils::mutex mMutex;
+    const sp<IAfDeviceEffectManagerCallback> mAfDeviceEffectManagerCallback;
     const sp<DeviceEffectManagerCallback> mMyCallback;
-    std::map<AudioDeviceTypeAddr, sp<DeviceEffectProxy>> mDeviceEffects;
+    std::map<AudioDeviceTypeAddr, sp<IAfDeviceEffectProxy>> mDeviceEffects GUARDED_BY(mutex());
 };
 
 class DeviceEffectManagerCallback : public EffectCallbackInterface {
@@ -78,59 +94,58 @@
         : mManager(manager) {}
 
     status_t createEffectHal(const effect_uuid_t *pEffectUuid,
-           int32_t sessionId, int32_t deviceId,
-           sp<EffectHalInterface> *effect) override {
+            int32_t sessionId, int32_t deviceId, sp<EffectHalInterface> *effect) final {
                 return mManager.createEffectHal(pEffectUuid, sessionId, deviceId, effect);
             }
     status_t allocateHalBuffer(size_t size __unused,
-            sp<EffectBufferHalInterface>* buffer __unused) override { return NO_ERROR; }
-    bool updateOrphanEffectChains(const sp<EffectBase>& effect __unused) override { return false; }
+            sp<EffectBufferHalInterface>* buffer __unused) final { return NO_ERROR; }
+    bool updateOrphanEffectChains(const sp<IAfEffectBase>& effect __unused) final {
+        return false;
+    }
 
-    audio_io_handle_t io() const override  { return AUDIO_IO_HANDLE_NONE; }
-    bool isOutput() const override { return false; }
-    bool isOffload() const override { return false; }
-    bool isOffloadOrDirect() const override { return false; }
-    bool isOffloadOrMmap() const override { return false; }
-    bool isSpatializer() const override { return false; }
+    audio_io_handle_t io() const final { return AUDIO_IO_HANDLE_NONE; }
+    bool isOutput() const final { return false; }
+    bool isOffload() const final { return false; }
+    bool isOffloadOrDirect() const final { return false; }
+    bool isOffloadOrMmap() const final { return false; }
+    bool isSpatializer() const final { return false; }
 
-    uint32_t  sampleRate() const override { return 0; }
-    audio_channel_mask_t inChannelMask(int id __unused) const override {
+    uint32_t sampleRate() const final { return 0; }
+    audio_channel_mask_t inChannelMask(int id __unused) const final {
         return AUDIO_CHANNEL_NONE;
     }
-    uint32_t inChannelCount(int id __unused) const override { return 0; }
-    audio_channel_mask_t outChannelMask() const override { return AUDIO_CHANNEL_NONE; }
-    uint32_t outChannelCount() const override { return 0; }
+    uint32_t inChannelCount(int id __unused) const final { return 0; }
+    audio_channel_mask_t outChannelMask() const final { return AUDIO_CHANNEL_NONE; }
+    uint32_t outChannelCount() const final { return 0; }
 
-    audio_channel_mask_t hapticChannelMask() const override { return AUDIO_CHANNEL_NONE; }
-    size_t    frameCount() const override  { return 0; }
-    uint32_t  latency() const override  { return 0; }
+    audio_channel_mask_t hapticChannelMask() const final { return AUDIO_CHANNEL_NONE; }
+    size_t frameCount() const final { return 0; }
+    uint32_t latency() const final { return 0; }
 
-    status_t addEffectToHal(const sp<EffectHalInterface>& /* effect */) override {
+    status_t addEffectToHal(const sp<EffectHalInterface>& /* effect */) final {
         return NO_ERROR;
     }
-    status_t removeEffectFromHal(const sp<EffectHalInterface>& /* effect */) override {
+    status_t removeEffectFromHal(const sp<EffectHalInterface>& /* effect */) final {
         return NO_ERROR;
     }
 
-    bool disconnectEffectHandle(EffectHandle *handle, bool unpinIfLast) override;
-    void setVolumeForOutput(float left __unused, float right __unused) const override {}
+    bool disconnectEffectHandle(IAfEffectHandle *handle, bool unpinIfLast) final;
+    void setVolumeForOutput(float left __unused, float right __unused) const final {}
 
     // check if effects should be suspended or restored when a given effect is enable or disabled
-    void checkSuspendOnEffectEnabled(const sp<EffectBase>& effect __unused,
-                          bool enabled __unused, bool threadLocked __unused) override {}
-    void resetVolume() override {}
-    product_strategy_t strategy() const override  { return static_cast<product_strategy_t>(0); }
-    int32_t activeTrackCnt() const override { return 0; }
-    void onEffectEnable(const sp<EffectBase>& effect __unused) override {}
-    void onEffectDisable(const sp<EffectBase>& effect __unused) override {}
+    void checkSuspendOnEffectEnabled(const sp<IAfEffectBase>& effect __unused,
+                          bool enabled __unused, bool threadLocked __unused) final {}
+    void resetVolume() final {}
+    product_strategy_t strategy() const final { return static_cast<product_strategy_t>(0); }
+    int32_t activeTrackCnt() const final { return 0; }
+    void onEffectEnable(const sp<IAfEffectBase>& effect __unused) final {}
+    void onEffectDisable(const sp<IAfEffectBase>& effect __unused) final {}
 
-    wp<EffectChain> chain() const override { return nullptr; }
+    wp<IAfEffectChain> chain() const final { 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) {
@@ -143,3 +158,5 @@
 private:
     DeviceEffectManager& mManager;
 };
+
+}  // namespace android
diff --git a/services/audioflinger/Effects.cpp b/services/audioflinger/Effects.cpp
index 081d9a9..0f3e130 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,21 +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 <algorithm>
 
 // ----------------------------------------------------------------------------
 
@@ -93,9 +96,9 @@
 // ----------------------------------------------------------------------------
 
 #undef LOG_TAG
-#define LOG_TAG "AudioFlinger::EffectBase"
+#define LOG_TAG "EffectBase"
 
-AudioFlinger::EffectBase::EffectBase(const sp<AudioFlinger::EffectCallbackInterface>& callback,
+EffectBase::EffectBase(const sp<EffectCallbackInterface>& callback,
                                         effect_descriptor_t *desc,
                                         int id,
                                         audio_session_t sessionId,
@@ -106,8 +109,8 @@
 {
 }
 
-// must be called with EffectModule::mLock held
-status_t AudioFlinger::EffectBase::setEnabled_l(bool enabled)
+// must be called with EffectModule::mutex() held
+status_t EffectBase::setEnabled_l(bool enabled)
 {
 
     ALOGV("setEnabled %p enabled %d", this, enabled);
@@ -139,7 +142,7 @@
             return NO_ERROR; // simply ignore as we are being destroyed
         }
         for (size_t i = 1; i < mHandles.size(); i++) {
-            EffectHandle *h = mHandles[i];
+            IAfEffectHandle *h = mHandles[i];
             if (h != NULL && !h->disconnected()) {
                 h->setEnabled(enabled);
             }
@@ -148,11 +151,11 @@
     return NO_ERROR;
 }
 
-status_t AudioFlinger::EffectBase::setEnabled(bool enabled, bool fromHandle)
+status_t EffectBase::setEnabled(bool enabled, bool fromHandle)
 {
     status_t status;
     {
-        Mutex::Autolock _l(mLock);
+        audio_utils::lock_guard _l(mutex());
         status = setEnabled_l(enabled);
     }
     if (fromHandle) {
@@ -169,7 +172,7 @@
     return status;
 }
 
-bool AudioFlinger::EffectBase::isEnabled() const
+bool EffectBase::isEnabled() const
 {
     switch (mState) {
     case RESTART:
@@ -185,29 +188,29 @@
     }
 }
 
-void AudioFlinger::EffectBase::setSuspended(bool suspended)
+void EffectBase::setSuspended(bool suspended)
 {
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mutex());
     mSuspended = suspended;
 }
 
-bool AudioFlinger::EffectBase::suspended() const
+bool EffectBase::suspended() const
 {
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mutex());
     return mSuspended;
 }
 
-status_t AudioFlinger::EffectBase::addHandle(EffectHandle *handle)
+status_t EffectBase::addHandle(IAfEffectHandle *handle)
 {
     status_t status;
 
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mutex());
     int priority = handle->priority();
     size_t size = mHandles.size();
-    EffectHandle *controlHandle = NULL;
+    IAfEffectHandle *controlHandle = nullptr;
     size_t i;
     for (i = 0; i < size; i++) {
-        EffectHandle *h = mHandles[i];
+        IAfEffectHandle *h = mHandles[i];
         if (h == NULL || h->disconnected()) {
             continue;
         }
@@ -236,7 +239,7 @@
     return status;
 }
 
-status_t AudioFlinger::EffectBase::updatePolicyState()
+status_t EffectBase::updatePolicyState()
 {
     status_t status = NO_ERROR;
     bool doRegister = false;
@@ -247,7 +250,7 @@
     product_strategy_t strategy = PRODUCT_STRATEGY_NONE;
 
     {
-        Mutex::Autolock _l(mLock);
+        audio_utils::lock_guard _l(mutex());
 
         if ((isInternal_l() && !mPolicyRegistered)
                 || !getCallback()->isAudioPolicyReady()) {
@@ -266,7 +269,7 @@
         }
         // enable effect when registered according to enable state requested by controlling handle
         if (mHandles.size() > 0) {
-            EffectHandle *handle = controlHandle_l();
+            IAfEffectHandle *handle = controlHandle_l();
             if (handle != nullptr && mPolicyEnabled != handle->enabled()) {
                 doEnable = true;
                 mPolicyEnabled = handle->enabled();
@@ -281,7 +284,7 @@
             return NO_ERROR;
         }
     }
-    mPolicyLock.lock();
+    policyMutex().lock();
     ALOGV("%s name %s id %d session %d doRegister %d registered %d doEnable %d enabled %d",
         __func__, mDescriptor.name, mId, mSessionId, doRegister, registered, doEnable, enabled);
     if (doRegister) {
@@ -299,19 +302,19 @@
     if (registered && doEnable) {
         status = AudioSystem::setEffectEnabled(mId, enabled);
     }
-    mPolicyLock.unlock();
+    policyMutex().unlock();
 
     return status;
 }
 
 
-ssize_t AudioFlinger::EffectBase::removeHandle(EffectHandle *handle)
+ssize_t EffectBase::removeHandle(IAfEffectHandle *handle)
 {
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mutex());
     return removeHandle_l(handle);
 }
 
-ssize_t AudioFlinger::EffectBase::removeHandle_l(EffectHandle *handle)
+ssize_t EffectBase::removeHandle_l(IAfEffectHandle *handle)
 {
     size_t size = mHandles.size();
     size_t i;
@@ -329,7 +332,7 @@
     mHandles.removeAt(i);
     // if removed from first place, move effect control from this handle to next in line
     if (i == 0) {
-        EffectHandle *h = controlHandle_l();
+        IAfEffectHandle *h = controlHandle_l();
         if (h != NULL) {
             h->setControl(true /*hasControl*/, true /*signal*/ , handle->enabled() /*enabled*/);
         }
@@ -345,12 +348,12 @@
     return mHandles.size();
 }
 
-// must be called with EffectModule::mLock held
-AudioFlinger::EffectHandle *AudioFlinger::EffectBase::controlHandle_l()
+// must be called with EffectModule::mutex() held
+IAfEffectHandle *EffectBase::controlHandle_l()
 {
     // the first valid handle in the list has control over the module
     for (size_t i = 0; i < mHandles.size(); i++) {
-        EffectHandle *h = mHandles[i];
+        IAfEffectHandle *h = mHandles[i];
         if (h != NULL && !h->disconnected()) {
             return h;
         }
@@ -360,7 +363,7 @@
 }
 
 // unsafe method called when the effect parent thread has been destroyed
-ssize_t AudioFlinger::EffectBase::disconnectHandle(EffectHandle *handle, bool unpinIfLast)
+ssize_t EffectBase::disconnectHandle(IAfEffectHandle *handle, bool unpinIfLast)
 {
     const auto callback = getCallback();
     ALOGV("disconnect() %p handle %p", this, handle);
@@ -368,21 +371,21 @@
         return mHandles.size();
     }
 
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mutex());
     ssize_t numHandles = removeHandle_l(handle);
     if ((numHandles == 0) && (!mPinned || unpinIfLast)) {
-        mLock.unlock();
+        mutex().unlock();
         callback->updateOrphanEffectChains(this);
-        mLock.lock();
+        mutex().lock();
     }
     return numHandles;
 }
 
-bool AudioFlinger::EffectBase::purgeHandles()
+bool EffectBase::purgeHandles()
 {
     bool enabled = false;
-    Mutex::Autolock _l(mLock);
-    EffectHandle *handle = controlHandle_l();
+    audio_utils::lock_guard _l(mutex());
+    IAfEffectHandle *handle = controlHandle_l();
     if (handle != NULL) {
         enabled = handle->enabled();
     }
@@ -390,7 +393,7 @@
     return enabled;
 }
 
-void AudioFlinger::EffectBase::checkSuspendOnEffectEnabled(bool enabled, bool threadLocked) {
+void EffectBase::checkSuspendOnEffectEnabled(bool enabled, bool threadLocked) {
     getCallback()->checkSuspendOnEffectEnabled(this, enabled, threadLocked);
 }
 
@@ -499,14 +502,14 @@
     return s;
 }
 
-void AudioFlinger::EffectBase::dump(int fd, const Vector<String16>& args __unused)
+void EffectBase::dump(int fd, const Vector<String16>& args __unused) const
 NO_THREAD_SAFETY_ANALYSIS // conditional try lock
 {
     String8 result;
 
     result.appendFormat("\tEffect ID %d:\n", mId);
 
-    bool locked = AudioFlinger::dumpTryLock(mLock);
+    const bool locked = afutils::dumpTryLock(mutex());
     // failed to lock - AudioFlinger is probably deadlocked
     if (!locked) {
         result.append("\t\tCould not lock Fx mutex:\n");
@@ -537,14 +540,14 @@
     result.append("\t\t\t  Pid Priority Ctrl Locked client server\n");
     char buffer[256];
     for (size_t i = 0; i < mHandles.size(); ++i) {
-        EffectHandle *handle = mHandles[i];
+        IAfEffectHandle *handle = mHandles[i];
         if (handle != NULL && !handle->disconnected()) {
             handle->dumpToBuffer(buffer, sizeof(buffer));
             result.append(buffer);
         }
     }
     if (locked) {
-        mLock.unlock();
+        mutex().unlock();
     }
 
     write(fd, result.c_str(), result.length());
@@ -555,9 +558,9 @@
 // ----------------------------------------------------------------------------
 
 #undef LOG_TAG
-#define LOG_TAG "AudioFlinger::EffectModule"
+#define LOG_TAG "EffectModule"
 
-AudioFlinger::EffectModule::EffectModule(const sp<AudioFlinger::EffectCallbackInterface>& callback,
+EffectModule::EffectModule(const sp<EffectCallbackInterface>& callback,
                                          effect_descriptor_t *desc,
                                          int id,
                                          audio_session_t sessionId,
@@ -599,7 +602,7 @@
     ALOGV("Constructor Error %d", mStatus);
 }
 
-AudioFlinger::EffectModule::~EffectModule()
+EffectModule::~EffectModule()
 {
     ALOGV("Destructor %p", this);
     if (mEffectInterface != 0) {
@@ -612,8 +615,8 @@
 
 }
 
-bool AudioFlinger::EffectModule::updateState() {
-    Mutex::Autolock _l(mLock);
+bool EffectModule::updateState() {
+    audio_utils::lock_guard _l(mutex());
 
     bool started = false;
     switch (mState) {
@@ -667,9 +670,9 @@
     return started;
 }
 
-void AudioFlinger::EffectModule::process()
+void EffectModule::process()
 {
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mutex());
 
     if (mState == DESTROYED || mEffectInterface == 0 || mInBuffer == 0 || mOutBuffer == 0) {
         return;
@@ -821,7 +824,7 @@
     }
 }
 
-void AudioFlinger::EffectModule::reset_l()
+void EffectModule::reset_l()
 {
     if (mStatus != NO_ERROR || mEffectInterface == 0) {
         return;
@@ -832,7 +835,7 @@
     mEffectInterface->command(EFFECT_CMD_RESET, 0, NULL, &replySize, &reply);
 }
 
-status_t AudioFlinger::EffectModule::configure()
+status_t EffectModule::configure()
 {
     ALOGVV("configure() started");
     status_t status;
@@ -1011,9 +1014,9 @@
     return status;
 }
 
-status_t AudioFlinger::EffectModule::init()
+status_t EffectModule::init()
 {
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mutex());
     if (mEffectInterface == 0) {
         return NO_INIT;
     }
@@ -1030,7 +1033,7 @@
     return status;
 }
 
-void AudioFlinger::EffectModule::addEffectToHal_l()
+void EffectModule::addEffectToHal_l()
 {
     if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_PRE_PROC ||
          (mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_POST_PROC) {
@@ -1043,12 +1046,12 @@
     }
 }
 
-// start() must be called with PlaybackThread::mLock or EffectChain::mLock held
-status_t AudioFlinger::EffectModule::start()
+// start() must be called with PlaybackThread::mutex() or EffectChain::mutex() held
+status_t EffectModule::start()
 {
     status_t status;
     {
-        Mutex::Autolock _l(mLock);
+        audio_utils::lock_guard _l(mutex());
         status = start_l();
     }
     if (status == NO_ERROR) {
@@ -1057,7 +1060,7 @@
     return status;
 }
 
-status_t AudioFlinger::EffectModule::start_l()
+status_t EffectModule::start_l()
 {
     if (mEffectInterface == 0) {
         return NO_INIT;
@@ -1081,13 +1084,13 @@
     return status;
 }
 
-status_t AudioFlinger::EffectModule::stop()
+status_t EffectModule::stop()
 {
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mutex());
     return stop_l();
 }
 
-status_t AudioFlinger::EffectModule::stop_l()
+status_t EffectModule::stop_l()
 {
     if (mEffectInterface == 0) {
         return NO_INIT;
@@ -1120,8 +1123,8 @@
     return status;
 }
 
-// must be called with EffectChain::mLock held
-void AudioFlinger::EffectModule::release_l()
+// must be called with EffectChain::mutex() held
+void EffectModule::release_l()
 {
     if (mEffectInterface != 0) {
         removeEffectFromHal_l();
@@ -1131,7 +1134,7 @@
     }
 }
 
-status_t AudioFlinger::EffectModule::removeEffectFromHal_l()
+status_t EffectModule::removeEffectFromHal_l()
 {
     if ((mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_PRE_PROC ||
              (mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_POST_PROC) {
@@ -1151,12 +1154,12 @@
     return remainder == 0 ? 0 : divisor - remainder;
 }
 
-status_t AudioFlinger::EffectModule::command(int32_t cmdCode,
+status_t EffectModule::command(int32_t cmdCode,
                      const std::vector<uint8_t>& cmdData,
                      int32_t maxReplySize,
                      std::vector<uint8_t>* reply)
 {
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mutex());
     ALOGVV("command(), cmdCode: %d, mEffectInterface: %p", cmdCode, mEffectInterface.get());
 
     if (mState == DESTROYED || mEffectInterface == 0) {
@@ -1224,7 +1227,7 @@
     reply->resize(status == NO_ERROR ? replySize : 0);
     if (cmdCode != EFFECT_CMD_GET_PARAM && status == NO_ERROR) {
         for (size_t i = 1; i < mHandles.size(); i++) {
-            EffectHandle *h = mHandles[i];
+            IAfEffectHandle *h = mHandles[i];
             if (h != NULL && !h->disconnected()) {
                 h->commandExecuted(cmdCode, cmdData, *reply);
             }
@@ -1233,7 +1236,7 @@
     return status;
 }
 
-bool AudioFlinger::EffectModule::isProcessEnabled() const
+bool EffectModule::isProcessEnabled() const
 {
     if (mStatus != NO_ERROR) {
         return false;
@@ -1253,17 +1256,17 @@
     }
 }
 
-bool AudioFlinger::EffectModule::isOffloadedOrDirect() const
+bool EffectModule::isOffloadedOrDirect() const
 {
     return getCallback()->isOffloadOrDirect();
 }
 
-bool AudioFlinger::EffectModule::isVolumeControlEnabled() const
+bool EffectModule::isVolumeControlEnabled() const
 {
     return (isVolumeControl() && (isOffloadedOrDirect() ? isEnabled() : isProcessEnabled()));
 }
 
-void AudioFlinger::EffectModule::setInBuffer(const sp<EffectBufferHalInterface>& buffer) {
+void EffectModule::setInBuffer(const sp<EffectBufferHalInterface>& buffer) {
     ALOGVV("setInBuffer %p",(&buffer));
 
     // mConfig.inputCfg.buffer.frameCount may be zero if configure() is not called yet.
@@ -1309,7 +1312,7 @@
     }
 }
 
-void AudioFlinger::EffectModule::setOutBuffer(const sp<EffectBufferHalInterface>& buffer) {
+void EffectModule::setOutBuffer(const sp<EffectBufferHalInterface>& buffer) {
     ALOGVV("setOutBuffer %p",(&buffer));
 
     // mConfig.outputCfg.buffer.frameCount may be zero if configure() is not called yet.
@@ -1351,9 +1354,9 @@
     }
 }
 
-status_t AudioFlinger::EffectModule::setVolume(uint32_t *left, uint32_t *right, bool controller)
+status_t EffectModule::setVolume(uint32_t *left, uint32_t *right, bool controller)
 {
-    AutoLockReentrant _l(mLock, mSetVolumeReentrantTid);
+    AutoLockReentrant _l(mutex(), mSetVolumeReentrantTid);
     if (mStatus != NO_ERROR) {
         return mStatus;
     }
@@ -1369,7 +1372,7 @@
     return status;
 }
 
-status_t AudioFlinger::EffectModule::setVolumeInternal(
+status_t EffectModule::setVolumeInternal(
         uint32_t *left, uint32_t *right, bool controller) {
     uint32_t volume[2] = {*left, *right};
     uint32_t *pVolume = controller ? volume : nullptr;
@@ -1386,7 +1389,7 @@
     return status;
 }
 
-void AudioFlinger::EffectChain::setVolumeForOutput_l(uint32_t left, uint32_t right)
+void EffectChain::setVolumeForOutput_l(uint32_t left, uint32_t right)
 {
     // for offload or direct thread, if the effect chain has non-offloadable
     // effect and any effect module within the chain has volume control, then
@@ -1399,7 +1402,7 @@
     }
 }
 
-status_t AudioFlinger::EffectModule::sendSetAudioDevicesCommand(
+status_t EffectModule::sendSetAudioDevicesCommand(
         const AudioDeviceTypeAddrVector &devices, uint32_t cmdCode)
 {
     audio_devices_t deviceType = deviceTypesToBitMask(getAudioDeviceTypes(devices));
@@ -1407,7 +1410,7 @@
         return NO_ERROR;
     }
 
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mutex());
     if (mStatus != NO_ERROR) {
         return mStatus;
     }
@@ -1425,19 +1428,19 @@
     return status;
 }
 
-status_t AudioFlinger::EffectModule::setDevices(const AudioDeviceTypeAddrVector &devices)
+status_t EffectModule::setDevices(const AudioDeviceTypeAddrVector &devices)
 {
     return sendSetAudioDevicesCommand(devices, EFFECT_CMD_SET_DEVICE);
 }
 
-status_t AudioFlinger::EffectModule::setInputDevice(const AudioDeviceTypeAddr &device)
+status_t EffectModule::setInputDevice(const AudioDeviceTypeAddr &device)
 {
     return sendSetAudioDevicesCommand({device}, EFFECT_CMD_SET_INPUT_DEVICE);
 }
 
-status_t AudioFlinger::EffectModule::setMode(audio_mode_t mode)
+status_t EffectModule::setMode(audio_mode_t mode)
 {
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mutex());
     if (mStatus != NO_ERROR) {
         return mStatus;
     }
@@ -1457,9 +1460,9 @@
     return status;
 }
 
-status_t AudioFlinger::EffectModule::setAudioSource(audio_source_t source)
+status_t EffectModule::setAudioSource(audio_source_t source)
 {
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mutex());
     if (mStatus != NO_ERROR) {
         return mStatus;
     }
@@ -1475,9 +1478,9 @@
     return status;
 }
 
-status_t AudioFlinger::EffectModule::setOffloaded(bool offloaded, audio_io_handle_t io)
+status_t EffectModule::setOffloaded(bool offloaded, audio_io_handle_t io)
 {
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mutex());
     if (mStatus != NO_ERROR) {
         return mStatus;
     }
@@ -1508,22 +1511,22 @@
     return status;
 }
 
-bool AudioFlinger::EffectModule::isOffloaded() const
+bool EffectModule::isOffloaded() const
 {
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mutex());
     return mOffloaded;
 }
 
 /*static*/
-bool AudioFlinger::EffectModule::isHapticGenerator(const effect_uuid_t *type) {
+bool IAfEffectModule::isHapticGenerator(const effect_uuid_t *type) {
     return memcmp(type, FX_IID_HAPTICGENERATOR, sizeof(effect_uuid_t)) == 0;
 }
 
-bool AudioFlinger::EffectModule::isHapticGenerator() const {
-    return isHapticGenerator(&mDescriptor.type);
+bool EffectModule::isHapticGenerator() const {
+    return IAfEffectModule::isHapticGenerator(&mDescriptor.type);
 }
 
-status_t AudioFlinger::EffectModule::setHapticIntensity(int id, os::HapticScale intensity)
+status_t EffectModule::setHapticIntensity(int id, os::HapticScale intensity)
 {
     if (mStatus != NO_ERROR) {
         return mStatus;
@@ -1549,7 +1552,7 @@
     return status;
 }
 
-status_t AudioFlinger::EffectModule::setVibratorInfo(const media::AudioVibratorInfo& vibratorInfo)
+status_t EffectModule::setVibratorInfo(const media::AudioVibratorInfo& vibratorInfo)
 {
     if (mStatus != NO_ERROR) {
         return mStatus;
@@ -1579,9 +1582,9 @@
     return status;
 }
 
-status_t AudioFlinger::EffectModule::getConfigs(
+status_t EffectModule::getConfigs(
         audio_config_base_t* inputCfg, audio_config_base_t* outputCfg, bool* isOutput) const {
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mutex());
     if (mConfig.inputCfg.mask == 0 || mConfig.outputCfg.mask == 0) {
         return NO_INIT;
     }
@@ -1610,13 +1613,13 @@
     return ss.str();
 }
 
-void AudioFlinger::EffectModule::dump(int fd, const Vector<String16>& args)
+void EffectModule::dump(int fd, const Vector<String16>& args) const
 NO_THREAD_SAFETY_ANALYSIS  // conditional try lock
 {
     EffectBase::dump(fd, args);
 
     String8 result;
-    bool locked = AudioFlinger::dumpTryLock(mLock);
+    const bool locked = afutils::dumpTryLock(mutex());
 
     result.append("\t\tStatus Engine:\n");
     result.appendFormat("\t\t%03d    %p\n",
@@ -1632,7 +1635,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");
@@ -1642,7 +1645,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",
@@ -1659,7 +1662,7 @@
     }
 
     if (locked) {
-        mLock.unlock();
+        mutex().unlock();
     }
 }
 
@@ -1668,10 +1671,21 @@
 // ----------------------------------------------------------------------------
 
 #undef LOG_TAG
-#define LOG_TAG "AudioFlinger::EffectHandle"
+#define LOG_TAG "EffectHandle"
 
-AudioFlinger::EffectHandle::EffectHandle(const sp<EffectBase>& effect,
-                                         const sp<AudioFlinger::Client>& client,
+/* static */
+sp<IAfEffectHandle> IAfEffectHandle::create(
+        const sp<IAfEffectBase>& effect,
+        const sp<Client>& client,
+        const sp<media::IEffectClient>& effectClient,
+        int32_t priority, bool notifyFramesProcessed)
+{
+    return sp<EffectHandle>::make(
+            effect, client, effectClient, priority, notifyFramesProcessed);
+}
+
+EffectHandle::EffectHandle(const sp<IAfEffectBase>& effect,
+                                         const sp<Client>& client,
                                          const sp<media::IEffectClient>& effectClient,
                                          int32_t priority, bool notifyFramesProcessed)
     : BnEffect(),
@@ -1705,7 +1719,7 @@
     mBuffer = (uint8_t *)mCblk + bufOffset;
 }
 
-AudioFlinger::EffectHandle::~EffectHandle()
+EffectHandle::~EffectHandle()
 {
     ALOGV("Destructor %p", this);
     disconnect(false);
@@ -1738,7 +1752,7 @@
     return methodStatistics;
 }
 
-status_t AudioFlinger::EffectHandle::onTransact(
+status_t EffectHandle::onTransact(
         uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) {
     const std::string methodName = getIEffectStatistics().getMethodForCode(code);
     mediautils::TimeCheck check(
@@ -1753,7 +1767,7 @@
     return BnEffect::onTransact(code, data, reply, flags);
 }
 
-status_t AudioFlinger::EffectHandle::initCheck()
+status_t EffectHandle::initCheck() const
 {
     return mClient == 0 || mCblkMemory != 0 ? OK : NO_MEMORY;
 }
@@ -1769,11 +1783,11 @@
         std::move(_tmp.value());                        \
     })
 
-Status AudioFlinger::EffectHandle::enable(int32_t* _aidl_return)
+Status EffectHandle::enable(int32_t* _aidl_return)
 {
-    AutoMutex _l(mLock);
+    audio_utils::lock_guard _l(mutex());
     ALOGV("enable %p", this);
-    sp<EffectBase> effect = mEffect.promote();
+    sp<IAfEffectBase> effect = mEffect.promote();
     if (effect == 0 || mDisconnected) {
         RETURN(DEAD_OBJECT);
     }
@@ -1807,11 +1821,11 @@
     RETURN(status);
 }
 
-Status AudioFlinger::EffectHandle::disable(int32_t* _aidl_return)
+Status EffectHandle::disable(int32_t* _aidl_return)
 {
     ALOGV("disable %p", this);
-    AutoMutex _l(mLock);
-    sp<EffectBase> effect = mEffect.promote();
+    audio_utils::lock_guard _l(mutex());
+    sp<IAfEffectBase> effect = mEffect.promote();
     if (effect == 0 || mDisconnected) {
         RETURN(DEAD_OBJECT);
     }
@@ -1834,16 +1848,16 @@
     RETURN(status);
 }
 
-Status AudioFlinger::EffectHandle::disconnect()
+Status EffectHandle::disconnect()
 {
     ALOGV("%s %p", __FUNCTION__, this);
     disconnect(true);
     return Status::ok();
 }
 
-void AudioFlinger::EffectHandle::disconnect(bool unpinIfLast)
+void EffectHandle::disconnect(bool unpinIfLast)
 {
-    AutoMutex _l(mLock);
+    audio_utils::lock_guard _l(mutex());
     ALOGV("disconnect(%s) %p", unpinIfLast ? "true" : "false", this);
     if (mDisconnected) {
         if (unpinIfLast) {
@@ -1853,7 +1867,7 @@
     }
     mDisconnected = true;
     {
-        sp<EffectBase> effect = mEffect.promote();
+        sp<IAfEffectBase> effect = mEffect.promote();
         if (effect != 0) {
             if (effect->disconnectHandle(this, unpinIfLast) > 0) {
                 ALOGW("%s Effect handle %p disconnected after thread destruction",
@@ -1870,24 +1884,24 @@
         }
         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);
+        audio_utils::lock_guard _l2(mClient->afClientCallback()->clientMutex());
         mClient.clear();
     }
 }
 
-Status AudioFlinger::EffectHandle::getCblk(media::SharedFileRegion* _aidl_return) {
+Status EffectHandle::getCblk(media::SharedFileRegion* _aidl_return) {
     LOG_ALWAYS_FATAL_IF(!convertIMemoryToSharedFileRegion(mCblkMemory, _aidl_return));
     return Status::ok();
 }
 
-Status AudioFlinger::EffectHandle::getConfig(
+Status EffectHandle::getConfig(
         media::EffectConfig* _config, int32_t* _aidl_return) {
-    AutoMutex _l(mLock);
-    sp<EffectBase> effect = mEffect.promote();
+    audio_utils::lock_guard _l(mutex());
+    sp<IAfEffectBase> effect = mEffect.promote();
     if (effect == nullptr || mDisconnected) {
         RETURN(DEAD_OBJECT);
     }
-    sp<EffectModule> effectModule = effect->asEffectModule();
+    sp<IAfEffectModule> effectModule = effect->asEffectModule();
     if (effectModule == nullptr) {
         RETURN(INVALID_OPERATION);
     }
@@ -1906,7 +1920,7 @@
     RETURN(status);
 }
 
-Status AudioFlinger::EffectHandle::command(int32_t cmdCode,
+Status EffectHandle::command(int32_t cmdCode,
                        const std::vector<uint8_t>& cmdData,
                        int32_t maxResponseSize,
                        std::vector<uint8_t>* response,
@@ -1949,8 +1963,8 @@
         return disable(_aidl_return);
     }
 
-    AutoMutex _l(mLock);
-    sp<EffectBase> effect = mEffect.promote();
+    audio_utils::lock_guard _l(mutex());
+    sp<IAfEffectBase> effect = mEffect.promote();
     if (effect == 0 || mDisconnected) {
         RETURN(DEAD_OBJECT);
     }
@@ -2039,7 +2053,7 @@
     RETURN(status);
 }
 
-void AudioFlinger::EffectHandle::setControl(bool hasControl, bool signal, bool enabled)
+void EffectHandle::setControl(bool hasControl, bool signal, bool enabled)
 {
     ALOGV("setControl %p control %d", this, hasControl);
 
@@ -2051,7 +2065,7 @@
     }
 }
 
-void AudioFlinger::EffectHandle::commandExecuted(uint32_t cmdCode,
+void EffectHandle::commandExecuted(uint32_t cmdCode,
                          const std::vector<uint8_t>& cmdData,
                          const std::vector<uint8_t>& replyData)
 {
@@ -2062,24 +2076,24 @@
 
 
 
-void AudioFlinger::EffectHandle::setEnabled(bool enabled)
+void EffectHandle::setEnabled(bool enabled)
 {
     if (mEffectClient != 0) {
         mEffectClient->enableStatusChanged(enabled);
     }
 }
 
-void AudioFlinger::EffectHandle::framesProcessed(int32_t frames) const
+void EffectHandle::framesProcessed(int32_t frames) const
 {
     if (mEffectClient != 0 && mNotifyFramesProcessed) {
         mEffectClient->framesProcessed(frames);
     }
 }
 
-void AudioFlinger::EffectHandle::dumpToBuffer(char* buffer, size_t size)
+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(),
@@ -2096,31 +2110,31 @@
 }
 
 #undef LOG_TAG
-#define LOG_TAG "AudioFlinger::EffectChain"
+#define LOG_TAG "EffectChain"
 
-AudioFlinger::EffectChain::EffectChain(const wp<ThreadBase>& thread,
+/* static */
+sp<IAfEffectChain> IAfEffectChain::create(
+        const sp<IAfThreadBase>& thread,
+        audio_session_t sessionId)
+{
+    return sp<EffectChain>::make(thread, sessionId);
+}
+
+EffectChain::EffectChain(const sp<IAfThreadBase>& thread,
                                        audio_session_t sessionId)
     : mSessionId(sessionId), mActiveTrackCnt(0), mTrackCnt(0), mTailBufferCount(0),
       mLeftVolume(UINT_MAX), mRightVolume(UINT_MAX),
       mNewLeftVolume(UINT_MAX), mNewRightVolume(UINT_MAX),
       mEffectCallback(new EffectCallback(wp<EffectChain>(this), thread))
 {
-    sp<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();
 }
 
-AudioFlinger::EffectChain::~EffectChain()
-{
-}
-
-// getEffectFromDesc_l() must be called with ThreadBase::mLock held
-sp<AudioFlinger::EffectModule> AudioFlinger::EffectChain::getEffectFromDesc_l(
-        effect_descriptor_t *descriptor)
+// getEffectFromDesc_l() must be called with IAfThreadBase::mutex() held
+sp<IAfEffectModule> EffectChain::getEffectFromDesc_l(
+        effect_descriptor_t *descriptor) const
 {
     size_t size = mEffects.size();
 
@@ -2132,8 +2146,8 @@
     return 0;
 }
 
-// getEffectFromId_l() must be called with ThreadBase::mLock held
-sp<AudioFlinger::EffectModule> AudioFlinger::EffectChain::getEffectFromId_l(int id)
+// getEffectFromId_l() must be called with IAfThreadBase::mutex() held
+sp<IAfEffectModule> EffectChain::getEffectFromId_l(int id) const
 {
     size_t size = mEffects.size();
 
@@ -2146,9 +2160,9 @@
     return 0;
 }
 
-// getEffectFromType_l() must be called with ThreadBase::mLock held
-sp<AudioFlinger::EffectModule> AudioFlinger::EffectChain::getEffectFromType_l(
-        const effect_uuid_t *type)
+// getEffectFromType_l() must be called with IAfThreadBase::mutex() held
+sp<IAfEffectModule> EffectChain::getEffectFromType_l(
+        const effect_uuid_t *type) const
 {
     size_t size = mEffects.size();
 
@@ -2160,24 +2174,24 @@
     return 0;
 }
 
-std::vector<int> AudioFlinger::EffectChain::getEffectIds()
+std::vector<int> EffectChain::getEffectIds() const
 {
     std::vector<int> ids;
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mutex());
     for (size_t i = 0; i < mEffects.size(); i++) {
         ids.push_back(mEffects[i]->id());
     }
     return ids;
 }
 
-void AudioFlinger::EffectChain::clearInputBuffer()
+void EffectChain::clearInputBuffer()
 {
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mutex());
     clearInputBuffer_l();
 }
 
-// Must be called with EffectChain::mLock locked
-void AudioFlinger::EffectChain::clearInputBuffer_l()
+// Must be called with EffectChain::mutex() locked
+void EffectChain::clearInputBuffer_l()
 {
     if (mInBuffer == NULL) {
         return;
@@ -2189,8 +2203,8 @@
     mInBuffer->commit();
 }
 
-// Must be called with EffectChain::mLock locked
-void AudioFlinger::EffectChain::process_l()
+// Must be called with EffectChain::mutex() locked
+void EffectChain::process_l()
 {
     // never process effects when:
     // - on an OFFLOAD thread
@@ -2241,14 +2255,14 @@
     }
 }
 
-// createEffect_l() must be called with ThreadBase::mLock held
-status_t AudioFlinger::EffectChain::createEffect_l(sp<EffectModule>& effect,
+// createEffect_l() must be called with IAfThreadBase::mutex() held
+status_t EffectChain::createEffect_l(sp<IAfEffectModule>& effect,
                                                    effect_descriptor_t *desc,
                                                    int id,
                                                    audio_session_t sessionId,
                                                    bool pinned)
 {
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mutex());
     effect = new EffectModule(mEffectCallback, desc, id, sessionId, pinned, AUDIO_PORT_HANDLE_NONE);
     status_t lStatus = effect->status();
     if (lStatus == NO_ERROR) {
@@ -2260,14 +2274,14 @@
     return lStatus;
 }
 
-// addEffect_l() must be called with ThreadBase::mLock held
-status_t AudioFlinger::EffectChain::addEffect_l(const sp<EffectModule>& effect)
+// addEffect_l() must be called with IAfThreadBase::mutex() held
+status_t EffectChain::addEffect_l(const sp<IAfEffectModule>& effect)
 {
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mutex());
     return addEffect_ll(effect);
 }
-// addEffect_l() must be called with ThreadBase::mLock and EffectChain::mLock held
-status_t AudioFlinger::EffectChain::addEffect_ll(const sp<EffectModule>& effect)
+// addEffect_l() must be called with IAfThreadBase::mutex() and EffectChain::mutex() held
+status_t EffectChain::addEffect_ll(const sp<IAfEffectModule>& effect)
 {
     effect->setCallback(mEffectCallback);
 
@@ -2347,7 +2361,7 @@
     return NO_ERROR;
 }
 
-std::optional<size_t> AudioFlinger::EffectChain::findVolumeControl_l(size_t from, size_t to) const {
+std::optional<size_t> EffectChain::findVolumeControl_l(size_t from, size_t to) const {
     for (size_t i = std::min(to, mEffects.size()); i > from; i--) {
         if (mEffects[i - 1]->isVolumeControlEnabled()) {
             return i - 1;
@@ -2356,7 +2370,7 @@
     return std::nullopt;
 }
 
-ssize_t AudioFlinger::EffectChain::getInsertIndex(const effect_descriptor_t& desc) {
+ssize_t EffectChain::getInsertIndex(const effect_descriptor_t& desc) {
     // Insert effects are inserted at the end of mEffects vector as they are processed
     //  after track and auxiliary effects.
     // Insert effect order as a function of indicated preference:
@@ -2429,11 +2443,11 @@
     return idx_insert;
 }
 
-// removeEffect_l() must be called with ThreadBase::mLock held
-size_t AudioFlinger::EffectChain::removeEffect_l(const sp<EffectModule>& effect,
+// removeEffect_l() must be called with IAfThreadBase::mutex() held
+size_t EffectChain::removeEffect_l(const sp<IAfEffectModule>& effect,
                                                  bool release)
 {
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mutex());
     size_t size = mEffects.size();
     uint32_t type = effect->desc().flags & EFFECT_FLAG_TYPE_MASK;
 
@@ -2477,8 +2491,8 @@
     return mEffects.size();
 }
 
-// setDevices_l() must be called with ThreadBase::mLock held
-void AudioFlinger::EffectChain::setDevices_l(const AudioDeviceTypeAddrVector &devices)
+// setDevices_l() must be called with IAfThreadBase::mutex() held
+void EffectChain::setDevices_l(const AudioDeviceTypeAddrVector &devices)
 {
     size_t size = mEffects.size();
     for (size_t i = 0; i < size; i++) {
@@ -2486,8 +2500,8 @@
     }
 }
 
-// setInputDevice_l() must be called with ThreadBase::mLock held
-void AudioFlinger::EffectChain::setInputDevice_l(const AudioDeviceTypeAddr &device)
+// setInputDevice_l() must be called with IAfThreadBase::mutex() held
+void EffectChain::setInputDevice_l(const AudioDeviceTypeAddr &device)
 {
     size_t size = mEffects.size();
     for (size_t i = 0; i < size; i++) {
@@ -2495,8 +2509,8 @@
     }
 }
 
-// setMode_l() must be called with ThreadBase::mLock held
-void AudioFlinger::EffectChain::setMode_l(audio_mode_t mode)
+// setMode_l() must be called with IAfThreadBase::mutex() held
+void EffectChain::setMode_l(audio_mode_t mode)
 {
     size_t size = mEffects.size();
     for (size_t i = 0; i < size; i++) {
@@ -2504,8 +2518,8 @@
     }
 }
 
-// setAudioSource_l() must be called with ThreadBase::mLock held
-void AudioFlinger::EffectChain::setAudioSource_l(audio_source_t source)
+// setAudioSource_l() must be called with IAfThreadBase::mutex() held
+void EffectChain::setAudioSource_l(audio_source_t source)
 {
     size_t size = mEffects.size();
     for (size_t i = 0; i < size; i++) {
@@ -2513,15 +2527,15 @@
     }
 }
 
-bool AudioFlinger::EffectChain::hasVolumeControlEnabled_l() const {
+bool EffectChain::hasVolumeControlEnabled_l() const {
     for (const auto &effect : mEffects) {
         if (effect->isVolumeControlEnabled()) return true;
     }
     return false;
 }
 
-// setVolume_l() must be called with ThreadBase::mLock or EffectChain::mLock held
-bool AudioFlinger::EffectChain::setVolume_l(uint32_t *left, uint32_t *right, bool force)
+// setVolume_l() must be called with IAfThreadBase::mutex() or EffectChain::mutex() held
+bool EffectChain::setVolume_l(uint32_t *left, uint32_t *right, bool force)
 {
     uint32_t newLeft = *left;
     uint32_t newRight = *right;
@@ -2530,9 +2544,9 @@
     // first update volume controller
     const auto volumeControlIndex = findVolumeControl_l(0, size);
     const int ctrlIdx = volumeControlIndex.value_or(-1);
-    const sp<EffectModule> volumeControlEffect =
+    const sp<IAfEffectModule> volumeControlEffect =
             volumeControlIndex.has_value() ? mEffects[ctrlIdx] : nullptr;
-    const sp<EffectModule> cachedVolumeControlEffect = mVolumeControlEffect.promote();
+    const sp<IAfEffectModule> cachedVolumeControlEffect = mVolumeControlEffect.promote();
 
     if (!force && volumeControlEffect == cachedVolumeControlEffect &&
             *left == mLeftVolume && *right == mRightVolume) {
@@ -2596,8 +2610,8 @@
     return volumeControlIndex.has_value();
 }
 
-// resetVolume_l() must be called with ThreadBase::mLock or EffectChain::mLock held
-void AudioFlinger::EffectChain::resetVolume_l()
+// resetVolume_l() must be called with IAfThreadBase::mutex() or EffectChain::mutex() held
+void EffectChain::resetVolume_l()
 {
     if ((mLeftVolume != UINT_MAX) && (mRightVolume != UINT_MAX)) {
         uint32_t left = mLeftVolume;
@@ -2606,8 +2620,9 @@
     }
 }
 
-// containsHapticGeneratingEffect_l must be called with ThreadBase::mLock or EffectChain::mLock held
-bool AudioFlinger::EffectChain::containsHapticGeneratingEffect_l()
+// containsHapticGeneratingEffect_l must be called with
+// IAfThreadBase::mutex() or EffectChain::mutex() held
+bool EffectChain::containsHapticGeneratingEffect_l()
 {
     for (size_t i = 0; i < mEffects.size(); ++i) {
         if (mEffects[i]->isHapticGenerator()) {
@@ -2617,17 +2632,17 @@
     return false;
 }
 
-void AudioFlinger::EffectChain::setHapticIntensity_l(int id, os::HapticScale intensity)
+void EffectChain::setHapticIntensity_l(int id, os::HapticScale intensity)
 {
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mutex());
     for (size_t i = 0; i < mEffects.size(); ++i) {
         mEffects[i]->setHapticIntensity(id, intensity);
     }
 }
 
-void AudioFlinger::EffectChain::syncHalEffectsState()
+void EffectChain::syncHalEffectsState()
 {
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mutex());
     for (size_t i = 0; i < mEffects.size(); i++) {
         if (mEffects[i]->state() == EffectModule::ACTIVE ||
                 mEffects[i]->state() == EffectModule::STOPPING) {
@@ -2636,7 +2651,7 @@
     }
 }
 
-void AudioFlinger::EffectChain::dump(int fd, const Vector<String16>& args)
+void EffectChain::dump(int fd, const Vector<String16>& args) const
 NO_THREAD_SAFETY_ANALYSIS  // conditional try lock
 {
     String8 result;
@@ -2645,7 +2660,7 @@
     result.appendFormat("    %zu effects for session %d\n", numEffects, mSessionId);
 
     if (numEffects) {
-        bool locked = AudioFlinger::dumpTryLock(mLock);
+        const bool locked = afutils::dumpTryLock(mutex());
         // failed to lock - AudioFlinger is probably deadlocked
         if (!locked) {
             result.append("\tCould not lock mutex:\n");
@@ -2661,22 +2676,22 @@
         write(fd, result.c_str(), result.size());
 
         for (size_t i = 0; i < numEffects; ++i) {
-            sp<EffectModule> effect = mEffects[i];
+            sp<IAfEffectModule> effect = mEffects[i];
             if (effect != 0) {
                 effect->dump(fd, args);
             }
         }
 
         if (locked) {
-            mLock.unlock();
+            mutex().unlock();
         }
     } else {
         write(fd, result.c_str(), result.size());
     }
 }
 
-// must be called with ThreadBase::mLock held
-void AudioFlinger::EffectChain::setEffectSuspended_l(
+// must be called with IAfThreadBase::mutex() held
+void EffectChain::setEffectSuspended_l(
         const effect_uuid_t *type, bool suspend)
 {
     sp<SuspendedEffectDesc> desc;
@@ -2694,7 +2709,7 @@
         }
 
         if (desc->mRefCount++ == 0) {
-            sp<EffectModule> effect = getEffectIfEnabled(type);
+            sp<IAfEffectModule> effect = getEffectIfEnabled(type);
             if (effect != 0) {
                 desc->mEffect = effect;
                 effect->setSuspended(true);
@@ -2714,15 +2729,15 @@
         if (--desc->mRefCount == 0) {
             ALOGV("setEffectSuspended_l() remove entry for %08x", mSuspendedEffects.keyAt(index));
             if (desc->mEffect != 0) {
-                sp<EffectModule> effect = desc->mEffect.promote();
+                sp<IAfEffectModule> effect = desc->mEffect.promote();
                 if (effect != 0) {
                     effect->setSuspended(false);
-                    effect->lock();
-                    EffectHandle *handle = effect->controlHandle_l();
+                    effect->mutex().lock();
+                    IAfEffectHandle *handle = effect->controlHandle_l();
                     if (handle != NULL && !handle->disconnected()) {
                         effect->setEnabled_l(handle->enabled());
                     }
-                    effect->unlock();
+                    effect->mutex().unlock();
                 }
                 desc->mEffect.clear();
             }
@@ -2731,8 +2746,8 @@
     }
 }
 
-// must be called with ThreadBase::mLock held
-void AudioFlinger::EffectChain::setEffectSuspendedAll_l(bool suspend)
+// must be called with IAfThreadBase::mutex() held
+void EffectChain::setEffectSuspendedAll_l(bool suspend)
 {
     sp<SuspendedEffectDesc> desc;
 
@@ -2746,7 +2761,7 @@
             ALOGV("setEffectSuspendedAll_l() add entry for 0");
         }
         if (desc->mRefCount++ == 0) {
-            Vector< sp<EffectModule> > effects;
+            Vector< sp<IAfEffectModule> > effects;
             getSuspendEligibleEffects(effects);
             for (size_t i = 0; i < effects.size(); i++) {
                 setEffectSuspended_l(&effects[i]->desc().type, true);
@@ -2788,7 +2803,7 @@
 #endif //OPENSL_ES_H_
 
 /* static */
-bool AudioFlinger::EffectChain::isEffectEligibleForBtNrecSuspend(const effect_uuid_t *type)
+bool EffectChain::isEffectEligibleForBtNrecSuspend(const effect_uuid_t *type)
 {
     // Only NS and AEC are suspended when BtNRec is off
     if ((memcmp(type, FX_IID_AEC, sizeof(effect_uuid_t)) == 0) ||
@@ -2798,7 +2813,7 @@
     return false;
 }
 
-bool AudioFlinger::EffectChain::isEffectEligibleForSuspend(const effect_descriptor_t& desc)
+bool EffectChain::isEffectEligibleForSuspend(const effect_descriptor_t& desc)
 {
     // auxiliary effects and visualizer are never suspended on output mix
     if ((mSessionId == AUDIO_SESSION_OUTPUT_MIX) &&
@@ -2811,8 +2826,8 @@
     return true;
 }
 
-void AudioFlinger::EffectChain::getSuspendEligibleEffects(
-        Vector< sp<AudioFlinger::EffectModule> > &effects)
+void EffectChain::getSuspendEligibleEffects(
+        Vector< sp<IAfEffectModule> > &effects)
 {
     effects.clear();
     for (size_t i = 0; i < mEffects.size(); i++) {
@@ -2822,14 +2837,13 @@
     }
 }
 
-sp<AudioFlinger::EffectModule> AudioFlinger::EffectChain::getEffectIfEnabled(
-                                                            const effect_uuid_t *type)
+sp<IAfEffectModule> EffectChain::getEffectIfEnabled(const effect_uuid_t *type)
 {
-    sp<EffectModule> effect = getEffectFromType_l(type);
+    sp<IAfEffectModule> effect = getEffectFromType_l(type);
     return effect != 0 && effect->isEnabled() ? effect : 0;
 }
 
-void AudioFlinger::EffectChain::checkSuspendOnEffectEnabled(const sp<EffectModule>& effect,
+void EffectChain::checkSuspendOnEffectEnabled(const sp<IAfEffectModule>& effect,
                                                             bool enabled)
 {
     ssize_t index = mSuspendedEffects.indexOfKey(effect->desc().type.timeLow);
@@ -2871,13 +2885,13 @@
     }
 }
 
-bool AudioFlinger::EffectChain::isNonOffloadableEnabled()
+bool EffectChain::isNonOffloadableEnabled() const
 {
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mutex());
     return isNonOffloadableEnabled_l();
 }
 
-bool AudioFlinger::EffectChain::isNonOffloadableEnabled_l()
+bool EffectChain::isNonOffloadableEnabled_l() const
 {
     size_t size = mEffects.size();
     for (size_t i = 0; i < size; i++) {
@@ -2888,13 +2902,13 @@
     return false;
 }
 
-void AudioFlinger::EffectChain::setThread(const sp<ThreadBase>& thread)
+void EffectChain::setThread(const sp<IAfThreadBase>& thread)
 {
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mutex());
     mEffectCallback->setThread(thread);
 }
 
-void AudioFlinger::EffectChain::checkOutputFlagCompatibility(audio_output_flags_t *flags) const
+void EffectChain::checkOutputFlagCompatibility(audio_output_flags_t *flags) const
 {
     if ((*flags & AUDIO_OUTPUT_FLAG_RAW) != 0 && !isRawCompatible()) {
         *flags = (audio_output_flags_t)(*flags & ~AUDIO_OUTPUT_FLAG_RAW);
@@ -2907,7 +2921,7 @@
     }
 }
 
-void AudioFlinger::EffectChain::checkInputFlagCompatibility(audio_input_flags_t *flags) const
+void EffectChain::checkInputFlagCompatibility(audio_input_flags_t *flags) const
 {
     if ((*flags & AUDIO_INPUT_FLAG_RAW) != 0 && !isRawCompatible()) {
         *flags = (audio_input_flags_t)(*flags & ~AUDIO_INPUT_FLAG_RAW);
@@ -2917,9 +2931,9 @@
     }
 }
 
-bool AudioFlinger::EffectChain::isRawCompatible() const
+bool EffectChain::isRawCompatible() const
 {
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mutex());
     for (const auto &effect : mEffects) {
         if (effect->isProcessImplemented()) {
             return false;
@@ -2929,9 +2943,9 @@
     return true;
 }
 
-bool AudioFlinger::EffectChain::isFastCompatible() const
+bool EffectChain::isFastCompatible() const
 {
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mutex());
     for (const auto &effect : mEffects) {
         if (effect->isProcessImplemented()
                 && effect->isImplementationSoftware()) {
@@ -2942,8 +2956,8 @@
     return true;
 }
 
-bool AudioFlinger::EffectChain::isBitPerfectCompatible() const {
-    Mutex::Autolock _l(mLock);
+bool EffectChain::isBitPerfectCompatible() const {
+    audio_utils::lock_guard _l(mutex());
     for (const auto &effect : mEffects) {
         if (effect->isProcessImplemented()
                 && effect->isImplementationSoftware()) {
@@ -2954,10 +2968,10 @@
     return true;
 }
 
-// isCompatibleWithThread_l() must be called with thread->mLock held
-bool AudioFlinger::EffectChain::isCompatibleWithThread_l(const sp<ThreadBase>& thread) const
+// isCompatibleWithThread_l() must be called with thread->mutex() held
+bool EffectChain::isCompatibleWithThread_l(const sp<IAfThreadBase>& thread) const
 {
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mutex());
     for (size_t i = 0; i < mEffects.size(); i++) {
         if (thread->checkEffectCompatibility_l(&(mEffects[i]->desc()), mSessionId) != NO_ERROR) {
             return false;
@@ -2967,7 +2981,7 @@
 }
 
 // EffectCallbackInterface implementation
-status_t AudioFlinger::EffectChain::EffectCallback::createEffectHal(
+status_t EffectChain::EffectCallback::createEffectHal(
         const effect_uuid_t *pEffectUuid, int32_t sessionId, int32_t deviceId,
         sp<EffectHalInterface> *effect) {
     status_t status = NO_INIT;
@@ -2979,21 +2993,21 @@
     return status;
 }
 
-bool AudioFlinger::EffectChain::EffectCallback::updateOrphanEffectChains(
-        const sp<AudioFlinger::EffectBase>& effect) {
+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 AudioFlinger::EffectChain::EffectCallback::allocateHalBuffer(
+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 AudioFlinger::EffectChain::EffectCallback::addEffectToHal(
+status_t EffectChain::EffectCallback::addEffectToHal(
         const sp<EffectHalInterface>& effect) {
     status_t result = NO_INIT;
-    sp<ThreadBase> t = thread().promote();
+    const sp<IAfThreadBase> t = thread().promote();
     if (t == nullptr) {
         return result;
     }
@@ -3006,10 +3020,10 @@
     return result;
 }
 
-status_t AudioFlinger::EffectChain::EffectCallback::removeEffectFromHal(
+status_t EffectChain::EffectCallback::removeEffectFromHal(
         const sp<EffectHalInterface>& effect) {
     status_t result = NO_INIT;
-    sp<ThreadBase> t = thread().promote();
+    const sp<IAfThreadBase> t = thread().promote();
     if (t == nullptr) {
         return result;
     }
@@ -3022,64 +3036,65 @@
     return result;
 }
 
-audio_io_handle_t AudioFlinger::EffectChain::EffectCallback::io() const {
-    sp<ThreadBase> t = thread().promote();
+audio_io_handle_t EffectChain::EffectCallback::io() const {
+    const sp<IAfThreadBase> t = thread().promote();
     if (t == nullptr) {
         return AUDIO_IO_HANDLE_NONE;
     }
     return t->id();
 }
 
-bool AudioFlinger::EffectChain::EffectCallback::isOutput() const {
-    sp<ThreadBase> t = thread().promote();
+bool EffectChain::EffectCallback::isOutput() const {
+    const sp<IAfThreadBase> t = thread().promote();
     if (t == nullptr) {
         return true;
     }
     return t->isOutput();
 }
 
-bool AudioFlinger::EffectChain::EffectCallback::isOffload() const {
-    return mThreadType == ThreadBase::OFFLOAD;
+bool EffectChain::EffectCallback::isOffload() const {
+    return mThreadType == IAfThreadBase::OFFLOAD;
 }
 
-bool AudioFlinger::EffectChain::EffectCallback::isOffloadOrDirect() const {
-    return mThreadType == ThreadBase::OFFLOAD || mThreadType == ThreadBase::DIRECT;
+bool EffectChain::EffectCallback::isOffloadOrDirect() const {
+    return mThreadType == IAfThreadBase::OFFLOAD
+            || mThreadType == IAfThreadBase::DIRECT;
 }
 
-bool AudioFlinger::EffectChain::EffectCallback::isOffloadOrMmap() const {
+bool EffectChain::EffectCallback::isOffloadOrMmap() const {
     switch (mThreadType) {
-    case ThreadBase::OFFLOAD:
-    case ThreadBase::MMAP_PLAYBACK:
-    case ThreadBase::MMAP_CAPTURE:
+    case IAfThreadBase::OFFLOAD:
+    case IAfThreadBase::MMAP_PLAYBACK:
+    case IAfThreadBase::MMAP_CAPTURE:
         return true;
     default:
         return false;
     }
 }
 
-bool AudioFlinger::EffectChain::EffectCallback::isSpatializer() const {
-    return mThreadType == ThreadBase::SPATIALIZER;
+bool EffectChain::EffectCallback::isSpatializer() const {
+    return mThreadType == IAfThreadBase::SPATIALIZER;
 }
 
-uint32_t AudioFlinger::EffectChain::EffectCallback::sampleRate() const {
-    sp<ThreadBase> t = thread().promote();
+uint32_t EffectChain::EffectCallback::sampleRate() const {
+    const sp<IAfThreadBase> t = thread().promote();
     if (t == nullptr) {
         return 0;
     }
     return t->sampleRate();
 }
 
-audio_channel_mask_t AudioFlinger::EffectChain::EffectCallback::inChannelMask(int id) const {
-    sp<ThreadBase> t = thread().promote();
+audio_channel_mask_t EffectChain::EffectCallback::inChannelMask(int id) const {
+    const sp<IAfThreadBase> t = thread().promote();
     if (t == nullptr) {
         return AUDIO_CHANNEL_NONE;
     }
-    sp<EffectChain> c = chain().promote();
+    sp<IAfEffectChain> c = chain().promote();
     if (c == nullptr) {
         return AUDIO_CHANNEL_NONE;
     }
 
-    if (mThreadType == ThreadBase::SPATIALIZER) {
+    if (mThreadType == IAfThreadBase::SPATIALIZER) {
         if (c->sessionId() == AUDIO_SESSION_OUTPUT_STAGE) {
             if (c->isFirstEffect(id)) {
                 return t->mixerChannelMask();
@@ -3087,7 +3102,8 @@
                 return t->channelMask();
             }
         } else if (!audio_is_global_session(c->sessionId())) {
-            if ((t->hasAudioSession_l(c->sessionId()) & ThreadBase::SPATIALIZED_SESSION) != 0) {
+            if ((t->hasAudioSession_l(c->sessionId())
+                    & IAfThreadBase::SPATIALIZED_SESSION) != 0) {
                 return t->mixerChannelMask();
             } else {
                 return t->channelMask();
@@ -3100,23 +3116,24 @@
     }
 }
 
-uint32_t AudioFlinger::EffectChain::EffectCallback::inChannelCount(int id) const {
+uint32_t EffectChain::EffectCallback::inChannelCount(int id) const {
     return audio_channel_count_from_out_mask(inChannelMask(id));
 }
 
-audio_channel_mask_t AudioFlinger::EffectChain::EffectCallback::outChannelMask() const {
-    sp<ThreadBase> t = thread().promote();
+audio_channel_mask_t EffectChain::EffectCallback::outChannelMask() const {
+    const sp<IAfThreadBase> t = thread().promote();
     if (t == nullptr) {
         return AUDIO_CHANNEL_NONE;
     }
-    sp<EffectChain> c = chain().promote();
+    sp<IAfEffectChain> c = chain().promote();
     if (c == nullptr) {
         return AUDIO_CHANNEL_NONE;
     }
 
-    if (mThreadType == ThreadBase::SPATIALIZER) {
+    if (mThreadType == IAfThreadBase::SPATIALIZER) {
         if (!audio_is_global_session(c->sessionId())) {
-            if ((t->hasAudioSession_l(c->sessionId()) & ThreadBase::SPATIALIZED_SESSION) != 0) {
+            if ((t->hasAudioSession_l(c->sessionId())
+                    & IAfThreadBase::SPATIALIZED_SESSION) != 0) {
                 return t->mixerChannelMask();
             } else {
                 return t->channelMask();
@@ -3129,30 +3146,30 @@
     }
 }
 
-uint32_t AudioFlinger::EffectChain::EffectCallback::outChannelCount() const {
+uint32_t EffectChain::EffectCallback::outChannelCount() const {
     return audio_channel_count_from_out_mask(outChannelMask());
 }
 
-audio_channel_mask_t AudioFlinger::EffectChain::EffectCallback::hapticChannelMask() const {
-    sp<ThreadBase> t = thread().promote();
+audio_channel_mask_t EffectChain::EffectCallback::hapticChannelMask() const {
+    const sp<IAfThreadBase> t = thread().promote();
     if (t == nullptr) {
         return AUDIO_CHANNEL_NONE;
     }
     return t->hapticChannelMask();
 }
 
-size_t AudioFlinger::EffectChain::EffectCallback::frameCount() const {
-    sp<ThreadBase> t = thread().promote();
+size_t EffectChain::EffectCallback::frameCount() const {
+    const sp<IAfThreadBase> t = thread().promote();
     if (t == nullptr) {
         return 0;
     }
     return t->frameCount();
 }
 
-uint32_t AudioFlinger::EffectChain::EffectCallback::latency() const
+uint32_t EffectChain::EffectCallback::latency() const
 NO_THREAD_SAFETY_ANALYSIS  // latency_l() access
 {
-    sp<ThreadBase> t = thread().promote();
+    const sp<IAfThreadBase> t = thread().promote();
     if (t == nullptr) {
         return 0;
     }
@@ -3160,25 +3177,25 @@
     return t->latency_l();
 }
 
-void AudioFlinger::EffectChain::EffectCallback::setVolumeForOutput(float left, float right) const
+void EffectChain::EffectCallback::setVolumeForOutput(float left, float right) const
 NO_THREAD_SAFETY_ANALYSIS  // setVolumeForOutput_l() access
 {
-    sp<ThreadBase> t = thread().promote();
+    const sp<IAfThreadBase> t = thread().promote();
     if (t == nullptr) {
         return;
     }
     t->setVolumeForOutput_l(left, right);
 }
 
-void AudioFlinger::EffectChain::EffectCallback::checkSuspendOnEffectEnabled(
-        const sp<EffectBase>& effect, bool enabled, bool threadLocked) {
-    sp<ThreadBase> t = thread().promote();
+void EffectChain::EffectCallback::checkSuspendOnEffectEnabled(
+        const sp<IAfEffectBase>& effect, bool enabled, bool threadLocked) {
+    const sp<IAfThreadBase> t = thread().promote();
     if (t == nullptr) {
         return;
     }
     t->checkSuspendOnEffectEnabled(enabled, effect->sessionId(), threadLocked);
 
-    sp<EffectChain> c = chain().promote();
+    sp<IAfEffectChain> c = chain().promote();
     if (c == nullptr) {
         return;
     }
@@ -3186,8 +3203,8 @@
     c->checkSuspendOnEffectEnabled(effect->asEffectModule(), enabled);
 }
 
-void AudioFlinger::EffectChain::EffectCallback::onEffectEnable(const sp<EffectBase>& effect) {
-    sp<ThreadBase> t = thread().promote();
+void EffectChain::EffectCallback::onEffectEnable(const sp<IAfEffectBase>& effect) {
+    const sp<IAfThreadBase> t = thread().promote();
     if (t == nullptr) {
         return;
     }
@@ -3195,19 +3212,19 @@
     t->onEffectEnable(effect->asEffectModule());
 }
 
-void AudioFlinger::EffectChain::EffectCallback::onEffectDisable(const sp<EffectBase>& effect) {
+void EffectChain::EffectCallback::onEffectDisable(const sp<IAfEffectBase>& effect) {
     checkSuspendOnEffectEnabled(effect, false, false /*threadLocked*/);
 
-    sp<ThreadBase> t = thread().promote();
+    const sp<IAfThreadBase> t = thread().promote();
     if (t == nullptr) {
         return;
     }
     t->onEffectDisable();
 }
 
-bool AudioFlinger::EffectChain::EffectCallback::disconnectEffectHandle(EffectHandle *handle,
+bool EffectChain::EffectCallback::disconnectEffectHandle(IAfEffectHandle *handle,
                                                       bool unpinIfLast) {
-    sp<ThreadBase> t = thread().promote();
+    const sp<IAfThreadBase> t = thread().promote();
     if (t == nullptr) {
         return false;
     }
@@ -3215,8 +3232,8 @@
     return true;
 }
 
-void AudioFlinger::EffectChain::EffectCallback::resetVolume() {
-    sp<EffectChain> c = chain().promote();
+void EffectChain::EffectCallback::resetVolume() {
+    sp<IAfEffectChain> c = chain().promote();
     if (c == nullptr) {
         return;
     }
@@ -3224,16 +3241,16 @@
 
 }
 
-product_strategy_t AudioFlinger::EffectChain::EffectCallback::strategy() const {
-    sp<EffectChain> c = chain().promote();
+product_strategy_t EffectChain::EffectCallback::strategy() const {
+    sp<IAfEffectChain> c = chain().promote();
     if (c == nullptr) {
         return PRODUCT_STRATEGY_NONE;
     }
     return c->strategy();
 }
 
-int32_t AudioFlinger::EffectChain::EffectCallback::activeTrackCnt() const {
-    sp<EffectChain> c = chain().promote();
+int32_t EffectChain::EffectCallback::activeTrackCnt() const {
+    sp<IAfEffectChain> c = chain().promote();
     if (c == nullptr) {
         return 0;
     }
@@ -3242,19 +3259,30 @@
 
 
 #undef LOG_TAG
-#define LOG_TAG "AudioFlinger::DeviceEffectProxy"
+#define LOG_TAG "DeviceEffectProxy"
 
-status_t AudioFlinger::DeviceEffectProxy::setEnabled(bool enabled, bool fromHandle)
+/* static */
+sp<IAfDeviceEffectProxy> IAfDeviceEffectProxy::create(
+        const AudioDeviceTypeAddr& device,
+        const sp<DeviceEffectManagerCallback>& callback,
+        effect_descriptor_t *desc, int id, bool notifyFramesProcessed)
+{
+    return sp<DeviceEffectProxy>::make(device,
+            callback,
+            desc, id, notifyFramesProcessed);
+}
+
+status_t DeviceEffectProxy::setEnabled(bool enabled, bool fromHandle)
 {
     status_t status = EffectBase::setEnabled(enabled, fromHandle);
-    Mutex::Autolock _l(mProxyLock);
+    audio_utils::lock_guard _l(proxyMutex());
     if (status == NO_ERROR) {
         for (auto& handle : mEffectHandles) {
             Status bs;
             if (enabled) {
-                bs = handle.second->enable(&status);
+                bs = handle.second->asIEffect()->enable(&status);
             } else {
-                bs = handle.second->disable(&status);
+                bs = handle.second->asIEffect()->disable(&status);
             }
             if (!bs.isOk()) {
               status = statusTFromBinderStatus(bs);
@@ -3265,8 +3293,8 @@
     return status;
 }
 
-status_t AudioFlinger::DeviceEffectProxy::init(
-        const std::map <audio_patch_handle_t, PatchPanel::Patch>& patches) {
+status_t DeviceEffectProxy::init(
+        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
@@ -3288,10 +3316,10 @@
     return status;
 }
 
-status_t AudioFlinger::DeviceEffectProxy::onCreatePatch(
-        audio_patch_handle_t patchHandle, const AudioFlinger::PatchPanel::Patch& patch) {
+status_t DeviceEffectProxy::onCreatePatch(
+        audio_patch_handle_t patchHandle, const IAfPatchPanel::Patch& patch) {
     status_t status = NAME_NOT_FOUND;
-    sp<EffectHandle> handle;
+    sp<IAfEffectHandle> handle;
     // only consider source[0] as this is the only "true" source of a patch
     status = checkPort(patch, &patch.mAudioPatch.sources[0], &handle);
     ALOGV("%s source checkPort status %d", __func__, status);
@@ -3300,7 +3328,7 @@
         ALOGV("%s sink %d checkPort status %d", __func__, i, status);
     }
     if (status == NO_ERROR || status == ALREADY_EXISTS) {
-        Mutex::Autolock _l(mProxyLock);
+        audio_utils::lock_guard _l(proxyMutex());
         mEffectHandles.emplace(patchHandle, handle);
     }
     ALOGW_IF(status == BAD_VALUE,
@@ -3309,8 +3337,11 @@
     return status;
 }
 
-status_t AudioFlinger::DeviceEffectProxy::checkPort(const PatchPanel::Patch& patch,
-        const struct audio_port_config *port, sp <EffectHandle> *handle) {
+status_t DeviceEffectProxy::checkPort(const IAfPatchPanel::Patch& patch,
+        const struct audio_port_config *port, sp<IAfEffectHandle> *handle)
+NO_THREAD_SAFETY_ANALYSIS
+// calling function 'createEffect_l' requires holding mutex 'AudioFlinger_Mutex' exclusively
+{
 
     ALOGV("%s type %d device type %d address %s device ID %d patch.isSoftware() %d",
             __func__, port->type, port->ext.device.type,
@@ -3332,7 +3363,7 @@
     status_t status = NAME_NOT_FOUND;
 
     if (mDescriptor.flags & EFFECT_FLAG_HW_ACC_TUNNEL) {
-        Mutex::Autolock _l(mProxyLock);
+        audio_utils::lock_guard _l(proxyMutex());
         mDevicePort = *port;
         mHalEffect = new EffectModule(mMyCallback,
                                       const_cast<effect_descriptor_t *>(&mDescriptor),
@@ -3355,7 +3386,7 @@
             mDevicePort.id = AUDIO_PORT_HANDLE_NONE;
         }
     } else if (patch.isSoftware() || patch.thread().promote() != nullptr) {
-        sp <ThreadBase> thread;
+        sp<IAfThreadBase> thread;
         if (audio_port_config_has_input_direction(port)) {
             if (patch.isSoftware()) {
                 thread = patch.mRecord.thread();
@@ -3382,9 +3413,9 @@
     if (status == NO_ERROR || status == ALREADY_EXISTS) {
         Status bs;
         if (isEnabled()) {
-            bs = (*handle)->enable(&status);
+            bs = (*handle)->asIEffect()->enable(&status);
         } else {
-            bs = (*handle)->disable(&status);
+            bs = (*handle)->asIEffect()->disable(&status);
         }
         if (!bs.isOk()) {
             status = statusTFromBinderStatus(bs);
@@ -3393,10 +3424,10 @@
     return status;
 }
 
-void AudioFlinger::DeviceEffectProxy::onReleasePatch(audio_patch_handle_t patchHandle) {
-    sp<EffectHandle> effect;
+void DeviceEffectProxy::onReleasePatch(audio_patch_handle_t patchHandle) {
+    sp<IAfEffectHandle> effect;
     {
-        Mutex::Autolock _l(mProxyLock);
+        audio_utils::lock_guard _l(proxyMutex());
         if (mEffectHandles.find(patchHandle) != mEffectHandles.end()) {
             effect = mEffectHandles.at(patchHandle);
             mEffectHandles.erase(patchHandle);
@@ -3405,9 +3436,9 @@
 }
 
 
-size_t AudioFlinger::DeviceEffectProxy::removeEffect(const sp<EffectModule>& effect)
+size_t DeviceEffectProxy::removeEffect(const sp<IAfEffectModule>& effect)
 {
-    Mutex::Autolock _l(mProxyLock);
+    audio_utils::lock_guard _l(proxyMutex());
     if (effect == mHalEffect) {
         mHalEffect->release_l();
         mHalEffect.clear();
@@ -3416,7 +3447,7 @@
     return mHalEffect == nullptr ? 0 : 1;
 }
 
-status_t AudioFlinger::DeviceEffectProxy::addEffectToHal(
+status_t DeviceEffectProxy::addEffectToHal(
         const sp<EffectHalInterface>& effect) {
     if (mHalEffect == nullptr) {
         return NO_INIT;
@@ -3424,7 +3455,7 @@
     return mManagerCallback->addEffectToHal(&mDevicePort, effect);
 }
 
-status_t AudioFlinger::DeviceEffectProxy::removeEffectFromHal(
+status_t DeviceEffectProxy::removeEffectFromHal(
         const sp<EffectHalInterface>& effect) {
     if (mHalEffect == nullptr) {
         return NO_INIT;
@@ -3432,14 +3463,14 @@
     return mManagerCallback->removeEffectFromHal(&mDevicePort, effect);
 }
 
-bool AudioFlinger::DeviceEffectProxy::isOutput() const {
+bool DeviceEffectProxy::isOutput() const {
     if (mDevicePort.id != AUDIO_PORT_HANDLE_NONE) {
         return mDevicePort.role == AUDIO_PORT_ROLE_SINK;
     }
     return true;
 }
 
-uint32_t AudioFlinger::DeviceEffectProxy::sampleRate() const {
+uint32_t DeviceEffectProxy::sampleRate() const {
     if (mDevicePort.id != AUDIO_PORT_HANDLE_NONE &&
             (mDevicePort.config_mask & AUDIO_PORT_CONFIG_SAMPLE_RATE) != 0) {
         return mDevicePort.sample_rate;
@@ -3447,7 +3478,7 @@
     return DEFAULT_OUTPUT_SAMPLE_RATE;
 }
 
-audio_channel_mask_t AudioFlinger::DeviceEffectProxy::channelMask() const {
+audio_channel_mask_t DeviceEffectProxy::channelMask() const {
     if (mDevicePort.id != AUDIO_PORT_HANDLE_NONE &&
             (mDevicePort.config_mask & AUDIO_PORT_CONFIG_CHANNEL_MASK) != 0) {
         return mDevicePort.channel_mask;
@@ -3455,20 +3486,20 @@
     return AUDIO_CHANNEL_OUT_STEREO;
 }
 
-uint32_t AudioFlinger::DeviceEffectProxy::channelCount() const {
+uint32_t DeviceEffectProxy::channelCount() const {
     if (isOutput()) {
         return audio_channel_count_from_out_mask(channelMask());
     }
     return audio_channel_count_from_in_mask(channelMask());
 }
 
-void AudioFlinger::DeviceEffectProxy::dump(int fd, int spaces)
+void DeviceEffectProxy::dump2(int fd, int spaces) const
 NO_THREAD_SAFETY_ANALYSIS  // conditional try lock
 {
     const Vector<String16> args;
     EffectBase::dump(fd, args);
 
-    const bool locked = dumpTryLock(mProxyLock);
+    const bool locked = afutils::dumpTryLock(proxyMutex());
     if (!locked) {
         String8 result("DeviceEffectProxy may be deadlocked\n");
         write(fd, result.c_str(), result.size());
@@ -3491,33 +3522,33 @@
         outStr.appendFormat("%*sEffect for patch handle %d:\n", spaces + 2, "", iter.first);
         write(fd, outStr.c_str(), outStr.size());
         outStr.clear();
-        sp<EffectBase> effect = iter.second->effect().promote();
+        sp<IAfEffectBase> effect = iter.second->effect().promote();
         if (effect != nullptr) {
             effect->dump(fd, args);
         }
     }
 
     if (locked) {
-        mLock.unlock();
+        proxyMutex().unlock();
     }
 }
 
 #undef LOG_TAG
-#define LOG_TAG "AudioFlinger::DeviceEffectProxy::ProxyCallback"
+#define LOG_TAG "DeviceEffectProxy::ProxyCallback"
 
-int AudioFlinger::DeviceEffectProxy::ProxyCallback::newEffectId() {
+int DeviceEffectProxy::ProxyCallback::newEffectId() {
     return mManagerCallback->newEffectId();
 }
 
 
-bool AudioFlinger::DeviceEffectProxy::ProxyCallback::disconnectEffectHandle(
-        EffectHandle *handle, bool unpinIfLast) {
-    sp<EffectBase> effectBase = handle->effect().promote();
+bool DeviceEffectProxy::ProxyCallback::disconnectEffectHandle(
+        IAfEffectHandle *handle, bool unpinIfLast) {
+    sp<IAfEffectBase> effectBase = handle->effect().promote();
     if (effectBase == nullptr) {
         return false;
     }
 
-    sp<EffectModule> effect = effectBase->asEffectModule();
+    sp<IAfEffectModule> effect = effectBase->asEffectModule();
     if (effect == nullptr) {
         return false;
     }
@@ -3536,13 +3567,13 @@
     return true;
 }
 
-status_t AudioFlinger::DeviceEffectProxy::ProxyCallback::createEffectHal(
+status_t DeviceEffectProxy::ProxyCallback::createEffectHal(
         const effect_uuid_t *pEffectUuid, int32_t sessionId, int32_t deviceId,
         sp<EffectHalInterface> *effect) {
     return mManagerCallback->createEffectHal(pEffectUuid, sessionId, deviceId, effect);
 }
 
-status_t AudioFlinger::DeviceEffectProxy::ProxyCallback::addEffectToHal(
+status_t DeviceEffectProxy::ProxyCallback::addEffectToHal(
         const sp<EffectHalInterface>& effect) {
     sp<DeviceEffectProxy> proxy = mProxy.promote();
     if (proxy == nullptr) {
@@ -3551,7 +3582,7 @@
     return proxy->addEffectToHal(effect);
 }
 
-status_t AudioFlinger::DeviceEffectProxy::ProxyCallback::removeEffectFromHal(
+status_t DeviceEffectProxy::ProxyCallback::removeEffectFromHal(
         const sp<EffectHalInterface>& effect) {
     sp<DeviceEffectProxy> proxy = mProxy.promote();
     if (proxy == nullptr) {
@@ -3560,7 +3591,7 @@
     return proxy->removeEffectFromHal(effect);
 }
 
-bool AudioFlinger::DeviceEffectProxy::ProxyCallback::isOutput() const {
+bool DeviceEffectProxy::ProxyCallback::isOutput() const {
     sp<DeviceEffectProxy> proxy = mProxy.promote();
     if (proxy == nullptr) {
         return true;
@@ -3568,7 +3599,7 @@
     return proxy->isOutput();
 }
 
-uint32_t AudioFlinger::DeviceEffectProxy::ProxyCallback::sampleRate() const {
+uint32_t DeviceEffectProxy::ProxyCallback::sampleRate() const {
     sp<DeviceEffectProxy> proxy = mProxy.promote();
     if (proxy == nullptr) {
         return DEFAULT_OUTPUT_SAMPLE_RATE;
@@ -3576,7 +3607,7 @@
     return proxy->sampleRate();
 }
 
-audio_channel_mask_t AudioFlinger::DeviceEffectProxy::ProxyCallback::inChannelMask(
+audio_channel_mask_t DeviceEffectProxy::ProxyCallback::inChannelMask(
         int id __unused) const {
     sp<DeviceEffectProxy> proxy = mProxy.promote();
     if (proxy == nullptr) {
@@ -3585,7 +3616,7 @@
     return proxy->channelMask();
 }
 
-uint32_t AudioFlinger::DeviceEffectProxy::ProxyCallback::inChannelCount(int id __unused) const {
+uint32_t DeviceEffectProxy::ProxyCallback::inChannelCount(int id __unused) const {
     sp<DeviceEffectProxy> proxy = mProxy.promote();
     if (proxy == nullptr) {
         return 2;
@@ -3593,7 +3624,7 @@
     return proxy->channelCount();
 }
 
-audio_channel_mask_t AudioFlinger::DeviceEffectProxy::ProxyCallback::outChannelMask() const {
+audio_channel_mask_t DeviceEffectProxy::ProxyCallback::outChannelMask() const {
     sp<DeviceEffectProxy> proxy = mProxy.promote();
     if (proxy == nullptr) {
         return AUDIO_CHANNEL_OUT_STEREO;
@@ -3601,7 +3632,7 @@
     return proxy->channelMask();
 }
 
-uint32_t AudioFlinger::DeviceEffectProxy::ProxyCallback::outChannelCount() const {
+uint32_t DeviceEffectProxy::ProxyCallback::outChannelCount() const {
     sp<DeviceEffectProxy> proxy = mProxy.promote();
     if (proxy == nullptr) {
         return 2;
@@ -3609,18 +3640,18 @@
     return proxy->channelCount();
 }
 
-void AudioFlinger::DeviceEffectProxy::ProxyCallback::onEffectEnable(
-        const sp<EffectBase>& effectBase) {
-    sp<EffectModule> effect = effectBase->asEffectModule();
+void DeviceEffectProxy::ProxyCallback::onEffectEnable(
+        const sp<IAfEffectBase>& effectBase) {
+    sp<IAfEffectModule> effect = effectBase->asEffectModule();
     if (effect == nullptr) {
         return;
     }
     effect->start();
 }
 
-void AudioFlinger::DeviceEffectProxy::ProxyCallback::onEffectDisable(
-        const sp<EffectBase>& effectBase) {
-    sp<EffectModule> effect = effectBase->asEffectModule();
+void DeviceEffectProxy::ProxyCallback::onEffectDisable(
+        const sp<IAfEffectBase>& effectBase) {
+    sp<IAfEffectModule> effect = effectBase->asEffectModule();
     if (effect == nullptr) {
         return;
     }
diff --git a/services/audioflinger/Effects.h b/services/audioflinger/Effects.h
index 7ceb6c6..6b1d9cf 100644
--- a/services/audioflinger/Effects.h
+++ b/services/audioflinger/Effects.h
@@ -15,62 +15,21 @@
 ** limitations under the License.
 */
 
-#ifndef INCLUDING_FROM_AUDIOFLINGER_H
-    #error This header file should only be included from AudioFlinger.h
-#endif
+#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
 
-// Interface implemented by the EffectModule parent or owner (e.g an EffectChain) to abstract
-// interactions between the EffectModule and the reset of the audio framework.
-class EffectCallbackInterface : public RefBase {
-public:
-            ~EffectCallbackInterface() override = default;
-
-    // Trivial methods usually implemented with help from ThreadBase
-    virtual audio_io_handle_t io() const = 0;
-    virtual bool isOutput() const = 0;
-    virtual bool isOffload() const = 0;
-    virtual bool isOffloadOrDirect() const = 0;
-    virtual bool isOffloadOrMmap() const = 0;
-    virtual bool isSpatializer() const = 0;
-    virtual uint32_t sampleRate() const = 0;
-    virtual audio_channel_mask_t inChannelMask(int id) const = 0;
-    virtual uint32_t inChannelCount(int id) const = 0;
-    virtual audio_channel_mask_t outChannelMask() const = 0;
-    virtual uint32_t outChannelCount() const = 0;
-    virtual audio_channel_mask_t hapticChannelMask() const = 0;
-    virtual size_t frameCount() const = 0;
-
-    // Non trivial methods usually implemented with help from ThreadBase:
-    //   pay attention to mutex locking order
-    virtual uint32_t latency() const { return 0; }
-    virtual status_t addEffectToHal(const sp<EffectHalInterface>& effect) = 0;
-    virtual status_t removeEffectFromHal(const sp<EffectHalInterface>& effect) = 0;
-    virtual void setVolumeForOutput(float left, float right) const = 0;
-    virtual bool disconnectEffectHandle(EffectHandle *handle, bool unpinIfLast) = 0;
-    virtual void checkSuspendOnEffectEnabled(const sp<EffectBase>& effect,
-                                             bool enabled,
-                                             bool threadLocked) = 0;
-    virtual void onEffectEnable(const sp<EffectBase>& effect) = 0;
-    virtual void onEffectDisable(const sp<EffectBase>& effect) = 0;
-
-    // Methods usually implemented with help from AudioFlinger: pay attention to mutex locking order
-    virtual status_t createEffectHal(const effect_uuid_t *pEffectUuid,
-                    int32_t sessionId, int32_t deviceId, sp<EffectHalInterface> *effect) = 0;
-    virtual status_t allocateHalBuffer(size_t size, sp<EffectBufferHalInterface>* buffer) = 0;
-    virtual bool updateOrphanEffectChains(const sp<EffectBase>& effect) = 0;
-
-    // Methods usually implemented with help from EffectChain: pay attention to mutex locking order
-    virtual product_strategy_t strategy() const = 0;
-    virtual int32_t activeTrackCnt() const = 0;
-    virtual void resetVolume() = 0;
-
-    virtual wp<EffectChain> chain() const = 0;
-
-    virtual bool isAudioPolicyReady() const = 0;
-};
-
 // EffectBase(EffectModule) and EffectChain classes both have their own mutex to protect
 // state changes or resource modifications. Always respect the following order
 // if multiple mutexes must be acquired to avoid cross deadlock:
@@ -90,7 +49,7 @@
 // The EffectBase class contains common properties, state and behavior for and EffectModule or
 // other derived classes managing an audio effect instance within the effect framework.
 // It also contains the class mutex (see comment on locking order above).
-class EffectBase : public RefBase {
+class EffectBase : public virtual IAfEffectBase {
 public:
     EffectBase(const sp<EffectCallbackInterface>& callback,
                effect_descriptor_t *desc,
@@ -98,76 +57,68 @@
                audio_session_t sessionId,
                bool pinned);
 
-    ~EffectBase() override = default;
-
-    enum effect_state {
-        IDLE,
-        RESTART,
-        STARTING,
-        ACTIVE,
-        STOPPING,
-        STOPPED,
-        DESTROYED
-    };
-
-    int id() const { return mId; }
-    effect_state state() const {
+    int id() const final { return mId; }
+    effect_state state() const final {
         return mState;
     }
-    audio_session_t sessionId() const {
+    audio_session_t sessionId() const final {
         return mSessionId;
     }
-    const effect_descriptor_t& desc() const { return mDescriptor; }
-    bool             isOffloadable() const
+    const effect_descriptor_t& desc() const final { return mDescriptor; }
+    bool isOffloadable() const final
                         { return (mDescriptor.flags & EFFECT_FLAG_OFFLOAD_SUPPORTED) != 0; }
-    bool             isImplementationSoftware() const
+    bool isImplementationSoftware() const final
                         { return (mDescriptor.flags & EFFECT_FLAG_HW_ACC_MASK) == 0; }
-    bool             isProcessImplemented() const
+    bool isProcessImplemented() const final
                         { return (mDescriptor.flags & EFFECT_FLAG_NO_PROCESS) == 0; }
-    bool             isVolumeControl() const
+    bool isVolumeControl() const
                         { return (mDescriptor.flags & EFFECT_FLAG_VOLUME_MASK)
                             == EFFECT_FLAG_VOLUME_CTRL; }
-    bool             isVolumeMonitor() const
+    bool isVolumeMonitor() const final
                         { return (mDescriptor.flags & EFFECT_FLAG_VOLUME_MASK)
                             == EFFECT_FLAG_VOLUME_MONITOR; }
 
-    virtual status_t setEnabled(bool enabled, bool fromHandle);
-    status_t    setEnabled_l(bool enabled);
-    bool isEnabled() const;
+    status_t setEnabled(bool enabled, bool fromHandle) override;
+    status_t setEnabled_l(bool enabled) final;
+    bool isEnabled() const final;
+    void setSuspended(bool suspended) final;
+    bool suspended() const final;
 
-    void             setSuspended(bool suspended);
-    bool             suspended() const;
-
-    virtual status_t command(int32_t __unused,
+    status_t command(int32_t __unused,
                              const std::vector<uint8_t>& __unused,
                              int32_t __unused,
-                             std::vector<uint8_t>* __unused) { return NO_ERROR; };
+                             std::vector<uint8_t>* __unused) override {
+        return NO_ERROR;
+    }
 
     // mCallback is atomic so this can be lock-free.
-    void setCallback(const sp<EffectCallbackInterface>& callback) { mCallback = callback; }
-    sp<EffectCallbackInterface> getCallback() const { return mCallback.load(); }
+    void setCallback(const sp<EffectCallbackInterface>& callback) final {
+        mCallback = callback;
+    }
+    sp<EffectCallbackInterface> getCallback() const final {
+        return mCallback.load();
+    }
 
-    status_t addHandle(EffectHandle *handle);
-    ssize_t disconnectHandle(EffectHandle *handle, bool unpinIfLast);
-    ssize_t removeHandle(EffectHandle *handle);
-    ssize_t removeHandle_l(EffectHandle *handle);
-    EffectHandle* controlHandle_l();
-    bool purgeHandles();
+    status_t addHandle(IAfEffectHandle *handle) final;
+    ssize_t disconnectHandle(IAfEffectHandle *handle, bool unpinIfLast) final;
+    ssize_t removeHandle(IAfEffectHandle *handle) final;
+    ssize_t removeHandle_l(IAfEffectHandle *handle) final;
+    IAfEffectHandle* controlHandle_l() final;
+    bool purgeHandles() final;
 
-    void             checkSuspendOnEffectEnabled(bool enabled, bool threadLocked);
+    void             checkSuspendOnEffectEnabled(bool enabled, bool threadLocked) final;
 
-    bool             isPinned() const { return mPinned; }
-    void             unPin() { mPinned = false; }
+    bool             isPinned() const final { return mPinned; }
+    void             unPin() final { mPinned = false; }
 
-    void             lock() ACQUIRE(mLock) { mLock.lock(); }
-    void             unlock() RELEASE(mLock) { mLock.unlock(); }
+    audio_utils::mutex& mutex() const final { return mMutex; }
 
-    status_t         updatePolicyState();
+    status_t         updatePolicyState() final;
 
-    virtual          sp<EffectModule> asEffectModule() { return nullptr; }
-    virtual          sp<DeviceEffectProxy> asDeviceEffectProxy() { return nullptr; }
+    sp<IAfEffectModule> asEffectModule() override { return nullptr; }
+    sp<IAfDeviceEffectProxy> asDeviceEffectProxy() override { return nullptr; }
 
-    void             dump(int fd, const Vector<String16>& args);
+    void             dump(int fd, const Vector<String16>& args) const override;
 
 protected:
     bool             isInternal_l() const {
@@ -179,13 +130,12 @@
                          return true;
                      }
 
-private:
-    friend class AudioFlinger;      // for mHandles
     bool             mPinned = false;
 
     DISALLOW_COPY_AND_ASSIGN(EffectBase);
 
-mutable Mutex                 mLock;      // mutex for process, commands and handles list protection
+    // mutex for process, commands and handles list protection
+    mutable audio_utils::mutex mMutex;
     mediautils::atomic_sp<EffectCallbackInterface> mCallback; // parent effect chain
     const int                 mId;        // this instance unique ID
     const audio_session_t     mSessionId; // audio session ID
@@ -194,13 +144,14 @@
     // effect is suspended: temporarily disabled by framework
     bool                      mSuspended = false;
 
-    Vector<EffectHandle *>    mHandles;   // list of client handles
+    Vector<IAfEffectHandle *> mHandles;  // list of client handles
                 // First handle in mHandles has highest priority and controls the effect module
 
     // Audio policy effect state management
-    // Mutex protecting transactions with audio policy manager as mLock cannot
+    // Mutex protecting transactions with audio policy manager as mutex() cannot
     // be held to avoid cross deadlocks with audio policy mutex
-    Mutex                     mPolicyLock;
+    audio_utils::mutex& policyMutex() const { return mPolicyMutex; }
+    mutable audio_utils::mutex mPolicyMutex;
     // Effect is registered in APM or not
     bool                      mPolicyRegistered = false;
     // Effect enabled state communicated to APM. Enabled state corresponds to
@@ -217,7 +168,7 @@
 // ramping when effects are activated/deactivated.
 // When controlling an auxiliary effect, the EffectModule also provides an input buffer used by
 // the attached track(s) to accumulate their auxiliary channel.
-class EffectModule : public EffectBase {
+class EffectModule : public IAfEffectModule, public EffectBase {
 public:
     EffectModule(const sp<EffectCallbackInterface>& callabck,
                     effect_descriptor_t *desc,
@@ -225,72 +176,65 @@
                     audio_session_t sessionId,
                     bool pinned,
                     audio_port_handle_t deviceId);
-    virtual ~EffectModule();
+    ~EffectModule() override;
 
-    void process();
-    bool updateState();
+    void process() final;
+    bool updateState() final;
     status_t command(int32_t cmdCode,
                      const std::vector<uint8_t>& cmdData,
                      int32_t maxReplySize,
-                     std::vector<uint8_t>* reply) override;
+                     std::vector<uint8_t>* reply) final;
 
-    void reset_l();
-    status_t configure();
-    status_t init();
-
-    uint32_t status() {
+    void reset_l() final;
+    status_t configure() final;
+    status_t init() final;
+    uint32_t status() const final {
         return mStatus;
     }
-
-    bool isProcessEnabled() const;
-    bool isOffloadedOrDirect() const;
-    bool isVolumeControlEnabled() const;
-
-    void        setInBuffer(const sp<EffectBufferHalInterface>& buffer);
-    int16_t     *inBuffer() const {
+    bool isProcessEnabled() const final;
+    bool isOffloadedOrDirect() const final;
+    bool isVolumeControlEnabled() const final;
+    void setInBuffer(const sp<EffectBufferHalInterface>& buffer) final;
+    int16_t *inBuffer() const final {
         return mInBuffer != 0 ? reinterpret_cast<int16_t*>(mInBuffer->ptr()) : NULL;
     }
-    void        setOutBuffer(const sp<EffectBufferHalInterface>& buffer);
-    int16_t     *outBuffer() const {
+    void setOutBuffer(const sp<EffectBufferHalInterface>& buffer) final;
+    int16_t *outBuffer() const final {
         return mOutBuffer != 0 ? reinterpret_cast<int16_t*>(mOutBuffer->ptr()) : NULL;
     }
-
     // Updates the access mode if it is out of date.  May issue a new effect configure.
-    void        updateAccessMode() {
+    void updateAccessMode() final {
                     if (requiredEffectBufferAccessMode() != mConfig.outputCfg.accessMode) {
                         configure();
                     }
                 }
+    status_t setDevices(const AudioDeviceTypeAddrVector &devices) final;
+    status_t setInputDevice(const AudioDeviceTypeAddr &device) final;
+    status_t setVolume(uint32_t *left, uint32_t *right, bool controller) final;
+    status_t setMode(audio_mode_t mode) final;
+    status_t setAudioSource(audio_source_t source) final;
+    status_t start() final;
+    status_t stop() final;
 
-    status_t         setDevices(const AudioDeviceTypeAddrVector &devices);
-    status_t         setInputDevice(const AudioDeviceTypeAddr &device);
-    status_t         setVolume(uint32_t *left, uint32_t *right, bool controller);
-    status_t         setMode(audio_mode_t mode);
-    status_t         setAudioSource(audio_source_t source);
-    status_t         start();
-    status_t         stop();
+    status_t setOffloaded(bool offloaded, audio_io_handle_t io) final;
+    bool isOffloaded() const final;
+    void addEffectToHal_l() final;
+    void release_l() final;
 
-    status_t         setOffloaded(bool offloaded, audio_io_handle_t io);
-    bool             isOffloaded() const;
-    void             addEffectToHal_l();
-    void             release_l();
+    sp<IAfEffectModule> asEffectModule() final { return this; }
 
-    sp<EffectModule> asEffectModule() override { return this; }
+    bool isHapticGenerator() const final;
 
-    static bool      isHapticGenerator(const effect_uuid_t* type);
-    bool             isHapticGenerator() const;
+    status_t setHapticIntensity(int id, os::HapticScale intensity) final;
+    status_t setVibratorInfo(const media::AudioVibratorInfo& vibratorInfo) final;
 
-    status_t         setHapticIntensity(int id, os::HapticScale intensity);
-    status_t         setVibratorInfo(const media::AudioVibratorInfo& vibratorInfo);
-
-    status_t         getConfigs(audio_config_base_t* inputCfg,
+    status_t getConfigs(audio_config_base_t* inputCfg,
                                 audio_config_base_t* outputCfg,
-                                bool* isOutput) const;
+                                bool* isOutput) const final;
 
-    void             dump(int fd, const Vector<String16>& args);
+    void dump(int fd, const Vector<String16>& args) const final;
 
 private:
-    friend class AudioFlinger;      // for mHandles
 
     // Maximum time allocated to effect engines to complete the turn off sequence
     static const uint32_t MAX_DISABLE_TIME_MS = 10000;
@@ -329,9 +273,10 @@
     uint32_t mInChannelCountRequested;
     uint32_t mOutChannelCountRequested;
 
+    template <typename MUTEX>
     class AutoLockReentrant {
     public:
-        AutoLockReentrant(Mutex& mutex, pid_t allowedTid)
+        AutoLockReentrant(MUTEX& mutex, pid_t allowedTid)
             : mMutex(gettid() == allowedTid ? nullptr : &mutex)
         {
             if (mMutex != nullptr) mMutex->lock();
@@ -340,7 +285,7 @@
             if (mMutex != nullptr) mMutex->unlock();
         }
     private:
-        Mutex * const mMutex;
+        MUTEX * const mMutex;
     };
 
     static constexpr pid_t INVALID_PID = (pid_t)-1;
@@ -354,32 +299,36 @@
 // There is one EffectHandle object for each application controlling (or using)
 // an effect module.
 // The EffectHandle is obtained by calling AudioFlinger::createEffect().
-class EffectHandle: public android::media::BnEffect {
+class EffectHandle: public IAfEffectHandle, public android::media::BnEffect {
 public:
 
-    EffectHandle(const sp<EffectBase>& effect,
-            const sp<AudioFlinger::Client>& client,
+    EffectHandle(const sp<IAfEffectBase>& effect,
+            const sp<Client>& client,
             const sp<media::IEffectClient>& effectClient,
             int32_t priority, bool notifyFramesProcessed);
-    virtual ~EffectHandle();
+    ~EffectHandle() override;
     status_t onTransact(
-            uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) override;
-    virtual status_t initCheck();
+            uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) final;
+    status_t initCheck() const final;
 
     // IEffect
-    android::binder::Status enable(int32_t* _aidl_return) override;
-    android::binder::Status disable(int32_t* _aidl_return) override;
+    android::binder::Status enable(int32_t* _aidl_return) final;
+    android::binder::Status disable(int32_t* _aidl_return) final;
     android::binder::Status command(int32_t cmdCode,
                                     const std::vector<uint8_t>& cmdData,
                                     int32_t maxResponseSize,
                                     std::vector<uint8_t>* response,
-                                    int32_t* _aidl_return) override;
-    android::binder::Status disconnect() override;
-    android::binder::Status getCblk(media::SharedFileRegion* _aidl_return) override;
+                                    int32_t* _aidl_return) final;
+    android::binder::Status disconnect() final;
+    android::binder::Status getCblk(media::SharedFileRegion* _aidl_return) final;
     android::binder::Status getConfig(media::EffectConfig* _config,
-                                      int32_t* _aidl_return) override;
+                                      int32_t* _aidl_return) final;
 
-    sp<Client> client() const { return mClient; }
+    const sp<Client>& client() const final { return mClient; }
+
+    sp<android::media::IEffect> asIEffect() final {
+        return sp<android::media::IEffect>::fromExisting(this);
+    }
 
 private:
     void disconnect(bool unpinIfLast);
@@ -388,36 +337,38 @@
     // - hasControl: true if control is given, false if removed
     // - signal: true client app should be signaled of change, false otherwise
     // - enabled: state of the effect when control is passed
-    void setControl(bool hasControl, bool signal, bool enabled);
+    void setControl(bool hasControl, bool signal, bool enabled) final;
     void commandExecuted(uint32_t cmdCode,
                          const std::vector<uint8_t>& cmdData,
-                         const std::vector<uint8_t>& replyData);
-    void setEnabled(bool enabled);
-    bool enabled() const { return mEnabled; }
+                         const std::vector<uint8_t>& replyData) final;
+    bool enabled() const final { return mEnabled; }
+    void setEnabled(bool enabled) final;
+    void framesProcessed(int32_t frames) const final;
 
-    void framesProcessed(int32_t frames) const;
-
+public:
     // Getters
-    wp<EffectBase> effect() const { return mEffect; }
-    int id() const {
-        sp<EffectBase> effect = mEffect.promote();
+    wp<IAfEffectBase> effect() const final { return mEffect; }
+    int id() const final {
+        sp<IAfEffectBase> effect = mEffect.promote();
         if (effect == 0) {
             return 0;
         }
         return effect->id();
     }
-    int priority() const { return mPriority; }
-    bool hasControl() const { return mHasControl; }
-    bool disconnected() const { return mDisconnected; }
+private:
+    int priority() const final { return mPriority; }
+    bool hasControl() const final { return mHasControl; }
+    bool disconnected() const final { return mDisconnected; }
 
-    void dumpToBuffer(char* buffer, size_t size);
+    void dumpToBuffer(char* buffer, size_t size) const final;
+
 
 private:
-    friend class AudioFlinger;          // for mEffect, mHasControl, mEnabled
     DISALLOW_COPY_AND_ASSIGN(EffectHandle);
 
-    Mutex mLock;                             // protects IEffect method calls
-    const wp<EffectBase> mEffect;            // pointer to controlled EffectModule
+    audio_utils::mutex& mutex() const { return mMutex; }
+    mutable audio_utils::mutex mMutex; // protects IEffect method calls
+    const wp<IAfEffectBase> mEffect;               // pointer to controlled EffectModule
     const sp<media::IEffectClient> mEffectClient;  // callback interface for client notifications
     /*const*/ sp<Client> mClient;            // client for shared memory allocation, see
                                              //   disconnect()
@@ -443,123 +394,123 @@
 // order corresponding in the effect process order. When attached to a track (session ID !=
 // AUDIO_SESSION_OUTPUT_MIX),
 // it also provide it's own input buffer used by the track as accumulation buffer.
-class EffectChain : public RefBase {
+class EffectChain : public IAfEffectChain {
 public:
-    EffectChain(const wp<ThreadBase>& wThread, audio_session_t sessionId);
-    virtual ~EffectChain();
+    EffectChain(const sp<IAfThreadBase>& thread, audio_session_t sessionId);
 
-    // special key used for an entry in mSuspendedEffects keyed vector
-    // corresponding to a suspend all request.
-    static const int        kKeyForSuspendAll = 0;
+    void process_l() final;
 
-    // minimum duration during which we force calling effect process when last track on
-    // a session is stopped or removed to allow effect tail to be rendered
-    static const int        kProcessTailDurationMs = 1000;
+    audio_utils::mutex& mutex() const final { return mMutex; }
 
-    void process_l();
-
-    void lock() ACQUIRE(mLock) {
-        mLock.lock();
-    }
-    void unlock() RELEASE(mLock) {
-        mLock.unlock();
-    }
-
-    status_t createEffect_l(sp<EffectModule>& effect,
+    status_t createEffect_l(sp<IAfEffectModule>& effect,
                             effect_descriptor_t *desc,
                             int id,
                             audio_session_t sessionId,
-                            bool pinned);
-    status_t addEffect_l(const sp<EffectModule>& handle);
-    status_t addEffect_ll(const sp<EffectModule>& handle);
-    size_t removeEffect_l(const sp<EffectModule>& handle, bool release = false);
+                            bool pinned) final;
+    status_t addEffect_l(const sp<IAfEffectModule>& handle) final;
+    status_t addEffect_ll(const sp<IAfEffectModule>& handle) final;
+    size_t removeEffect_l(const sp<IAfEffectModule>& handle, bool release = false) final;
 
-    audio_session_t sessionId() const { return mSessionId; }
-    void setSessionId(audio_session_t sessionId) { mSessionId = sessionId; }
+    audio_session_t sessionId() const final { return mSessionId; }
+    void setSessionId(audio_session_t sessionId) final { mSessionId = sessionId; }
 
-    sp<EffectModule> getEffectFromDesc_l(effect_descriptor_t *descriptor);
-    sp<EffectModule> getEffectFromId_l(int id);
-    sp<EffectModule> getEffectFromType_l(const effect_uuid_t *type);
-    std::vector<int> getEffectIds();
+    sp<IAfEffectModule> getEffectFromDesc_l(effect_descriptor_t *descriptor) const final;
+    sp<IAfEffectModule> getEffectFromId_l(int id) const final;
+    sp<IAfEffectModule> getEffectFromType_l(const effect_uuid_t *type) const final;
+    std::vector<int> getEffectIds() const final;
     // FIXME use float to improve the dynamic range
-    bool setVolume_l(uint32_t *left, uint32_t *right, bool force = false);
-    void resetVolume_l();
-    void setDevices_l(const AudioDeviceTypeAddrVector &devices);
-    void setInputDevice_l(const AudioDeviceTypeAddr &device);
-    void setMode_l(audio_mode_t mode);
-    void setAudioSource_l(audio_source_t source);
 
-    void setInBuffer(const sp<EffectBufferHalInterface>& buffer) {
+    bool setVolume_l(uint32_t *left, uint32_t *right, bool force = false) final;
+    void resetVolume_l() final;
+    void setDevices_l(const AudioDeviceTypeAddrVector &devices) final;
+    void setInputDevice_l(const AudioDeviceTypeAddr &device) final;
+    void setMode_l(audio_mode_t mode) final;
+    void setAudioSource_l(audio_source_t source) final;
+
+    void setInBuffer(const sp<EffectBufferHalInterface>& buffer) final {
         mInBuffer = buffer;
     }
-    float *inBuffer() const {
+    float *inBuffer() const final {
         return mInBuffer != 0 ? reinterpret_cast<float*>(mInBuffer->ptr()) : NULL;
     }
-    void setOutBuffer(const sp<EffectBufferHalInterface>& buffer) {
+    void setOutBuffer(const sp<EffectBufferHalInterface>& buffer) final {
         mOutBuffer = buffer;
     }
-    float *outBuffer() const {
+    float *outBuffer() const final {
         return mOutBuffer != 0 ? reinterpret_cast<float*>(mOutBuffer->ptr()) : NULL;
     }
+    void incTrackCnt() final { android_atomic_inc(&mTrackCnt); }
+    void decTrackCnt() final { android_atomic_dec(&mTrackCnt); }
+    int32_t trackCnt() const final { return android_atomic_acquire_load(&mTrackCnt); }
 
-    void incTrackCnt() { android_atomic_inc(&mTrackCnt); }
-    void decTrackCnt() { android_atomic_dec(&mTrackCnt); }
-    int32_t trackCnt() const { return android_atomic_acquire_load(&mTrackCnt); }
-
-    void incActiveTrackCnt() { android_atomic_inc(&mActiveTrackCnt);
+    void incActiveTrackCnt() final { android_atomic_inc(&mActiveTrackCnt);
                                mTailBufferCount = mMaxTailBuffers; }
-    void decActiveTrackCnt() { android_atomic_dec(&mActiveTrackCnt); }
-    int32_t activeTrackCnt() const { return android_atomic_acquire_load(&mActiveTrackCnt); }
+    void decActiveTrackCnt() final { android_atomic_dec(&mActiveTrackCnt); }
+    int32_t activeTrackCnt() const final {
+        return android_atomic_acquire_load(&mActiveTrackCnt);
+    }
 
-    product_strategy_t strategy() const { return mStrategy; }
-    void setStrategy(product_strategy_t strategy)
+    product_strategy_t strategy() const final { return mStrategy; }
+    void setStrategy(product_strategy_t strategy) final
             { mStrategy = strategy; }
 
     // suspend or restore effects of the specified type. The number of suspend requests is counted
     // and restore occurs once all suspend requests are cancelled.
     void setEffectSuspended_l(const effect_uuid_t *type,
-                              bool suspend);
+                              bool suspend) final;
     // suspend all eligible effects
-    void setEffectSuspendedAll_l(bool suspend);
+    void setEffectSuspendedAll_l(bool suspend) final;
     // check if effects should be suspended or restored when a given effect is enable or disabled
-    void checkSuspendOnEffectEnabled(const sp<EffectModule>& effect, bool enabled);
+    void checkSuspendOnEffectEnabled(
+            const sp<IAfEffectModule>& effect, bool enabled) final;
 
-    void clearInputBuffer();
+    void clearInputBuffer() final;
 
     // At least one non offloadable effect in the chain is enabled
-    bool isNonOffloadableEnabled();
-    bool isNonOffloadableEnabled_l();
+    bool isNonOffloadableEnabled() const final;
+    bool isNonOffloadableEnabled_l() const final;
 
-    void syncHalEffectsState();
+    void syncHalEffectsState() final;
 
     // flags is an ORed set of audio_output_flags_t which is updated on return.
-    void checkOutputFlagCompatibility(audio_output_flags_t *flags) const;
+    void checkOutputFlagCompatibility(audio_output_flags_t *flags) const final;
 
     // flags is an ORed set of audio_input_flags_t which is updated on return.
-    void checkInputFlagCompatibility(audio_input_flags_t *flags) const;
+    void checkInputFlagCompatibility(audio_input_flags_t *flags) const final;
 
     // Is this EffectChain compatible with the RAW audio flag.
-    bool isRawCompatible() const;
+    bool isRawCompatible() const final;
 
     // Is this EffectChain compatible with the FAST audio flag.
-    bool isFastCompatible() const;
+    bool isFastCompatible() const final;
 
     // Is this EffectChain compatible with the bit-perfect audio flag.
-    bool isBitPerfectCompatible() const;
+    bool isBitPerfectCompatible() const final;
 
-    // isCompatibleWithThread_l() must be called with thread->mLock held
-    bool isCompatibleWithThread_l(const sp<ThreadBase>& thread) const;
+    // isCompatibleWithThread_l() must be called with thread->mutex() held
+    bool isCompatibleWithThread_l(const sp<IAfThreadBase>& thread) const final;
 
-    bool containsHapticGeneratingEffect_l();
+    bool containsHapticGeneratingEffect_l() final;
 
-    void setHapticIntensity_l(int id, os::HapticScale intensity);
+    void setHapticIntensity_l(int id, os::HapticScale intensity) final;
 
-    sp<EffectCallbackInterface> effectCallback() const { return mEffectCallback; }
-    wp<ThreadBase> thread() const { return mEffectCallback->thread(); }
+    sp<EffectCallbackInterface> effectCallback() const final { return mEffectCallback; }
 
-    bool isFirstEffect(int id) const { return !mEffects.isEmpty() && id == mEffects[0]->id(); }
+    wp<IAfThreadBase> thread() const final { return mEffectCallback->thread(); }
 
-    void dump(int fd, const Vector<String16>& args);
+    bool isFirstEffect(int id) const final {
+        return !mEffects.isEmpty() && id == mEffects[0]->id();
+    }
+
+    void dump(int fd, const Vector<String16>& args) const final;
+
+    size_t numberOfEffects() const final { return mEffects.size(); }
+
+    sp<IAfEffectModule> getEffectModule(size_t index) const final {
+        return mEffects[index];
+    }
+
+    void setThread(const sp<IAfThreadBase>& thread) final;
 
 private:
 
@@ -574,22 +525,17 @@
         // Note: ctors taking a weak pointer to their owner must not promote it
         // during construction (but may keep a reference for later promotion).
         EffectCallback(const wp<EffectChain>& owner,
-                       const wp<ThreadBase>& thread)
+                const sp<IAfThreadBase>& thread)  // we take a sp<> but store a wp<>.
             : mChain(owner)
-            , mThread(thread)
-            , mAudioFlinger(*gAudioFlinger) {
-            sp<ThreadBase> base = thread.promote();
-            if (base != nullptr) {
-                mThreadType = base->type();
-            } else {
-                mThreadType = ThreadBase::MIXER;  // assure a consistent value.
-            }
+            , mThread(thread) {
+            mThreadType = thread->type();
+            mAfThreadCallback = thread->afThreadCallback();
         }
 
         status_t createEffectHal(const effect_uuid_t *pEffectUuid,
                int32_t sessionId, int32_t deviceId, sp<EffectHalInterface> *effect) override;
         status_t allocateHalBuffer(size_t size, sp<EffectBufferHalInterface>* buffer) override;
-        bool updateOrphanEffectChains(const sp<EffectBase>& effect) override;
+        bool updateOrphanEffectChains(const sp<IAfEffectBase>& effect) override;
 
         audio_io_handle_t io() const override;
         bool isOutput() const override;
@@ -609,39 +555,39 @@
 
         status_t addEffectToHal(const sp<EffectHalInterface>& effect) override;
         status_t removeEffectFromHal(const sp<EffectHalInterface>& effect) override;
-        bool disconnectEffectHandle(EffectHandle *handle, bool unpinIfLast) override;
+        bool disconnectEffectHandle(IAfEffectHandle *handle, bool unpinIfLast) override;
         void setVolumeForOutput(float left, float right) const override;
 
         // check if effects should be suspended/restored when a given effect is enable/disabled
-        void checkSuspendOnEffectEnabled(const sp<EffectBase>& effect,
+        void checkSuspendOnEffectEnabled(const sp<IAfEffectBase>& effect,
                               bool enabled, bool threadLocked) override;
         void resetVolume() override;
         product_strategy_t strategy() const override;
         int32_t activeTrackCnt() const override;
-        void onEffectEnable(const sp<EffectBase>& effect) override;
-        void onEffectDisable(const sp<EffectBase>& effect) override;
+        void onEffectEnable(const sp<IAfEffectBase>& effect) override;
+        void onEffectDisable(const sp<IAfEffectBase>& effect) override;
 
-        wp<EffectChain> chain() const override { return mChain; }
+        wp<IAfEffectChain> chain() const final { return mChain; }
 
-        bool isAudioPolicyReady() const override {
-            return mAudioFlinger.isAudioPolicyReady();
+        bool isAudioPolicyReady() const final {
+            return mAfThreadCallback->isAudioPolicyReady();
         }
 
-        wp<ThreadBase> thread() const { return mThread.load(); }
+        wp<IAfThreadBase> thread() const { return mThread.load(); }
 
-        void setThread(const sp<ThreadBase>& thread) {
+        void setThread(const sp<IAfThreadBase>& thread) {
             mThread = thread;
             mThreadType = thread->type();
+            mAfThreadCallback = thread->afThreadCallback();
         }
 
     private:
-        const wp<EffectChain> mChain;
-        mediautils::atomic_wp<ThreadBase> mThread;
-        AudioFlinger &mAudioFlinger;  // implementation detail: outer instance always exists.
-        ThreadBase::type_t mThreadType;
+        const wp<IAfEffectChain> mChain;
+        mediautils::atomic_wp<IAfThreadBase> mThread;
+        sp<IAfThreadCallback> mAfThreadCallback;
+        IAfThreadBase::type_t mThreadType;
     };
 
-    friend class AudioFlinger;  // for mThread, mEffects
     DISALLOW_COPY_AND_ASSIGN(EffectChain);
 
     class SuspendedEffectDesc : public RefBase {
@@ -650,15 +596,15 @@
 
         int mRefCount;   // > 0 when suspended
         effect_uuid_t mType;
-        wp<EffectModule> mEffect;
+        wp<IAfEffectModule> mEffect;
     };
 
     // get a list of effect modules to suspend when an effect of the type
     // passed is enabled.
-    void                       getSuspendEligibleEffects(Vector< sp<EffectModule> > &effects);
+    void  getSuspendEligibleEffects(Vector<sp<IAfEffectModule>> &effects);
 
     // get an effect module if it is currently enable
-    sp<EffectModule> getEffectIfEnabled(const effect_uuid_t *type);
+    sp<IAfEffectModule> getEffectIfEnabled(const effect_uuid_t *type);
     // true if the effect whose descriptor is passed can be suspended
     // OEMs can modify the rules implemented in this method to exclude specific effect
     // types or implementations from the suspend/restore mechanism.
@@ -668,8 +614,6 @@
 
     void clearInputBuffer_l();
 
-    void setThread(const sp<ThreadBase>& thread);
-
     // true if any effect module within the chain has volume control
     bool hasVolumeControlEnabled_l() const;
 
@@ -679,8 +623,8 @@
 
     std::optional<size_t> findVolumeControl_l(size_t from, size_t to) const;
 
-    mutable  Mutex mLock;        // mutex protecting effect list
-             Vector< sp<EffectModule> > mEffects; // list of effect modules
+    mutable audio_utils::mutex mMutex; // mutex protecting effect list
+             Vector<sp<IAfEffectModule>> mEffects; // list of effect modules
              audio_session_t mSessionId; // audio session ID
              sp<EffectBufferHalInterface> mInBuffer;  // chain input buffer
              sp<EffectBufferHalInterface> mOutBuffer; // chain output buffer
@@ -704,38 +648,42 @@
 
              const sp<EffectCallback> mEffectCallback;
 
-             wp<EffectModule> mVolumeControlEffect;
+             wp<IAfEffectModule> mVolumeControlEffect;
 };
 
-class DeviceEffectProxy : public EffectBase {
+class DeviceEffectProxy : public IAfDeviceEffectProxy, public EffectBase {
 public:
-        DeviceEffectProxy (const AudioDeviceTypeAddr& device,
-                const sp<DeviceEffectManagerCallback>& callback,
+    DeviceEffectProxy(const AudioDeviceTypeAddr& device,
+            const sp<DeviceEffectManagerCallback>& callback,
                 effect_descriptor_t *desc, int id, bool notifyFramesProcessed)
             : EffectBase(callback, desc, id, AUDIO_SESSION_DEVICE, false),
                 mDevice(device), mManagerCallback(callback),
                 mMyCallback(new ProxyCallback(wp<DeviceEffectProxy>(this), callback)),
                 mNotifyFramesProcessed(notifyFramesProcessed) {}
 
-    status_t setEnabled(bool enabled, bool fromHandle) override;
-    sp<DeviceEffectProxy> asDeviceEffectProxy() override { return this; }
+    status_t setEnabled(bool enabled, bool fromHandle) final;
+    sp<IAfDeviceEffectProxy> asDeviceEffectProxy() final { return this; }
 
-    status_t init(const std::map<audio_patch_handle_t, PatchPanel::Patch>& patches);
-    status_t onCreatePatch(audio_patch_handle_t patchHandle, const PatchPanel::Patch& patch);
-    void onReleasePatch(audio_patch_handle_t patchHandle);
+    status_t init(const std::map<audio_patch_handle_t,
+            IAfPatchPanel::Patch>& patches) final;
 
-    size_t removeEffect(const sp<EffectModule>& effect);
+    status_t onCreatePatch(audio_patch_handle_t patchHandle,
+            const IAfPatchPanel::Patch& patch) final;
 
-    status_t addEffectToHal(const sp<EffectHalInterface>& effect);
-    status_t removeEffectFromHal(const sp<EffectHalInterface>& effect);
+    void onReleasePatch(audio_patch_handle_t patchHandle) final;
 
-    const AudioDeviceTypeAddr& device() { return mDevice; };
-    bool isOutput() const;
-    uint32_t sampleRate() const;
-    audio_channel_mask_t channelMask() const;
-    uint32_t channelCount() const;
+    size_t removeEffect(const sp<IAfEffectModule>& effect) final;
 
-    void dump(int fd, int spaces);
+    status_t addEffectToHal(const sp<EffectHalInterface>& effect) final;
+    status_t removeEffectFromHal(const sp<EffectHalInterface>& effect) final;
+
+    const AudioDeviceTypeAddr& device() const final { return mDevice; };
+    bool isOutput() const final;
+    uint32_t sampleRate() const final;
+    audio_channel_mask_t channelMask() const final;
+    uint32_t channelCount() const final;
+
+    void dump2(int fd, int spaces) const final;
 
 private:
 
@@ -751,7 +699,7 @@
                int32_t sessionId, int32_t deviceId, sp<EffectHalInterface> *effect) override;
         status_t allocateHalBuffer(size_t size __unused,
                 sp<EffectBufferHalInterface>* buffer __unused) override { return NO_ERROR; }
-        bool updateOrphanEffectChains(const sp<EffectBase>& effect __unused) override {
+        bool updateOrphanEffectChains(const sp<IAfEffectBase>& effect __unused) override {
                     return false;
         }
 
@@ -774,18 +722,18 @@
         status_t addEffectToHal(const sp<EffectHalInterface>& effect) override;
         status_t removeEffectFromHal(const sp<EffectHalInterface>& effect) override;
 
-        bool disconnectEffectHandle(EffectHandle *handle, bool unpinIfLast) override;
+        bool disconnectEffectHandle(IAfEffectHandle *handle, bool unpinIfLast) override;
         void setVolumeForOutput(float left __unused, float right __unused) const override {}
 
-        void checkSuspendOnEffectEnabled(const sp<EffectBase>& effect __unused,
+        void checkSuspendOnEffectEnabled(const sp<IAfEffectBase>& effect __unused,
                               bool enabled __unused, bool threadLocked __unused) override {}
         void resetVolume() override {}
         product_strategy_t strategy() const override  { return static_cast<product_strategy_t>(0); }
         int32_t activeTrackCnt() const override { return 0; }
-        void onEffectEnable(const sp<EffectBase>& effect __unused) override;
-        void onEffectDisable(const sp<EffectBase>& effect __unused) override;
+        void onEffectEnable(const sp<IAfEffectBase>& effect __unused) override;
+        void onEffectDisable(const sp<IAfEffectBase>& effect __unused) override;
 
-        wp<EffectChain> chain() const override { return nullptr; }
+        wp<IAfEffectChain> chain() const override { return nullptr; }
 
         bool isAudioPolicyReady() const override {
             return mManagerCallback->isAudioPolicyReady();
@@ -798,16 +746,19 @@
         const sp<DeviceEffectManagerCallback> mManagerCallback;
     };
 
-    status_t checkPort(const PatchPanel::Patch& patch, const struct audio_port_config *port,
-            sp<EffectHandle> *handle);
+    status_t checkPort(const IAfPatchPanel::Patch& patch,
+            const struct audio_port_config *port, sp<IAfEffectHandle> *handle);
 
     const AudioDeviceTypeAddr mDevice;
     const sp<DeviceEffectManagerCallback> mManagerCallback;
     const sp<ProxyCallback> mMyCallback;
 
-    Mutex mProxyLock;
-    std::map<audio_patch_handle_t, sp<EffectHandle>> mEffectHandles; // protected by mProxyLock
-    sp<EffectModule> mHalEffect; // protected by mProxyLock
+    audio_utils::mutex& proxyMutex() const { return mProxyMutex; }
+    mutable audio_utils::mutex mProxyMutex;
+    std::map<audio_patch_handle_t, sp<IAfEffectHandle>> mEffectHandles; // protected by mProxyMutex
+    sp<IAfEffectModule> mHalEffect; // protected by mProxyMutex
     struct audio_port_config mDevicePort = { .id = AUDIO_PORT_HANDLE_NONE };
     const bool mNotifyFramesProcessed;
 };
+
+} // namespace android
diff --git a/services/audioflinger/IAfEffect.h b/services/audioflinger/IAfEffect.h
new file mode 100644
index 0000000..ea0c6d9
--- /dev/null
+++ b/services/audioflinger/IAfEffect.h
@@ -0,0 +1,379 @@
+/*
+ * 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 "IAfPatchPanel.h"  // full class Patch definition needed
+
+#include <android/media/AudioVibratorInfo.h>
+#include <android/media/BnEffect.h>
+#include <android/media/BnEffectClient.h>
+#include <audio_utils/mutex.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.
+class EffectCallbackInterface : public RefBase {
+public:
+    // Trivial methods usually implemented with help from ThreadBase
+    virtual audio_io_handle_t io() const = 0;
+    virtual bool isOutput() const = 0;
+    virtual bool isOffload() const = 0;
+    virtual bool isOffloadOrDirect() const = 0;
+    virtual bool isOffloadOrMmap() const = 0;
+    virtual bool isSpatializer() const = 0;
+    virtual uint32_t sampleRate() const = 0;
+    virtual audio_channel_mask_t inChannelMask(int id) const = 0;
+    virtual uint32_t inChannelCount(int id) const = 0;
+    virtual audio_channel_mask_t outChannelMask() const = 0;
+    virtual uint32_t outChannelCount() const = 0;
+    virtual audio_channel_mask_t hapticChannelMask() const = 0;
+    virtual size_t frameCount() const = 0;
+
+    // Non trivial methods usually implemented with help from ThreadBase:
+    // pay attention to mutex locking order
+    virtual uint32_t latency() const { return 0; }
+    virtual status_t addEffectToHal(const sp<EffectHalInterface>& effect) = 0;
+    virtual status_t removeEffectFromHal(const sp<EffectHalInterface>& effect) = 0;
+    virtual void setVolumeForOutput(float left, float right) const = 0;
+    virtual bool disconnectEffectHandle(IAfEffectHandle *handle, bool unpinIfLast) = 0;
+    virtual void checkSuspendOnEffectEnabled(
+            const sp<IAfEffectBase>& effect, bool enabled, bool threadLocked) = 0;
+    virtual void onEffectEnable(const sp<IAfEffectBase>& effect) = 0;
+    virtual void onEffectDisable(const sp<IAfEffectBase>& effect) = 0;
+
+    // Methods usually implemented with help from AudioFlinger: pay attention to mutex locking order
+    virtual status_t createEffectHal(const effect_uuid_t *pEffectUuid,
+            int32_t sessionId, int32_t deviceId, sp<EffectHalInterface> *effect) = 0;
+    virtual status_t allocateHalBuffer(size_t size, sp<EffectBufferHalInterface>* buffer) = 0;
+    virtual bool updateOrphanEffectChains(const sp<IAfEffectBase>& effect) = 0;
+
+    // Methods usually implemented with help from EffectChain: pay attention to mutex locking order
+    virtual product_strategy_t strategy() const = 0;
+    virtual int32_t activeTrackCnt() const = 0;
+    virtual void resetVolume() = 0;
+    virtual wp<IAfEffectChain> chain() const = 0;
+    virtual bool isAudioPolicyReady() const = 0;
+};
+
+class IAfEffectBase : public virtual RefBase {
+    friend class EffectChain;
+    friend class EffectHandle;
+
+public:
+    enum effect_state {
+        IDLE,
+        RESTART,
+        STARTING,
+        ACTIVE,
+        STOPPING,
+        STOPPED,
+        DESTROYED
+    };
+    virtual int id() const = 0;
+    virtual effect_state state() const = 0;
+    virtual audio_session_t sessionId() const = 0;
+    virtual const effect_descriptor_t& desc() const = 0;
+    virtual bool isOffloadable() const = 0;
+    virtual bool isImplementationSoftware() const = 0;
+    virtual bool isProcessImplemented() const = 0;
+    virtual bool isVolumeControl() const = 0;
+    virtual bool isVolumeMonitor() const = 0;
+    virtual bool isEnabled() const = 0;
+    virtual bool isPinned() const = 0;
+    virtual void unPin() = 0;
+    virtual status_t updatePolicyState() = 0;
+    virtual bool purgeHandles() = 0;
+    virtual void checkSuspendOnEffectEnabled(bool enabled, bool threadLocked) = 0;
+
+    // mCallback is atomic so this can be lock-free.
+    virtual void setCallback(const sp<EffectCallbackInterface>& callback) = 0;
+    virtual sp<EffectCallbackInterface> getCallback() const = 0;
+
+    virtual status_t addHandle(IAfEffectHandle *handle) = 0;
+    virtual ssize_t removeHandle(IAfEffectHandle *handle) = 0;
+
+    virtual sp<IAfEffectModule> asEffectModule() = 0;
+    virtual sp<IAfDeviceEffectProxy> asDeviceEffectProxy() = 0;
+
+    virtual void dump(int fd, const Vector<String16>& args) const = 0;
+
+private:
+    virtual status_t setEnabled(bool enabled, bool fromHandle) = 0;
+    virtual status_t setEnabled_l(bool enabled) = 0;
+    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;
+
+    virtual audio_utils::mutex& mutex() const = 0;
+};
+
+class IAfEffectModule : public virtual IAfEffectBase {
+    friend class DeviceEffectProxy;
+    friend class EffectChain;
+
+public:
+    static sp<IAfEffectModule> create(
+            const sp<EffectCallbackInterface>& callabck,
+            effect_descriptor_t *desc,
+            int id,
+            audio_session_t sessionId,
+            bool pinned,
+            audio_port_handle_t deviceId);
+
+    virtual int16_t *inBuffer() const = 0;
+    virtual status_t setDevices(const AudioDeviceTypeAddrVector &devices) = 0;
+    virtual status_t setInputDevice(const AudioDeviceTypeAddr &device) = 0;
+    virtual status_t setVolume(uint32_t *left, uint32_t *right, bool controller) = 0;
+    virtual status_t setOffloaded(bool offloaded, audio_io_handle_t io) = 0;
+    virtual bool isOffloaded() const = 0;
+
+    virtual status_t setAudioSource(audio_source_t source) = 0;
+    virtual status_t setMode(audio_mode_t mode) = 0;
+
+    virtual status_t start() = 0;
+    virtual status_t getConfigs(audio_config_base_t* inputCfg,
+            audio_config_base_t* outputCfg,
+            bool* isOutput) const = 0;
+
+    static bool isHapticGenerator(const effect_uuid_t* type);
+    virtual bool isHapticGenerator() const = 0;
+    virtual status_t setHapticIntensity(int id, os::HapticScale intensity) = 0;
+    virtual status_t setVibratorInfo(const media::AudioVibratorInfo& vibratorInfo) = 0;
+
+private:
+    virtual void process() = 0;
+    virtual bool updateState() = 0;
+    virtual void reset_l() = 0;
+    virtual status_t configure() = 0;
+    virtual status_t init() = 0;
+    virtual uint32_t status() const = 0;
+    virtual bool isProcessEnabled() const = 0;
+    virtual bool isOffloadedOrDirect() const = 0;
+    virtual bool isVolumeControlEnabled() const = 0;
+
+    virtual void setInBuffer(const sp<EffectBufferHalInterface>& buffer) = 0;
+    virtual void setOutBuffer(const sp<EffectBufferHalInterface>& buffer) = 0;
+    virtual int16_t *outBuffer() const = 0;
+
+    // Updates the access mode if it is out of date.  May issue a new effect configure.
+    virtual void updateAccessMode() = 0;
+
+    virtual status_t stop() = 0;
+    virtual void addEffectToHal_l() = 0;
+    virtual void release_l() = 0;
+};
+
+class IAfEffectChain : public RefBase {
+    // Most of these methods are accessed from AudioFlinger::Thread
+public:
+    static sp<IAfEffectChain> create(
+            const sp<IAfThreadBase>& thread,
+            audio_session_t sessionId);
+
+    // special key used for an entry in mSuspendedEffects keyed vector
+    // corresponding to a suspend all request.
+    static constexpr int kKeyForSuspendAll = 0;
+
+    // minimum duration during which we force calling effect process when last track on
+    // a session is stopped or removed to allow effect tail to be rendered
+    static constexpr int kProcessTailDurationMs = 1000;
+
+    virtual void process_l() = 0;
+
+    virtual audio_utils::mutex& mutex() const = 0;
+
+    virtual status_t createEffect_l(sp<IAfEffectModule>& effect,
+                            effect_descriptor_t *desc,
+                            int id,
+                            audio_session_t sessionId,
+                            bool pinned) = 0;
+
+    virtual status_t addEffect_l(const sp<IAfEffectModule>& handle) = 0;
+    virtual status_t addEffect_ll(const sp<IAfEffectModule>& handle) = 0;
+    virtual size_t removeEffect_l(const sp<IAfEffectModule>& handle, bool release = false) = 0;
+
+    virtual audio_session_t sessionId() const = 0;
+    virtual void setSessionId(audio_session_t sessionId) = 0;
+
+    virtual sp<IAfEffectModule> getEffectFromDesc_l(effect_descriptor_t *descriptor) const = 0;
+    virtual sp<IAfEffectModule> getEffectFromId_l(int id) const = 0;
+    virtual sp<IAfEffectModule> getEffectFromType_l(const effect_uuid_t *type) const = 0;
+    virtual std::vector<int> getEffectIds() const = 0;
+    virtual bool setVolume_l(uint32_t *left, uint32_t *right, bool force = false) = 0;
+    virtual void resetVolume_l() = 0;
+    virtual void setDevices_l(const AudioDeviceTypeAddrVector &devices) = 0;
+    virtual void setInputDevice_l(const AudioDeviceTypeAddr &device) = 0;
+    virtual void setMode_l(audio_mode_t mode) = 0;
+    virtual void setAudioSource_l(audio_source_t source) = 0;
+
+    virtual void setInBuffer(const sp<EffectBufferHalInterface>& buffer) = 0;
+    virtual float *inBuffer() const = 0;
+    virtual void setOutBuffer(const sp<EffectBufferHalInterface>& buffer) = 0;
+    virtual float *outBuffer() const = 0;
+
+    virtual void incTrackCnt() = 0;
+    virtual void decTrackCnt() = 0;
+    virtual int32_t trackCnt() const = 0;
+
+    virtual void incActiveTrackCnt() = 0;
+    virtual void decActiveTrackCnt() = 0;
+    virtual int32_t activeTrackCnt() const = 0;
+
+    virtual product_strategy_t strategy() const = 0;
+    virtual void setStrategy(product_strategy_t strategy) = 0;
+
+    // suspend or restore effects of the specified type. The number of suspend requests is counted
+    // and restore occurs once all suspend requests are cancelled.
+    virtual void setEffectSuspended_l(
+            const effect_uuid_t *type, bool suspend) = 0;
+    // suspend all eligible effects
+    virtual void setEffectSuspendedAll_l(bool suspend) = 0;
+    // check if effects should be suspended or restored when a given effect is enable or disabled
+    virtual void checkSuspendOnEffectEnabled(const sp<IAfEffectModule>& effect, bool enabled) = 0;
+
+    virtual void clearInputBuffer() = 0;
+
+    // At least one non offloadable effect in the chain is enabled
+    virtual bool isNonOffloadableEnabled() const = 0;
+    virtual bool isNonOffloadableEnabled_l() const = 0;
+
+    virtual void syncHalEffectsState() = 0;
+
+    // flags is an ORed set of audio_output_flags_t which is updated on return.
+    virtual void checkOutputFlagCompatibility(audio_output_flags_t *flags) const = 0;
+
+    // flags is an ORed set of audio_input_flags_t which is updated on return.
+    virtual void checkInputFlagCompatibility(audio_input_flags_t *flags) const = 0;
+
+    // Is this EffectChain compatible with the RAW audio flag.
+    virtual bool isRawCompatible() const = 0;
+
+    // Is this EffectChain compatible with the FAST audio flag.
+    virtual bool isFastCompatible() const = 0;
+
+    // Is this EffectChain compatible with the bit-perfect audio flag.
+    virtual bool isBitPerfectCompatible() const = 0;
+
+    // isCompatibleWithThread_l() must be called with thread->mLock held
+    virtual bool isCompatibleWithThread_l(const sp<IAfThreadBase>& thread) const = 0;
+
+    virtual bool containsHapticGeneratingEffect_l() = 0;
+
+    virtual void setHapticIntensity_l(int id, os::HapticScale intensity) = 0;
+
+    virtual sp<EffectCallbackInterface> effectCallback() const = 0;
+
+    virtual wp<IAfThreadBase> thread() const = 0;
+    virtual void setThread(const sp<IAfThreadBase>& thread) = 0;
+
+    virtual bool isFirstEffect(int id) const = 0;
+
+    virtual size_t numberOfEffects() const = 0;
+    virtual sp<IAfEffectModule> getEffectModule(size_t index) const = 0;
+
+    virtual void dump(int fd, const Vector<String16>& args) const = 0;
+};
+
+class IAfEffectHandle : public virtual RefBase {
+    friend class EffectBase;
+    friend class EffectChain;
+    friend class EffectModule;
+
+public:
+    static sp<IAfEffectHandle> create(
+            const sp<IAfEffectBase>& effect,
+            const sp<Client>& client,
+            const sp<media::IEffectClient>& effectClient,
+            int32_t priority, bool notifyFramesProcessed);
+
+    virtual status_t initCheck() const = 0;
+    virtual bool enabled() const = 0;
+    virtual int id() const = 0;
+    virtual wp<IAfEffectBase> effect() const = 0;
+    virtual sp<android::media::IEffect> asIEffect() = 0;
+    virtual const sp<Client>& client() const = 0;
+
+private:
+    virtual void setControl(bool hasControl, bool signal, bool enabled) = 0;
+    virtual bool hasControl() const = 0;
+    virtual void setEnabled(bool enabled) = 0;
+    virtual bool disconnected() const = 0;
+    virtual int priority() const = 0;
+
+    virtual void commandExecuted(uint32_t cmdCode,
+            const std::vector<uint8_t>& cmdData,
+            const std::vector<uint8_t>& replyData) = 0;
+    virtual void framesProcessed(int32_t frames) const = 0;
+
+    virtual void dumpToBuffer(char* buffer, size_t size) const = 0;
+};
+
+class IAfDeviceEffectProxy : public virtual IAfEffectBase {
+public:
+    static sp<IAfDeviceEffectProxy> create(const AudioDeviceTypeAddr& device,
+                const sp<DeviceEffectManagerCallback>& callback,
+                effect_descriptor_t *desc, int id, bool notifyFramesProcessed);
+
+    virtual status_t init(
+            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 IAfPatchPanel::Patch& patch) = 0;
+    virtual void onReleasePatch(audio_patch_handle_t patchHandle) = 0;
+
+    virtual void dump2(int fd, int spaces) const = 0; // TODO(b/291319101) naming?
+
+private:
+    // used by DeviceEffectProxy
+    virtual bool isOutput() const = 0;
+    virtual uint32_t sampleRate() const = 0;
+    virtual audio_channel_mask_t channelMask() const = 0;
+    virtual uint32_t channelCount() const = 0;
+
+    virtual size_t removeEffect(const sp<IAfEffectModule>& effect) = 0;
+    virtual status_t addEffectToHal(const sp<EffectHalInterface>& effect) = 0;
+    virtual status_t removeEffectFromHal(const sp<EffectHalInterface>& effect) = 0;
+};
+
+}  // namespace android
diff --git a/services/audioflinger/IAfPatchPanel.h b/services/audioflinger/IAfPatchPanel.h
new file mode 100644
index 0000000..5a6621e
--- /dev/null
+++ b/services/audioflinger/IAfPatchPanel.h
@@ -0,0 +1,307 @@
+/*
+ * 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;
+
+    status_t getLatencyMs_l(double* latencyMs) const REQUIRES(audio_utils::AudioFlinger_Mutex);
+    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) REQUIRES(mutex()) = 0;
+    virtual void closeThreadInternal_l(const sp<IAfRecordThread>& thread) REQUIRES(mutex()) = 0;
+    virtual IAfPlaybackThread* primaryPlaybackThread_l() const REQUIRES(mutex()) = 0;
+    virtual IAfPlaybackThread* checkPlaybackThread_l(audio_io_handle_t output) const
+            REQUIRES(mutex()) = 0;
+    virtual IAfRecordThread* checkRecordThread_l(audio_io_handle_t input) const
+            REQUIRES(mutex()) = 0;
+    virtual IAfMmapThread* checkMmapThread_l(audio_io_handle_t io) const REQUIRES(mutex()) = 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) REQUIRES(mutex()) = 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) REQUIRES(mutex()) = 0;
+    virtual audio_utils::mutex& mutex() const
+            RETURN_CAPABILITY(audio_utils::AudioFlinger_Mutex) = 0;
+    virtual const DefaultKeyedVector<audio_module_handle_t, AudioHwDevice*>&
+            getAudioHwDevs_l() const REQUIRES(mutex()) = 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)
+            REQUIRES(mutex()) = 0;
+    virtual void updateOutDevicesForRecordThreads_l(const DeviceDescriptorBaseVector& devices)
+            REQUIRES(mutex()) = 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_l(const sp<IAfPatchPanel>& panel)
+                REQUIRES(audio_utils::AudioFlinger_Mutex)
+                NO_THREAD_SAFETY_ANALYSIS // this is broken in clang
+        {
+            if (mHandle != AUDIO_PATCH_HANDLE_NONE) {
+                panel->releaseAudioPatch_l(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_l(const sp<IAfPatchPanel>& panel)
+                REQUIRES(audio_utils::AudioFlinger_Mutex);
+        void clearConnections_l(const sp<IAfPatchPanel>& panel)
+                REQUIRES(audio_utils::AudioFlinger_Mutex);
+        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_l(unsigned int* num_ports, struct audio_port* ports)
+            REQUIRES(audio_utils::AudioFlinger_Mutex) = 0;
+
+    /* Get supported attributes for a given audio port */
+    virtual status_t getAudioPort_l(struct audio_port_v7* port)
+            REQUIRES(audio_utils::AudioFlinger_Mutex) = 0;
+
+    /* Create a patch between several source and sink ports */
+    virtual status_t createAudioPatch_l(
+            const struct audio_patch* patch,
+            audio_patch_handle_t* handle,
+            bool endpointPatch = false)
+            REQUIRES(audio_utils::AudioFlinger_Mutex) = 0;
+
+    /* Release a patch */
+    virtual status_t releaseAudioPatch_l(audio_patch_handle_t handle)
+            REQUIRES(audio_utils::AudioFlinger_Mutex) = 0;
+
+    /* List connected audio devices and they attributes */
+    virtual status_t listAudioPatches_l(unsigned int* num_patches, struct audio_patch* patches)
+            REQUIRES(audio_utils::AudioFlinger_Mutex) = 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;
+
+    virtual const std::map<audio_patch_handle_t, Patch>& patches_l() const
+            REQUIRES(audio_utils::AudioFlinger_Mutex) = 0;
+
+    virtual status_t getLatencyMs_l(audio_patch_handle_t patchHandle, double* latencyMs) const
+            REQUIRES(audio_utils::AudioFlinger_Mutex) = 0;
+
+    virtual void closeThreadInternal_l(const sp<IAfThreadBase>& thread) const
+            REQUIRES(audio_utils::AudioFlinger_Mutex) = 0;
+};
+
+}  // namespace android
diff --git a/services/audioflinger/IAfThread.h b/services/audioflinger/IAfThread.h
new file mode 100644
index 0000000..fc2f805
--- /dev/null
+++ b/services/audioflinger/IAfThread.h
@@ -0,0 +1,621 @@
+/*
+ * 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/mutex.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/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 audio_utils::mutex& mutex() const
+            RETURN_CAPABILITY(audio_utils::AudioFlinger_Mutex) = 0;
+    virtual bool isNonOffloadableGlobalEffectEnabled_l() const
+            REQUIRES(mutex()) = 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
+            REQUIRES(mutex()) = 0;
+    virtual bool masterMute_l() const
+            REQUIRES(mutex()) = 0;
+    virtual float getMasterBalance_l() const
+            REQUIRES(mutex()) = 0;
+    virtual bool streamMute_l(audio_stream_type_t stream) const
+            REQUIRES(mutex()) = 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
+            REQUIRES(mutex()) = 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)
+            EXCLUDES_AudioFlinger_Mutex = 0;
+    virtual status_t moveEffectChain_ll(audio_session_t sessionId,
+            IAfPlaybackThread* srcThread, IAfPlaybackThread* dstThread)
+            REQUIRES(mutex(), audio_utils::ThreadBase_Mutex) = 0;
+
+    virtual void requestLogMerge() = 0;
+    virtual sp<NBLog::Writer> newWriter_l(size_t size, const char *name)
+            REQUIRES(mutex()) = 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)
+            EXCLUDES_AudioFlinger_Mutex = 0;
+
+    virtual void ioConfigChanged(audio_io_config_event_t event,
+            const sp<AudioIoDescriptor>& ioDesc,
+            pid_t pid = 0) EXCLUDES_AudioFlinger_ClientMutex = 0;
+    virtual void onNonOffloadableGlobalEffectEnable() EXCLUDES_AudioFlinger_Mutex = 0;
+    virtual void onSupportedLatencyModesChanged(
+            audio_io_handle_t output, const std::vector<audio_latency_mode_t>& modes)
+            EXCLUDES_AudioFlinger_ClientMutex = 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)
+            REQUIRES(audio_utils::AudioFlinger_Mutex) = 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_ll(const sp<IAfEffectModule>& effect)
+            REQUIRES(audio_utils::AudioFlinger_Mutex, mutex()) = 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 audio_utils::mutex& mutex() const
+            RETURN_CAPABILITY(audio_utils::ThreadBase_Mutex) = 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)
+            REQUIRES(audio_utils::AudioFlinger_Mutex) = 0;
+    virtual void stopMelComputation_l()
+            REQUIRES(audio_utils::AudioFlinger_Mutex) = 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)
+            REQUIRES(audio_utils::AudioFlinger_Mutex) = 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)
+            REQUIRES(audio_utils::AudioFlinger_Mutex) = 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..cf30ded
--- /dev/null
+++ b/services/audioflinger/IAfTrack.h
@@ -0,0 +1,595 @@
+/*
+ * 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;
+
+    /**
+     * 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() = 0;
+
+    // Argument teePatchesToUpdate is by value, use std::move to optimize.
+    virtual void setTeePatchesToUpdate(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..add453f 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,9 +63,9 @@
     return true;
 }
 
-void AudioFlinger::MelReporter::activateInternalSoundDoseComputation() {
+void MelReporter::activateInternalSoundDoseComputation() {
     {
-        std::lock_guard _l(mLock);
+        audio_utils::lock_guard _l(mutex());
         if (!mUseHalSoundDoseInterface) {
             // no need to start internal MEL on active patches
             return;
@@ -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,15 +104,15 @@
     }
 }
 
-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 _l(mLock);
+    audio_utils::lock_guard _laf(mAfMelReporterCallback->mutex());  // AudioFlinger_Mutex
+    audio_utils::lock_guard _l(mutex());
     auto activeMelPatchId = activePatchStreamHandle_l(streamHandle);
     if (!activeMelPatchId) {
         ALOGV("%s stream handle %d does not have an active patch", __func__, streamHandle);
@@ -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,8 +171,8 @@
     }
 
     if (!newPatch.deviceHandles.empty()) {
-        std::lock_guard _afl(mAudioFlinger.mLock);
-        std::lock_guard _l(mLock);
+        audio_utils::lock_guard _afl(mAfMelReporterCallback->mutex());  // AudioFlinger_Mutex
+        audio_utils::lock_guard _l(mutex());
         ALOGV("%s add patch handle %d to active devices", __func__, handle);
         startMelComputationForActivePatch_l(newPatch);
         newPatch.csdActive = true;
@@ -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;
@@ -213,7 +213,7 @@
 
     ActiveMelPatch melPatch;
     {
-        std::lock_guard _l(mLock);
+        audio_utils::lock_guard _l(mutex());
 
         auto patchIt = mActiveMelPatches.find(handle);
         if (patchIt == mActiveMelPatches.end()) {
@@ -226,25 +226,25 @@
         mActiveMelPatches.erase(patchIt);
     }
 
-    std::lock_guard _afl(mAudioFlinger.mLock);
-    std::lock_guard _l(mLock);
+    audio_utils::lock_guard _afl(mAfMelReporterCallback->mutex());  // AudioFlinger_Mutex
+    audio_utils::lock_guard _l(mutex());
     stopMelComputationForPatch_l(melPatch);
 }
 
-sp<media::ISoundDose> AudioFlinger::MelReporter::getSoundDoseInterface(
+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);
+    audio_utils::lock_guard _l(mutex());
     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 +252,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) {
@@ -271,8 +271,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,12 +281,12 @@
     return std::nullopt;
 }
 
-bool AudioFlinger::MelReporter::useHalSoundDoseInterface_l() {
+bool MelReporter::useHalSoundDoseInterface_l() {
     return !mSoundDoseManager->forceUseFrameworkMel() & mUseHalSoundDoseInterface;
 }
 
-std::string AudioFlinger::MelReporter::dump() {
-    std::lock_guard _l(mLock);
+std::string MelReporter::dump() {
+    audio_utils::lock_guard _l(mutex());
     std::string output("\nSound Dose:\n");
     output.append(mSoundDoseManager->dump());
     return output;
diff --git a/services/audioflinger/MelReporter.h b/services/audioflinger/MelReporter.h
index 2bc33f2..07ab94d 100644
--- a/services/audioflinger/MelReporter.h
+++ b/services/audioflinger/MelReporter.h
@@ -15,25 +15,38 @@
 ** limitations under the License.
 */
 
-#ifndef INCLUDING_FROM_AUDIOFLINGER_H
-    #error This header file should only be included from AudioFlinger.h
-#endif
+#pragma once
 
-#include <mutex>
+#include "IAfPatchPanel.h"
+#include "PatchCommandThread.h"
+
+#include <audio_utils/mutex.h>
 #include <sounddose/SoundDoseManager.h>
+
 #include <unordered_map>
 
+namespace android {
+
 constexpr static int kMaxTimestampDeltaInSec = 120;
 
+class IAfMelReporterCallback : public virtual RefBase {
+public:
+    virtual audio_utils::mutex& mutex() const
+            RETURN_CAPABILITY(audio_utils::AudioFlinger_Mutex) = 0;
+    virtual const sp<PatchCommandThread>& getPatchCommandThread() = 0;
+    virtual sp<IAfThreadBase> checkOutputThread_l(audio_io_handle_t ioHandle) const
+            REQUIRES(mutex()) = 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),
-          mSoundDoseManager(sp<SoundDoseManager>::make()) {}
+    explicit MelReporter(const sp<IAfMelReporterCallback>& afMelReporterCallback)
+        : mAfMelReporterCallback(afMelReporterCallback),
+         mSoundDoseManager(sp<SoundDoseManager>::make()) {}
 
     void onFirstRef() override;
 
@@ -51,7 +64,7 @@
      * implementation, false otherwise.
      */
     bool activateHalSoundDoseComputation(const std::string& module,
-                                         const sp<DeviceHalInterface>& device);
+            const sp<DeviceHalInterface>& device) EXCLUDES_MelReporter_Mutex;
 
     /**
      * Activates the MEL reporting from internal framework values. These are used
@@ -59,7 +72,7 @@
      * Note: the internal CSD computation does not guarantee a certification with
      * IEC62368-1 3rd edition or EN50332-3
      */
-    void activateInternalSoundDoseComputation();
+    void activateInternalSoundDoseComputation() EXCLUDES_MelReporter_Mutex;
 
     sp<media::ISoundDose> getSoundDoseInterface(const sp<media::ISoundDoseCallback>& callback);
 
@@ -67,8 +80,9 @@
 
     // 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
+            EXCLUDES_AudioFlinger_Mutex;
+    void onReleaseAudioPatch(audio_patch_handle_t handle) final EXCLUDES_AudioFlinger_Mutex;
 
     /**
      * The new metadata can determine whether we should compute MEL for the given thread.
@@ -76,7 +90,9 @@
      * Otherwise, this method will disable CSD.
      **/
     void updateMetadataForCsd(audio_io_handle_t streamHandle,
-                              const std::vector<playback_track_metadata_v7_t>& metadataVec);
+            const std::vector<playback_track_metadata_v7_t>& metadataVec)
+            EXCLUDES_AudioFlinger_Mutex;
+
 private:
     struct ActiveMelPatch {
         audio_io_handle_t streamHandle{AUDIO_IO_HANDLE_NONE};
@@ -88,30 +104,34 @@
     bool shouldComputeMelForDeviceType(audio_devices_t device);
 
     void stopInternalMelComputation();
+    audio_utils::mutex& mutex() const RETURN_CAPABILITY(audio_utils::MelReporter_Mutex) {
+        return mMutex;
+    }
 
-    /** Should be called with the following order of locks: mAudioFlinger.mLock -> mLock. */
-    void stopMelComputationForPatch_l(const ActiveMelPatch& patch) REQUIRES(mLock);
+    /** Should be called with the following order of locks: mAudioFlinger.mutex() -> mutex(). */
+    void stopMelComputationForPatch_l(const ActiveMelPatch& patch) REQUIRES(mutex());
 
-    /** Should be called with the following order of locks: mAudioFlinger.mLock -> mLock. */
-    void startMelComputationForActivePatch_l(const ActiveMelPatch& patch) REQUIRES(mLock);
+    /** Should be called with the following order of locks: mAudioFlinger.mutex() -> mutex(). */
+    void startMelComputationForActivePatch_l(const ActiveMelPatch& patch) REQUIRES(mutex());
 
     std::optional<audio_patch_handle_t>
-    activePatchStreamHandle_l(audio_io_handle_t streamHandle) REQUIRES(mLock);
+    activePatchStreamHandle_l(audio_io_handle_t streamHandle) REQUIRES(mutex());
 
-    bool useHalSoundDoseInterface_l() REQUIRES(mLock);
+    bool useHalSoundDoseInterface_l() REQUIRES(mutex());
 
-    AudioFlinger& mAudioFlinger;  // does not own the object
+    const sp<IAfMelReporterCallback> mAfMelReporterCallback;
 
-    sp<SoundDoseManager> mSoundDoseManager;
+    /* const */ sp<SoundDoseManager> mSoundDoseManager;  // set onFirstRef
 
     /**
      * Lock for protecting the active mel patches. Do not mix with the AudioFlinger lock.
-     * Locking order AudioFlinger::mLock -> PatchCommandThread::mLock -> MelReporter::mLock.
+     * Locking order AudioFlinger::mutex() -> PatchCommandThread::mutex() -> MelReporter::mutex().
      */
-    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;
+    mutable audio_utils::mutex mMutex;
+    std::unordered_map<audio_patch_handle_t, ActiveMelPatch> mActiveMelPatches
+            GUARDED_BY(mutex());
+    std::unordered_map<audio_port_handle_t, int> mActiveDevices GUARDED_BY(mutex());
+    bool mUseHalSoundDoseInterface GUARDED_BY(mutex()) = 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..f4c76d6 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);
+    audio_utils::lock_guard _l(mutex());
     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);
+    audio_utils::lock_guard _l(listenerMutex());
     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,15 +53,14 @@
     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()
-NO_THREAD_SAFETY_ANALYSIS  // bug in clang compiler.
+bool PatchCommandThread::threadLoop()
 {
-    std::unique_lock _l(mLock);
+    audio_utils::unique_lock _l(mutex());
 
     while (!exitPending()) {
         while (!mCommands.empty() && !exitPending()) {
@@ -69,7 +70,7 @@
 
             std::vector<wp<PatchCommandListener>> listenersCopy;
             {
-                std::lock_guard _ll(mListenerLock);
+                audio_utils::lock_guard _ll(listenerMutex());
                 listenersCopy = mListeners;
             }
 
@@ -119,14 +120,14 @@
     return false;
 }
 
-void AudioFlinger::PatchCommandThread::sendCommand(const sp<Command>& command) {
-    std::lock_guard _l(mLock);
+void PatchCommandThread::sendCommand(const sp<Command>& command) {
+    audio_utils::lock_guard _l(mutex());
     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,17 +137,17 @@
     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::exit() {
     ALOGV("%s", __func__);
     {
-        std::lock_guard _l(mLock);
+        audio_utils::lock_guard _l(mutex());
         requestExit();
         mWaitWorkCV.notify_one();
     }
diff --git a/services/audioflinger/PatchCommandThread.h b/services/audioflinger/PatchCommandThread.h
index b52e0a9..8ca96f1 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:
@@ -35,17 +43,19 @@
     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;
     };
 
     PatchCommandThread() : Thread(false /* canCallJava */) {}
     ~PatchCommandThread() override;
 
-    void addListener(const sp<PatchCommandListener>& listener);
+    void addListener(const sp<PatchCommandListener>& listener)
+            EXCLUDES_PatchCommandThread_ListenerMutex;
 
-    void createAudioPatch(audio_patch_handle_t handle, const PatchPanel::Patch& patch);
-    void releaseAudioPatch(audio_patch_handle_t handle);
+    void createAudioPatch(audio_patch_handle_t handle, const IAfPatchPanel::Patch& patch)
+            EXCLUDES_PatchCommandThread_Mutex;
+    void releaseAudioPatch(audio_patch_handle_t handle) EXCLUDES_PatchCommandThread_Mutex;
 
     // Thread virtuals
     void onFirstRef() override;
@@ -54,9 +64,8 @@
     void exit();
 
     void createAudioPatchCommand(audio_patch_handle_t handle,
-            const PatchPanel::Patch& patch);
-    void releaseAudioPatchCommand(audio_patch_handle_t handle);
-
+            const IAfPatchPanel::Patch& patch) EXCLUDES_PatchCommandThread_Mutex;
+    void releaseAudioPatchCommand(audio_patch_handle_t handle) EXCLUDES_PatchCommandThread_Mutex;
 private:
     class CommandData;
 
@@ -75,11 +84,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,13 +99,22 @@
         audio_patch_handle_t mHandle;
     };
 
-    void sendCommand(const sp<Command>& command);
+    void sendCommand(const sp<Command>& command) EXCLUDES_PatchCommandThread_Mutex;
 
-    std::string mThreadName;
-    std::mutex mLock;
-    std::condition_variable mWaitWorkCV;
-    std::deque<sp<Command>> mCommands GUARDED_BY(mLock); // list of pending commands
+    audio_utils::mutex& mutex() const RETURN_CAPABILITY(audio_utils::PatchCommandThread_Mutex) {
+        return mMutex;
+    }
+    audio_utils::mutex& listenerMutex() const
+            RETURN_CAPABILITY(audio_utils::PatchCommandThread_ListenerMutex) {
+        return mListenerMutex;
+    }
 
-    std::mutex mListenerLock;
-    std::vector<wp<PatchCommandListener>> mListeners GUARDED_BY(mListenerLock);
+    mutable audio_utils::mutex mMutex;
+    audio_utils::condition_variable mWaitWorkCV;
+    std::deque<sp<Command>> mCommands GUARDED_BY(mutex()); // list of pending commands
+
+    mutable audio_utils::mutex mListenerMutex;
+    std::vector<wp<PatchCommandListener>> mListeners GUARDED_BY(listenerMutex());
 };
+
+}  // namespace android
diff --git a/services/audioflinger/PatchPanel.cpp b/services/audioflinger/PatchPanel.cpp
index 837d045..7d3900b 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_l(unsigned int* /* num_ports */,
                                 struct audio_port *ports __unused)
 {
     ALOGV(__func__);
@@ -113,14 +91,14 @@
 }
 
 /* Get supported attributes for a given audio port */
-status_t AudioFlinger::PatchPanel::getAudioPort(struct audio_port_v7 *port)
+status_t PatchPanel::getAudioPort_l(struct audio_port_v7* port)
 {
     if (port->type != AUDIO_PORT_TYPE_DEVICE) {
         // Only query the HAL when the port is a device.
         // TODO: implement getAudioPort for mix.
         return INVALID_OPERATION;
     }
-    AudioHwDevice* hwDevice = findAudioHwDeviceByModule(port->ext.device.hw_module);
+    AudioHwDevice* hwDevice = findAudioHwDeviceByModule_l(port->ext.device.hw_module);
     if (hwDevice == nullptr) {
         ALOGW("%s cannot find hw module %d", __func__, port->ext.device.hw_module);
         return BAD_VALUE;
@@ -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_l(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
@@ -166,7 +144,7 @@
             // 1) if a software patch is present, release the playback and capture threads and
             // tracks created. This will also release the corresponding audio HAL patches
             if (removedPatch.isSoftware()) {
-                removedPatch.clearConnections(this);
+                removedPatch.clearConnections_l(this);
             }
             // 2) if the new patch and old patch source or sink are devices from different
             // hw modules,  clear the audio HAL patches now because they will not be updated
@@ -191,7 +169,7 @@
                     // removedPatch.mHalHandle would be AUDIO_PATCH_HANDLE_NONE in this case.
                     hwModule = oldPatch.sinks[0].ext.device.hw_module;
                 }
-                sp<DeviceHalInterface> hwDevice = findHwDeviceByModule(hwModule);
+                sp<DeviceHalInterface> hwDevice = findHwDeviceByModule_l(hwModule);
                 if (hwDevice != 0) {
                     hwDevice->releaseAudioPatch(removedPatch.mHalHandle);
                 }
@@ -207,7 +185,7 @@
     switch (patch->sources[0].type) {
         case AUDIO_PORT_TYPE_DEVICE: {
             audio_module_handle_t srcModule = patch->sources[0].ext.device.hw_module;
-            AudioHwDevice *audioHwDevice = findAudioHwDeviceByModule(srcModule);
+            AudioHwDevice *audioHwDevice = findAudioHwDeviceByModule_l(srcModule);
             if (!audioHwDevice) {
                 status = BAD_VALUE;
                 goto exit;
@@ -249,8 +227,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 +236,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 +254,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 +262,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 +301,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,14 +310,14 @@
                                                                     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()));
-                status = newPatch.createConnections(this);
+                newPatch.mRecord.setThread(thread->asIAfRecordThread().get());
+                status = newPatch.createConnections_l(this);
                 if (status != NO_ERROR) {
                     goto exit;
                 }
@@ -348,10 +326,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 +338,9 @@
                             goto exit;
                         }
                     }
-                    mAudioFlinger.unlock();
+                    mAfPatchPanelCallback->mutex().unlock();
                     status = thread->sendCreateAudioPatchConfigEvent(patch, &halHandle);
-                    mAudioFlinger.lock();
+                    mAfPatchPanelCallback->mutex().lock();
                     if (status == NO_ERROR) {
                         newPatch.setThread(thread);
                     }
@@ -385,7 +364,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 +390,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 +402,13 @@
                     goto exit;
                 }
             }
-            if (thread == mAudioFlinger.primaryPlaybackThread_l()) {
-                mAudioFlinger.updateOutDevicesForRecordThreads_l(devices);
+            if (thread == mAfPatchPanelCallback->primaryPlaybackThread_l()) {
+                mAfPatchPanelCallback->updateOutDevicesForRecordThreads_l(devices);
             }
 
-            mAudioFlinger.unlock();
+            mAfPatchPanelCallback->mutex().unlock();
             status = thread->sendCreateAudioPatchConfigEvent(patch, &halHandle);
-            mAudioFlinger.lock();
+            mAfPatchPanelCallback->mutex().lock();
             if (status == NO_ERROR) {
                 newPatch.setThread(thread);
             }
@@ -453,29 +433,30 @@
 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);
+        mAfPatchPanelCallback->getPatchCommandThread()->createAudioPatch(*handle, newPatch);
         if (insertedModule != AUDIO_MODULE_HANDLE_NONE) {
-            addSoftwarePatchToInsertedModules(insertedModule, *handle, &newPatch.mAudioPatch);
+            addSoftwarePatchToInsertedModules_l(insertedModule, *handle, &newPatch.mAudioPatch);
         }
         mPatches.insert(std::make_pair(*handle, std::move(newPatch)));
     } else {
-        newPatch.clearConnections(this);
+        newPatch.clearConnections_l(this);
     }
     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_l(const sp<IAfPatchPanel>& panel)
 {
     // create patch from source device to record thread input
-    status_t status = panel->createAudioPatch(
+    status_t status = panel->createAudioPatch_l(
             PatchBuilder().addSource(mAudioPatch.sources[0]).
                 addSink(mRecord.thread(), { .source = AUDIO_SOURCE_MIC }).patch(),
             mRecord.handlePtr(),
@@ -487,7 +468,7 @@
 
     // create patch from playback thread output to sink device
     if (mAudioPatch.num_sinks != 0) {
-        status = panel->createAudioPatch(
+        status = panel->createAudioPatch_l(
                 PatchBuilder().addSource(mPlayback.thread()).addSink(mAudioPatch.sinks[0]).patch(),
                 mPlayback.handlePtr(),
                 true /*endpointPatch*/);
@@ -546,7 +527,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 +539,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 +558,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 +583,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,18 +617,18 @@
     return status;
 }
 
-void AudioFlinger::PatchPanel::Patch::clearConnections(PatchPanel *panel)
+void PatchPanel::Patch::clearConnections_l(const sp<IAfPatchPanel>& panel)
 {
     ALOGV("%s() mRecord.handle %d mPlayback.handle %d",
             __func__, mRecord.handle(), mPlayback.handle());
     mRecord.stopTrack();
     mPlayback.stopTrack();
     mRecord.clearTrackPeer(); // mRecord stop is synchronous. Break PeerProxy sp<> cycle.
-    mRecord.closeConnections(panel);
-    mPlayback.closeConnections(panel);
+    mRecord.closeConnections_l(panel);
+    mPlayback.closeConnections_l(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 +660,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 +687,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 +715,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_l(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
@@ -753,7 +734,7 @@
     const struct audio_port_config &src = patch.sources[0];
     switch (src.type) {
         case AUDIO_PORT_TYPE_DEVICE: {
-            sp<DeviceHalInterface> hwDevice = findHwDeviceByModule(src.ext.device.hw_module);
+            sp<DeviceHalInterface> hwDevice = findHwDeviceByModule_l(src.ext.device.hw_module);
             if (hwDevice == 0) {
                 ALOGW("%s() bad src hw module %d", __func__, src.ext.device.hw_module);
                 status = BAD_VALUE;
@@ -761,47 +742,47 @@
             }
 
             if (removedPatch.isSoftware()) {
-                removedPatch.clearConnections(this);
+                removedPatch.clearConnections_l(this);
                 break;
             }
 
             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->mutex().unlock();
                 status = thread->sendReleaseAudioPatchConfigEvent(removedPatch.mHalHandle);
-                mAudioFlinger.lock();
+                mAfPatchPanelCallback->mutex().lock();
             } else {
                 status = hwDevice->releaseAudioPatch(removedPatch.mHalHandle);
             }
         } break;
         case AUDIO_PORT_TYPE_MIX: {
-            if (findHwDeviceByModule(src.ext.mix.hw_module) == 0) {
+            if (findHwDeviceByModule_l(src.ext.mix.hw_module) == 0) {
                 ALOGW("%s() bad src hw module %d", __func__, src.ext.mix.hw_module);
                 status = BAD_VALUE;
                 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->mutex().unlock();
             status = thread->sendReleaseAudioPatchConfigEvent(removedPatch.mHalHandle);
-            mAudioFlinger.lock();
+            mAfPatchPanelCallback->mutex().lock();
         } break;
         default:
             status = BAD_VALUE;
@@ -811,23 +792,23 @@
     return status;
 }
 
-void AudioFlinger::PatchPanel::erasePatch(audio_patch_handle_t handle) {
+void PatchPanel::erasePatch(audio_patch_handle_t handle) {
     mPatches.erase(handle);
     removeSoftwarePatchFromInsertedModules(handle);
-    mAudioFlinger.mPatchCommandThread->releaseAudioPatch(handle);
+    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_l(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 +816,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 +831,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 +849,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_l(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_l(audio_module_handle_t module)
 {
-    AudioHwDevice *audioHwDevice = findAudioHwDeviceByModule(module);
+    AudioHwDevice *audioHwDevice = findAudioHwDeviceByModule_l(module);
     return audioHwDevice ? audioHwDevice->hwDevice() : nullptr;
 }
 
-void AudioFlinger::PatchPanel::addSoftwarePatchToInsertedModules(
+void PatchPanel::addSoftwarePatchToInsertedModules_l(
         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 +891,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 5555766..1ff8fff 100644
--- a/services/audioflinger/PatchPanel.h
+++ b/services/audioflinger/PatchPanel.h
@@ -15,228 +15,77 @@
 ** 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"
 
-// PatchPanel is concealed within AudioFlinger, their lifetimes are the same.
-class PatchPanel {
+#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);
+    status_t listAudioPorts_l(unsigned int *num_ports,
+            struct audio_port* ports) final REQUIRES(audio_utils::AudioFlinger_Mutex);
 
     /* Get supported attributes for a given audio port */
-    status_t getAudioPort(struct audio_port_v7 *port);
+    status_t getAudioPort_l(struct audio_port_v7* port) final
+            REQUIRES(audio_utils::AudioFlinger_Mutex);
 
     /* Create a patch between several source and sink ports */
-    status_t createAudioPatch(const struct audio_patch *patch,
+    status_t createAudioPatch_l(const struct audio_patch *patch,
                               audio_patch_handle_t *handle,
-                              bool endpointPatch = false);
+                              bool endpointPatch = false) final
+            REQUIRES(audio_utils::AudioFlinger_Mutex);
 
     /* Release a patch */
-    status_t releaseAudioPatch(audio_patch_handle_t handle);
+    status_t releaseAudioPatch_l(audio_patch_handle_t handle) final
+            REQUIRES(audio_utils::AudioFlinger_Mutex);
 
     /* List connected audio devices and they attributes */
-    status_t listAudioPatches(unsigned int *num_patches,
-                                      struct audio_patch *patches);
+    status_t listAudioPatches_l(unsigned int *num_patches,
+            struct audio_patch* patches) final
+            REQUIRES(audio_utils::AudioFlinger_Mutex);
 
-    // Retrieves all currently estrablished software patches for a stream
+    // Retrieves all currently established 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;
+    void dump(int fd) const final;
 
-    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);
-        }
+    const std::map<audio_patch_handle_t, Patch>& patches_l() const final
+            REQUIRES(audio_utils::AudioFlinger_Mutex) { return mPatches; }
 
-        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; }
+    status_t getLatencyMs_l(audio_patch_handle_t patchHandle, double* latencyMs) const final
+            REQUIRES(audio_utils::AudioFlinger_Mutex);
 
-        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;
-    };
-
-    // Call with AudioFlinger mLock held
-    std::map<audio_patch_handle_t, Patch>& patches_l() { return mPatches; }
+    void closeThreadInternal_l(const sp<IAfThreadBase>& thread) const final
+            REQUIRES(audio_utils::AudioFlinger_Mutex);
 
 private:
-    AudioHwDevice* findAudioHwDeviceByModule(audio_module_handle_t module);
-    sp<DeviceHalInterface> findHwDeviceByModule(audio_module_handle_t module);
-    void addSoftwarePatchToInsertedModules(
+    AudioHwDevice* findAudioHwDeviceByModule_l(audio_module_handle_t module)
+            REQUIRES(audio_utils::AudioFlinger_Mutex);
+    sp<DeviceHalInterface> findHwDeviceByModule_l(audio_module_handle_t module)
+            REQUIRES(audio_utils::AudioFlinger_Mutex);
+    void addSoftwarePatchToInsertedModules_l(
             audio_module_handle_t module, audio_patch_handle_t handle,
-            const struct audio_patch *patch);
+            const struct audio_patch *patch)
+            REQUIRES(audio_utils::AudioFlinger_Mutex);
     void removeSoftwarePatchFromInsertedModules(audio_patch_handle_t handle);
     void erasePatch(audio_patch_handle_t handle);
 
-    AudioFlinger &mAudioFlinger;
+    const sp<IAfPatchPanelCallback> mAfPatchPanelCallback;
     std::map<audio_patch_handle_t, Patch> mPatches;
 
     // This map allows going from a thread to "downstream" software patches
@@ -265,3 +114,5 @@
     };
     std::map<audio_module_handle_t, ModuleConnections> mInsertedModules;
 };
+
+}  // namespace android
diff --git a/services/audioflinger/PlaybackTracks.h b/services/audioflinger/PlaybackTracks.h
index 464940e..15e85f9 100644
--- a/services/audioflinger/PlaybackTracks.h
+++ b/services/audioflinger/PlaybackTracks.h
@@ -15,12 +15,16 @@
 ** 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/mutex.h>
+#include <audio_utils/LinearMap.h>
+#include <binder/AppOpsManager.h>
+
+namespace android {
 
 // Checks and monitors OP_PLAY_AUDIO
 class OpPlayAudioMonitor : public RefBase {
@@ -30,13 +34,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 +61,7 @@
     // called by PlayAudioOpCallback when OP_PLAY_AUDIO is updated in AppOp callback
     void checkPlayAudioForUsage(bool doBroadcast);
 
-    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,9 +71,9 @@
 };
 
 // playback track
-class Track : public TrackBase, public VolumeProvider {
+class Track : public TrackBase, public virtual IAfTrack, public VolumeProvider {
 public:
-                        Track(  PlaybackThread *thread,
+    Track(IAfPlaybackThread* thread,
                                 const sp<Client>& client,
                                 audio_stream_type_t streamType,
                                 const audio_attributes_t& attr,
@@ -92,72 +96,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;
     }
@@ -165,21 +163,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);
@@ -188,16 +187,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();
-            void    setTeePatchesToUpdate(TeePatches teePatchesToUpdate);
+    void updateTeePatches() final;
+    void setTeePatchesToUpdate(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
@@ -208,29 +207,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);
 
@@ -239,38 +227,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;
     }
@@ -281,25 +270,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;
@@ -377,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;
@@ -391,7 +398,7 @@
 
 
 // playback track, used by DuplicatingThread
-class OutputTrack : public Track {
+class OutputTrack : public Track, public IAfOutputTrack {
 public:
 
     class Buffer : public AudioBufferProvider::Buffer {
@@ -399,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;
@@ -432,7 +438,6 @@
                             // (with mTimeNs[] filled with -1's) is returned.
                             return timestamp;
                         }
-
 private:
     status_t            obtainBuffer(AudioBufferProvider::Buffer* buffer,
                                      uint32_t waitTimeMs);
@@ -447,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.
@@ -463,14 +468,14 @@
      */
     SourceMetadatas mTrackMetadatas;
     /** Protects mTrackMetadatas against concurrent access. */
-    mutable std::mutex mTrackMetadatasMutex;
+    audio_utils::mutex& trackMetadataMutex() const { return mTrackMetadataMutex; }
+    mutable audio_utils::mutex mTrackMetadataMutex;
 };  // 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,
@@ -484,23 +489,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 d91a210..8d3de38 100644
--- a/services/audioflinger/RecordTracks.h
+++ b/services/audioflinger/RecordTracks.h
@@ -15,16 +15,20 @@
 ** 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 <audio_utils/mutex.h>
+#include <datapath/AudioStreamIn.h> // struct Source
+
+namespace android {
 
 // record track
-class RecordTrack : public TrackBase {
+class RecordTrack : public TrackBase, public virtual IAfRecordTrack {
 public:
-                        RecordTrack(RecordThread *thread,
+    RecordTrack(IAfRecordThread* thread,
                                 const sp<Client>& client,
                                 const audio_attributes_t& attr,
                                 uint32_t sampleRate,
@@ -40,67 +44,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
@@ -113,7 +120,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;
@@ -126,10 +133,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,
@@ -139,20 +145,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);
     }
 
@@ -165,7 +171,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,
@@ -173,25 +179,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
@@ -208,15 +214,18 @@
         PassthruPatchRecord& mPassthru;
     };
 
-    sp<StreamInHalInterface> obtainStream(sp<ThreadBase>* thread);
+    sp<StreamInHalInterface> obtainStream(sp<IAfThreadBase>* thread);
+    audio_utils::mutex& readMutex() const { return mReadMutex; }
 
     PatchRecordAudioBufferProvider mPatchRecordAudioBufferProvider;
     std::unique_ptr<void, decltype(free)*> mSinkBuffer;  // frame size aligned continuous buffer
     std::unique_ptr<void, decltype(free)*> mStubBuffer;  // buffer used for AudioBufferProvider
     size_t mUnconsumedFrames = 0;
-    std::mutex mReadLock;
-    std::condition_variable mReadCV;
-    size_t mReadBytes = 0; // GUARDED_BY(mReadLock)
-    status_t mReadError = NO_ERROR; // GUARDED_BY(mReadLock)
+    mutable audio_utils::mutex mReadMutex;
+    audio_utils::condition_variable mReadCV;
+    size_t mReadBytes = 0; // GUARDED_BY(readMutex())
+    status_t mReadError = NO_ERROR; // GUARDED_BY(readMutex())
     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 1530697..d971da0 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
@@ -605,26 +685,26 @@
         //      mWaitWorkCV.wait(...);
         //      // now thread is hung
         //  }
-        AutoMutex lock(mLock);
+        audio_utils::lock_guard lock(mutex());
         requestExit();
-        mWaitWorkCV.broadcast();
+        mWaitWorkCV.notify_all();
     }
     // When Thread::requestExitAndWait is made virtual and this method is renamed to
     // "virtual status_t requestExitAndWait()", replace by "return Thread::requestExitAndWait();"
     requestExitAndWait();
 }
 
-status_t AudioFlinger::ThreadBase::setParameters(const String8& keyValuePairs)
+status_t ThreadBase::setParameters(const String8& keyValuePairs)
 {
     ALOGV("ThreadBase::setParameters() %s", keyValuePairs.c_str());
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mutex());
 
     return sendSetParameterConfigEvent_l(keyValuePairs);
 }
 
 // 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;
@@ -636,31 +716,32 @@
     }
     mConfigEvents.add(event);
     ALOGV("sendConfigEvent_l() num events %zu event %d", mConfigEvents.size(), event->mType);
-    mWaitWorkCV.signal();
-    mLock.unlock();
+    mWaitWorkCV.notify_one();
+    mutex().unlock();
     {
-        Mutex::Autolock _l(event->mLock);
+        audio_utils::unique_lock _l(event->mutex());
         while (event->mWaitStatus) {
-            if (event->mCond.waitRelative(event->mLock, kConfigEventTimeoutNs) != NO_ERROR) {
+            if (event->mCondition.wait_for(_l, std::chrono::nanoseconds(kConfigEventTimeoutNs))
+                        == std::cv_status::timeout) {
                 event->mStatus = TIMED_OUT;
                 event->mWaitStatus = false;
             }
         }
         status = event->mStatus;
     }
-    mLock.lock();
+    mutex().lock();
     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);
+    audio_utils::lock_guard _l(mutex());
     sendIoConfigEvent_l(event, pid, portId);
 }
 
-// sendIoConfigEvent_l() must be called with ThreadBase::mLock held
-void AudioFlinger::ThreadBase::sendIoConfigEvent_l(audio_io_config_event_t event, pid_t pid,
+// sendIoConfigEvent_l() must be called with ThreadBase::mutex() held
+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,22 +758,22 @@
     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);
+    audio_utils::lock_guard _l(mutex());
     sendPrioConfigEvent_l(pid, tid, prio, forApp);
 }
 
-// sendPrioConfigEvent_l() must be called with ThreadBase::mLock held
-void AudioFlinger::ThreadBase::sendPrioConfigEvent_l(
+// sendPrioConfigEvent_l() must be called with ThreadBase::mutex() held
+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);
     sendConfigEvent_l(configEvent);
 }
 
-// sendSetParameterConfigEvent_l() must be called with ThreadBase::mLock held
-status_t AudioFlinger::ThreadBase::sendSetParameterConfigEvent_l(const String8& keyValuePair)
+// sendSetParameterConfigEvent_l() must be called with ThreadBase::mutex() held
+status_t ThreadBase::sendSetParameterConfigEvent_l(const String8& keyValuePair)
 {
     sp<ConfigEvent> configEvent;
     AudioParameter param(keyValuePair);
@@ -710,11 +791,11 @@
     return sendConfigEvent_l(configEvent);
 }
 
-status_t AudioFlinger::ThreadBase::sendCreateAudioPatchConfigEvent(
+status_t ThreadBase::sendCreateAudioPatchConfigEvent(
                                                         const struct audio_patch *patch,
                                                         audio_patch_handle_t *handle)
 {
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mutex());
     sp<ConfigEvent> configEvent = (ConfigEvent *)new CreateAudioPatchConfigEvent(*patch, *handle);
     status_t status = sendConfigEvent_l(configEvent);
     if (status == NO_ERROR) {
@@ -725,27 +806,27 @@
     return status;
 }
 
-status_t AudioFlinger::ThreadBase::sendReleaseAudioPatchConfigEvent(
+status_t ThreadBase::sendReleaseAudioPatchConfigEvent(
                                                                 const audio_patch_handle_t handle)
 {
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mutex());
     sp<ConfigEvent> configEvent = (ConfigEvent *)new ReleaseAudioPatchConfigEvent(handle);
     return sendConfigEvent_l(configEvent);
 }
 
-status_t AudioFlinger::ThreadBase::sendUpdateOutDeviceConfigEvent(
+status_t ThreadBase::sendUpdateOutDeviceConfigEvent(
         const DeviceDescriptorBaseVector& outDevices)
 {
     if (type() != RECORD) {
         // The update out device operation is only for record thread.
         return INVALID_OPERATION;
     }
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mutex());
     sp<ConfigEvent> configEvent = (ConfigEvent *)new UpdateOutDevicesConfigEvent(outDevices);
     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 +834,27 @@
     sendConfigEvent_l(configEvent);
 }
 
-void AudioFlinger::ThreadBase::sendCheckOutputStageEffectsEvent()
+void ThreadBase::sendCheckOutputStageEffectsEvent()
 {
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mutex());
     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;
 
@@ -850,10 +931,10 @@
             break;
         }
         {
-            Mutex::Autolock _l(event->mLock);
+            audio_utils::lock_guard _l(event->mutex());
             if (event->mWaitStatus) {
                 event->mWaitStatus = false;
-                event->mCond.signal();
+                event->mCondition.notify_one();
             }
         }
         ALOGV_IF(mConfigEvents.isEmpty(), "processConfigEvents_l() DONE thread %p", this);
@@ -940,13 +1021,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(mutex());
     if (!locked) {
         dprintf(fd, "  Thread may be deadlocked\n");
     }
@@ -957,7 +1038,7 @@
     dumpEffectChains_l(fd, args);
 
     if (locked) {
-        mLock.unlock();
+        mutex().unlock();
     }
 
     dprintf(fd, "  Local log:\n");
@@ -978,18 +1059,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).c_str());
-    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 +1134,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];
@@ -1061,20 +1144,20 @@
     write(fd, buffer, strlen(buffer));
 
     for (size_t i = 0; i < numEffectChains; ++i) {
-        sp<EffectChain> chain = mEffectChains[i];
+        sp<IAfEffectChain> chain = mEffectChains[i];
         if (chain != 0) {
             chain->dump(fd, args);
         }
     }
 }
 
-void AudioFlinger::ThreadBase::acquireWakeLock()
+void ThreadBase::acquireWakeLock()
 {
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mutex());
     acquireWakeLock_l();
 }
 
-String16 AudioFlinger::ThreadBase::getWakeLockTag()
+String16 ThreadBase::getWakeLockTag()
 {
     switch (mType) {
     case MIXER:
@@ -1099,7 +1182,7 @@
     }
 }
 
-void AudioFlinger::ThreadBase::acquireWakeLock_l()
+void ThreadBase::acquireWakeLock_l()
 {
     getPowerManager_l();
     if (mPowerManager != 0) {
@@ -1122,13 +1205,13 @@
             gBoottime.getBoottimeOffset();
 }
 
-void AudioFlinger::ThreadBase::releaseWakeLock()
+void ThreadBase::releaseWakeLock()
 {
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mutex());
     releaseWakeLock_l();
 }
 
-void AudioFlinger::ThreadBase::releaseWakeLock_l()
+void ThreadBase::releaseWakeLock_l()
 {
     gBoottime.release(mWakeLockToken);
     if (mWakeLockToken != 0) {
@@ -1140,7 +1223,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 +1237,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 +1264,25 @@
     }
 }
 
-void AudioFlinger::ThreadBase::clearPowerManager()
+void ThreadBase::clearPowerManager()
 {
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mutex());
     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,10 +1291,10 @@
     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<EffectChain> chain = getEffectChain_l(sessionId);
+    sp<IAfEffectChain> chain = getEffectChain_l(sessionId);
     if (chain != 0) {
         if (type != NULL) {
             chain->setEffectSuspended_l(type, suspend);
@@ -1223,7 +1306,7 @@
     updateSuspendedSessions_l(type, suspend, sessionId);
 }
 
-void AudioFlinger::ThreadBase::checkSuspendOnAddEffectChain_l(const sp<EffectChain>& chain)
+void ThreadBase::checkSuspendOnAddEffectChain_l(const sp<IAfEffectChain>& chain)
 {
     ssize_t index = mSuspendedSessions.indexOfKey(chain->sessionId());
     if (index < 0) {
@@ -1236,7 +1319,7 @@
     for (size_t i = 0; i < sessionEffects.size(); i++) {
         const sp<SuspendedSessionDesc>& desc = sessionEffects.valueAt(i);
         for (int j = 0; j < desc->mRefCount; j++) {
-            if (sessionEffects.keyAt(i) == EffectChain::kKeyForSuspendAll) {
+            if (sessionEffects.keyAt(i) == IAfEffectChain::kKeyForSuspendAll) {
                 chain->setEffectSuspendedAll_l(true);
             } else {
                 ALOGV("checkSuspendOnAddEffectChain_l() suspending effects %08x",
@@ -1247,7 +1330,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)
 {
@@ -1269,7 +1352,7 @@
     }
 
 
-    int key = EffectChain::kKeyForSuspendAll;
+    int key = IAfEffectChain::kKeyForSuspendAll;
     if (type != NULL) {
         key = type->timeLow;
     }
@@ -1308,13 +1391,13 @@
     }
 }
 
-void AudioFlinger::ThreadBase::checkSuspendOnEffectEnabled(bool enabled,
+void ThreadBase::checkSuspendOnEffectEnabled(bool enabled,
                                                            audio_session_t sessionId,
                                                            bool threadLocked)
 NO_THREAD_SAFETY_ANALYSIS  // manual locking
 {
     if (!threadLocked) {
-        mLock.lock();
+        mutex().lock();
     }
 
     if (mType != RECORD) {
@@ -1329,12 +1412,12 @@
     }
 
     if (!threadLocked) {
-        mLock.unlock();
+        mutex().unlock();
     }
 }
 
-// checkEffectCompatibility_l() must be called with ThreadBase::mLock held
-status_t AudioFlinger::RecordThread::checkEffectCompatibility_l(
+// checkEffectCompatibility_l() must be called with ThreadBase::mutex() held
+status_t RecordThread::checkEffectCompatibility_l(
         const effect_descriptor_t *desc, audio_session_t sessionId)
 {
     // No global output effect sessions on record threads
@@ -1370,15 +1453,15 @@
         }
     }
 
-    if (EffectModule::isHapticGenerator(&desc->type)) {
+    if (IAfEffectModule::isHapticGenerator(&desc->type)) {
         ALOGE("%s(): HapticGenerator is not supported in RecordThread", __func__);
         return BAD_VALUE;
     }
     return NO_ERROR;
 }
 
-// checkEffectCompatibility_l() must be called with ThreadBase::mLock held
-status_t AudioFlinger::PlaybackThread::checkEffectCompatibility_l(
+// checkEffectCompatibility_l() must be called with ThreadBase::mutex() held
+status_t PlaybackThread::checkEffectCompatibility_l(
         const effect_descriptor_t *desc, audio_session_t sessionId)
 {
     // no preprocessing on playback threads
@@ -1393,7 +1476,7 @@
         return NO_ERROR;
     }
 
-    if (EffectModule::isHapticGenerator(&desc->type) && mHapticChannelCount == 0) {
+    if (IAfEffectModule::isHapticGenerator(&desc->type) && mHapticChannelCount == 0) {
         ALOGW("%s: thread doesn't support haptic playback while the effect is HapticGenerator",
                 __func__);
         return BAD_VALUE;
@@ -1532,9 +1615,9 @@
     return NO_ERROR;
 }
 
-// ThreadBase::createEffect_l() must be called with AudioFlinger::mLock held
-sp<AudioFlinger::EffectHandle> AudioFlinger::ThreadBase::createEffect_l(
-        const sp<AudioFlinger::Client>& client,
+// ThreadBase::createEffect_l() must be called with AudioFlinger::mutex() held
+sp<IAfEffectHandle> ThreadBase::createEffect_l(
+        const sp<Client>& client,
         const sp<IEffectClient>& effectClient,
         int32_t priority,
         audio_session_t sessionId,
@@ -1545,10 +1628,10 @@
         bool probe,
         bool notifyFramesProcessed)
 {
-    sp<EffectModule> effect;
-    sp<EffectHandle> handle;
+    sp<IAfEffectModule> effect;
+    sp<IAfEffectHandle> handle;
     status_t lStatus;
-    sp<EffectChain> chain;
+    sp<IAfEffectChain> chain;
     bool chainCreated = false;
     bool effectCreated = false;
     audio_unique_id_t effectId = AUDIO_UNIQUE_ID_USE_UNSPECIFIED;
@@ -1561,8 +1644,8 @@
 
     ALOGV("createEffect_l() thread %p effect %s on session %d", this, desc->name, sessionId);
 
-    { // scope for mLock
-        Mutex::Autolock _l(mLock);
+    { // scope for mutex()
+        audio_utils::lock_guard _l(mutex());
 
         lStatus = checkEffectCompatibility_l(desc, sessionId);
         if (probe || lStatus != NO_ERROR) {
@@ -1574,7 +1657,7 @@
         if (chain == 0) {
             // create a new chain for this session
             ALOGV("createEffect_l() new effect chain for session %d", sessionId);
-            chain = new EffectChain(this, sessionId);
+            chain = IAfEffectChain::create(this, sessionId);
             addEffectChain_l(chain);
             chain->setStrategy(getStrategyForSession_l(sessionId));
             chainCreated = true;
@@ -1585,7 +1668,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,21 +1679,22 @@
             // 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);
             }
         }
         // create effect handle and connect it to effect module
-        handle = new EffectHandle(effect, client, effectClient, priority, notifyFramesProcessed);
+        handle = IAfEffectHandle::create(
+                effect, client, effectClient, priority, notifyFramesProcessed);
         lStatus = handle->initCheck();
         if (lStatus == OK) {
             lStatus = effect->addHandle(handle.get());
@@ -1623,7 +1707,7 @@
 
 Exit:
     if (!probe && lStatus != NO_ERROR && lStatus != ALREADY_EXISTS) {
-        Mutex::Autolock _l(mLock);
+        audio_utils::lock_guard _l(mutex());
         if (effectCreated) {
             chain->removeEffect_l(effect);
         }
@@ -1637,14 +1721,14 @@
     return handle;
 }
 
-void AudioFlinger::ThreadBase::disconnectEffectHandle(EffectHandle *handle,
+void ThreadBase::disconnectEffectHandle(IAfEffectHandle* handle,
                                                       bool unpinIfLast)
 {
     bool remove = false;
-    sp<EffectModule> effect;
+    sp<IAfEffectModule> effect;
     {
-        Mutex::Autolock _l(mLock);
-        sp<EffectBase> effectBase = handle->effect().promote();
+        audio_utils::lock_guard _l(mutex());
+        sp<IAfEffectBase> effectBase = handle->effect().promote();
         if (effectBase == nullptr) {
             return;
         }
@@ -1660,16 +1744,16 @@
         sendCheckOutputStageEffectsEvent_l();
     }
     if (remove) {
-        mAudioFlinger->updateOrphanEffectChains(effect);
+        mAfThreadCallback->updateOrphanEffectChains(effect);
         if (handle->enabled()) {
             effect->checkSuspendOnEffectEnabled(false, false /*threadLocked*/);
         }
     }
 }
 
-void AudioFlinger::ThreadBase::onEffectEnable(const sp<EffectModule>& effect) {
+void ThreadBase::onEffectEnable(const sp<IAfEffectModule>& effect) {
     if (isOffloadOrMmap()) {
-        Mutex::Autolock _l(mLock);
+        audio_utils::lock_guard _l(mutex());
         broadcast_l();
     }
     if (!effect->isOffloadable()) {
@@ -1678,64 +1762,64 @@
             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);
+        audio_utils::lock_guard _l(mutex());
         broadcast_l();
     }
 }
 
-sp<AudioFlinger::EffectModule> AudioFlinger::ThreadBase::getEffect(audio_session_t sessionId,
-        int effectId)
+sp<IAfEffectModule> ThreadBase::getEffect(audio_session_t sessionId,
+        int effectId) const
 {
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mutex());
     return getEffect_l(sessionId, effectId);
 }
 
-sp<AudioFlinger::EffectModule> AudioFlinger::ThreadBase::getEffect_l(audio_session_t sessionId,
-        int effectId)
+sp<IAfEffectModule> ThreadBase::getEffect_l(audio_session_t sessionId,
+        int effectId) const
 {
-    sp<EffectChain> chain = getEffectChain_l(sessionId);
+    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<EffectChain> chain = getEffectChain_l(sessionId);
+    sp<IAfEffectChain> chain = getEffectChain_l(sessionId);
     return chain != nullptr ? chain->getEffectIds() : std::vector<int>{};
 }
 
-// PlaybackThread::addEffect_l() must be called with AudioFlinger::mLock and
-// PlaybackThread::mLock held
-status_t AudioFlinger::ThreadBase::addEffect_l(const sp<EffectModule>& effect)
+// PlaybackThread::addEffect_ll() must be called with AudioFlinger::mutex() and
+// ThreadBase::mutex() held
+status_t ThreadBase::addEffect_ll(const sp<IAfEffectModule>& effect)
 {
     // check for existing effect chain with the requested audio session
     audio_session_t sessionId = effect->sessionId();
-    sp<EffectChain> chain = getEffectChain_l(sessionId);
+    sp<IAfEffectChain> chain = getEffectChain_l(sessionId);
     bool chainCreated = false;
 
     ALOGD_IF((mType == OFFLOAD) && !effect->isOffloadable(),
-             "addEffect_l() on offloaded thread %p: effect %s does not support offload flags %#x",
-                    this, effect->desc().name, effect->desc().flags);
+             "%s: on offloaded thread %p: effect %s does not support offload flags %#x",
+             __func__, this, effect->desc().name, effect->desc().flags);
 
     if (chain == 0) {
         // create a new chain for this session
-        ALOGV("addEffect_l() new effect chain for session %d", sessionId);
-        chain = new EffectChain(this, sessionId);
+        ALOGV("%s: new effect chain for session %d", __func__, sessionId);
+        chain = IAfEffectChain::create(this, sessionId);
         addEffectChain_l(chain);
         chain->setStrategy(getStrategyForSession_l(sessionId));
         chainCreated = true;
     }
-    ALOGV("addEffect_l() %p chain %p effect %p", this, chain.get(), effect.get());
+    ALOGV("%s: %p chain %p effect %p", __func__, this, chain.get(), effect.get());
 
     if (chain->getEffectFromId_l(effect->id()) != 0) {
-        ALOGW("addEffect_l() %p effect %s already present in chain %p",
-                this, effect->desc().name, chain.get());
+        ALOGW("%s: %p effect %s already present in chain %p",
+                __func__, this, effect->desc().name, chain.get());
         return BAD_VALUE;
     }
 
@@ -1751,13 +1835,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<EffectModule>& 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();
@@ -1765,7 +1849,7 @@
         detachAuxEffect_l(effect->id());
     }
 
-    sp<EffectChain> chain = effect->getCallback()->chain().promote();
+    sp<IAfEffectChain> chain = effect->getCallback()->chain().promote();
     if (chain != 0) {
         // remove effect chain if removing last effect
         if (chain->removeEffect_l(effect, release) == 0) {
@@ -1776,32 +1860,32 @@
     }
 }
 
-void AudioFlinger::ThreadBase::lockEffectChains_l(
-        Vector< sp<AudioFlinger::EffectChain> >& effectChains)
+void ThreadBase::lockEffectChains_l(
+        Vector<sp<IAfEffectChain>>& effectChains)
 NO_THREAD_SAFETY_ANALYSIS  // calls EffectChain::lock()
 {
     effectChains = mEffectChains;
     for (size_t i = 0; i < mEffectChains.size(); i++) {
-        mEffectChains[i]->lock();
+        mEffectChains[i]->mutex().lock();
     }
 }
 
-void AudioFlinger::ThreadBase::unlockEffectChains(
-        const Vector< sp<AudioFlinger::EffectChain> >& effectChains)
+void ThreadBase::unlockEffectChains(
+        const Vector<sp<IAfEffectChain>>& effectChains)
 NO_THREAD_SAFETY_ANALYSIS  // calls EffectChain::unlock()
 {
     for (size_t i = 0; i < effectChains.size(); i++) {
-        effectChains[i]->unlock();
+        effectChains[i]->mutex().unlock();
     }
 }
 
-sp<AudioFlinger::EffectChain> AudioFlinger::ThreadBase::getEffectChain(audio_session_t sessionId)
+sp<IAfEffectChain> ThreadBase::getEffectChain(audio_session_t sessionId) const
 {
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mutex());
     return getEffectChain_l(sessionId);
 }
 
-sp<AudioFlinger::EffectChain> AudioFlinger::ThreadBase::getEffectChain_l(audio_session_t sessionId)
+sp<IAfEffectChain> ThreadBase::getEffectChain_l(audio_session_t sessionId)
         const
 {
     size_t size = mEffectChains.size();
@@ -1813,16 +1897,16 @@
     return 0;
 }
 
-void AudioFlinger::ThreadBase::setMode(audio_mode_t mode)
+void ThreadBase::setMode(audio_mode_t mode)
 {
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mutex());
     size_t size = mEffectChains.size();
     for (size_t i = 0; i < size; i++) {
         mEffectChains[i]->setMode_l(mode);
     }
 }
 
-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;
@@ -1833,9 +1917,9 @@
                             AUDIO_PORT_CONFIG_FORMAT;
 }
 
-void AudioFlinger::ThreadBase::systemReady()
+void ThreadBase::systemReady()
 {
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mutex());
     if (mSystemReady) {
         return;
     }
@@ -1848,7 +1932,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());
@@ -1863,7 +1947,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());
@@ -1882,7 +1966,7 @@
 }
 
 template <typename T>
-void AudioFlinger::ThreadBase::ActiveTracks<T>::clear() {
+void ThreadBase::ActiveTracks<T>::clear() {
     for (const sp<T> &track : mActiveTracks) {
         BatteryNotifier::getInstance().noteStopAudio(track->uid());
         logTrack("clear", track);
@@ -1895,7 +1979,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) {
@@ -1926,7 +2010,7 @@
 }
 
 template <typename T>
-bool AudioFlinger::ThreadBase::ActiveTracks<T>::readAndClearHasChanged() {
+bool ThreadBase::ActiveTracks<T>::readAndClearHasChanged() {
     bool hasChanged = mHasChanged;
     mHasChanged = false;
 
@@ -1939,7 +2023,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;
@@ -1948,19 +2032,19 @@
     }
 }
 
-void AudioFlinger::ThreadBase::broadcast_l()
+void ThreadBase::broadcast_l()
 {
     // Thread could be blocked waiting for async
     // so signal it to handle state changes immediately
     // If threadLoop is currently unlocked a signal of mWaitWorkCV will
     // be lost so we also flag to prevent it blocking on mWaitWorkCV
     mSignalPending = true;
-    mWaitWorkCV.broadcast();
+    mWaitWorkCV.notify_all();
 }
 
 // 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.
@@ -2023,24 +2107,24 @@
     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(
+// startMelComputation_l() must be called with AudioFlinger::mutex() held
+void ThreadBase::startMelComputation_l(
         const sp<audio_utils::MelProcessor>& /*processor*/)
 {
     // Do nothing
     ALOGW("%s: ThreadBase does not support CSD", __func__);
 }
 
-// stopMelComputation_l() must be called with AudioFlinger::mLock held
-void AudioFlinger::ThreadBase::stopMelComputation_l()
+// stopMelComputation_l() must be called with AudioFlinger::mutex() held
+void ThreadBase::stopMelComputation_l()
 {
     // Do nothing
     ALOGW("%s: ThreadBase does not support CSD", __func__);
@@ -2050,20 +2134,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),
@@ -2078,13 +2162,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),
@@ -2093,17 +2177,17 @@
         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
+    // Assumes constructor is called by AudioFlinger with its mutex() held, but
     // it would be safer to explicitly pass initial masterVolume/masterMute as
     // parameter.
     //
     // 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;
@@ -2141,7 +2225,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;
@@ -2150,9 +2234,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);
@@ -2161,7 +2245,7 @@
 
 // Thread virtuals
 
-void AudioFlinger::PlaybackThread::onFirstRef()
+void PlaybackThread::onFirstRef()
 {
     if (!isStreamInitialized()) {
         ALOGE("The stream is not open yet"); // This should not happen.
@@ -2176,7 +2260,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) {
@@ -2188,14 +2272,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;
 
@@ -2229,7 +2313,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) {
@@ -2249,7 +2333,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 */);
@@ -2260,7 +2344,7 @@
     write(fd, result.c_str(), 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");
@@ -2295,9 +2379,9 @@
     }
 }
 
-// PlaybackThread::createTrack_l() must be called with AudioFlinger::mLock held
-sp<AudioFlinger::PlaybackThread::Track> AudioFlinger::PlaybackThread::createTrack_l(
-        const sp<AudioFlinger::Client>& client,
+// PlaybackThread::createTrack_l() must be called with AudioFlinger::mutex() held
+sp<IAfTrack> PlaybackThread::createTrack_l(
+        const sp<Client>& client,
         audio_stream_type_t streamType,
         const audio_attributes_t& attr,
         uint32_t *pSampleRate,
@@ -2321,7 +2405,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;
@@ -2350,7 +2434,7 @@
     }
 
     if (isBitPerfect) {
-        sp<EffectChain> chain = getEffectChain_l(sessionId);
+        sp<IAfEffectChain> chain = getEffectChain_l(sessionId);
         if (chain.get() != nullptr) {
             // Bit-perfect is required according to the configuration and preferred mixer
             // attributes, but it is not in the output flag from the client's request. Explicitly
@@ -2399,15 +2483,15 @@
         }
 
         // check compatibility with audio effects.
-        { // scope for mLock
-            Mutex::Autolock _l(mLock);
+        { // scope for mutex()
+            audio_utils::lock_guard _l(mutex());
             for (audio_session_t session : {
                     AUDIO_SESSION_DEVICE,
                     AUDIO_SESSION_OUTPUT_STAGE,
                     AUDIO_SESSION_OUTPUT_MIX,
                     sessionId,
                 }) {
-                sp<EffectChain> chain = getEffectChain_l(session);
+                sp<IAfEffectChain> chain = getEffectChain_l(session);
                 if (chain.get() != nullptr) {
                     audio_output_flags_t old = *flags;
                     chain->checkOutputFlagCompatibility(flags);
@@ -2606,15 +2690,15 @@
         goto Exit;
     }
 
-    { // scope for mLock
-        Mutex::Autolock _l(mLock);
+    { // scope for mutex()
+        audio_utils::lock_guard _l(mutex());
 
         // all tracks in same audio session must share the same routing strategy otherwise
         // conflicts will happen when tracks are moved from one output to another by audio policy
         // 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) {
@@ -2636,11 +2720,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;
@@ -2651,13 +2735,13 @@
         }
         mTracks.add(track);
         {
-            Mutex::Autolock _atCbL(mAudioTrackCbLock);
+            audio_utils::lock_guard _atCbL(audioTrackCbMutex());
             if (callback.get() != nullptr) {
                 mAudioTrackCallbacks.emplace(track, callback);
             }
         }
 
-        sp<EffectChain> chain = getEffectChain_l(sessionId);
+        sp<IAfEffectChain> chain = getEffectChain_l(sessionId);
         if (chain != 0) {
             ALOGV("createTrack_l() setting main buffer %p", chain->inBuffer());
             track->setMainBuffer(chain->inBuffer());
@@ -2681,7 +2765,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);
@@ -2696,17 +2780,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);
+    audio_utils::lock_guard _l(mutex());
     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) {
@@ -2715,9 +2799,9 @@
     return 0;
 }
 
-void AudioFlinger::PlaybackThread::setMasterVolume(float value)
+void PlaybackThread::setMasterVolume(float value)
 {
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mutex());
     // Don't apply master volume in SW if our HAL can do it for us.
     if (mOutput && mOutput->audioHwDev &&
         mOutput->audioHwDev->canSetMasterVolume()) {
@@ -2727,17 +2811,17 @@
     }
 }
 
-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;
     }
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mutex());
     // Don't apply master mute in SW if our HAL can do it for us.
     if (mOutput && mOutput->audioHwDev &&
         mOutput->audioHwDev->canSetMasterMute()) {
@@ -2747,34 +2831,34 @@
     }
 }
 
-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);
+    audio_utils::lock_guard _l(mutex());
     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);
+    audio_utils::lock_guard _l(mutex());
     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);
+    audio_utils::lock_guard _l(mutex());
     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)
-NO_THREAD_SAFETY_ANALYSIS  // release and re-acquire mLock
+// addTrack_l() must be called with ThreadBase::mutex() held
+status_t PlaybackThread::addTrack_l(const sp<IAfTrack>& track)
+NO_THREAD_SAFETY_ANALYSIS  // release and re-acquire mutex()
 {
     status_t status = ALREADY_EXISTS;
 
@@ -2783,16 +2867,16 @@
         // 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;
-            mLock.unlock();
+            IAfTrackBase::track_state state = track->state();
+            mutex().unlock();
             status = AudioSystem::startOutput(track->portId());
-            mLock.lock();
+            mutex().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();
+                    mutex().unlock();
                     AudioSystem::stopOutput(track->portId());
-                    mLock.lock();
+                    mutex().lock();
                 }
                 return INVALID_OPERATION;
             }
@@ -2814,34 +2898,34 @@
         // 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<EffectChain> chain = getEffectChain_l(track->sessionId());
+        sp<IAfEffectChain> chain = getEffectChain_l(track->sessionId());
         if (mHapticChannelMask != AUDIO_CHANNEL_NONE
                 && ((track->channelMask() & AUDIO_CHANNEL_HAPTIC_ALL) != AUDIO_CHANNEL_NONE
                         || (chain != nullptr && chain->containsHapticGeneratingEffect_l()))) {
             // 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(
+            mutex().unlock();
+            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());
+                 audio_utils::lock_guard _l(mAfThreadCallback->mutex());
+                vibratorInfo = std::move(mAfThreadCallback->getDefaultVibratorInfo_l());
             }
-            mLock.lock();
+            mutex().lock();
             track->setHapticIntensity(intensity);
             if (vibratorInfo) {
                 track->setHapticMaxAmplitude(vibratorInfo->maxAmplitude);
@@ -2862,7 +2946,7 @@
             }
         }
 
-        track->mResetDone = false;
+        track->setResetDone(false);
         track->resetPresentationComplete();
         mActiveTracks.add(track);
         if (chain != 0) {
@@ -2879,25 +2963,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);
 
@@ -2907,26 +2991,26 @@
 
     mTracks.remove(track);
     {
-        Mutex::Autolock _atCbL(mAudioTrackCbLock);
+        audio_utils::lock_guard _atCbL(audioTrackCbMutex());
         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<EffectChain> chain = getEffectChain_l(track->sessionId());
+    sp<IAfEffectChain> chain = getEffectChain_l(track->sessionId());
     if (chain != 0) {
         chain->decTrackCnt();
     }
 }
 
-String8 AudioFlinger::PlaybackThread::getParameters(const String8& keys)
+String8 PlaybackThread::getParameters(const String8& keys)
 {
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mutex());
     String8 out_s8;
     if (initCheck() == NO_ERROR && mOutput->stream->getParameters(keys, &out_s8) == OK) {
         return out_s8;
@@ -2934,15 +3018,15 @@
     return {};
 }
 
-status_t AudioFlinger::DirectOutputThread::selectPresentation(int presentationId, int programId) {
-    Mutex::Autolock _l(mLock);
+status_t DirectOutputThread::selectPresentation(int presentationId, int programId) {
+    audio_utils::lock_guard _l(mutex());
     if (!isStreamInitialized()) {
         return NO_INIT;
     }
     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;
@@ -2964,30 +3048,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;
@@ -3005,26 +3089,26 @@
             audio_utils::metadata::ByteString metaDataStr =
                     audio_utils::metadata::byteStringFromData(metadata);
             std::vector metadataVec(metaDataStr.begin(), metaDataStr.end());
-            Mutex::Autolock _l(mAudioTrackCbLock);
+            audio_utils::lock_guard _l(audioTrackCbMutex());
             for (const auto& callbackPair : mAudioTrackCallbacks) {
                 callbackPair.second->onCodecFormatChanged(metadataVec);
             }
     }).detach();
 }
 
-void AudioFlinger::PlaybackThread::resetWriteBlocked(uint32_t sequence)
+void PlaybackThread::resetWriteBlocked(uint32_t sequence)
 {
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mutex());
     // reject out of sequence requests
     if ((mWriteAckSequence & 1) && (sequence == mWriteAckSequence)) {
         mWriteAckSequence &= ~1;
-        mWaitWorkCV.signal();
+        mWaitWorkCV.notify_one();
     }
 }
 
-void AudioFlinger::PlaybackThread::resetDraining(uint32_t sequence)
+void PlaybackThread::resetDraining(uint32_t sequence)
 {
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mutex());
     // reject out of sequence requests
     if ((mDrainSequence & 1) && (sequence == mDrainSequence)) {
         // Register discontinuity when HW drain is completed because that can cause
@@ -3033,11 +3117,13 @@
         // elsewhere, e.g. in flush).
         mTimestampVerifier.discontinuity(mTimestampVerifier.DISCONTINUITY_MODE_ZERO);
         mDrainSequence &= ~1;
-        mWaitWorkCV.signal();
+        mWaitWorkCV.notify_one();
     }
 }
 
-void AudioFlinger::PlaybackThread::readOutputParameters_l()
+void PlaybackThread::readOutputParameters_l()
+NO_THREAD_SAFETY_ANALYSIS
+// 'moveEffectChain_ll' requires holding mutex 'AudioFlinger_Mutex' exclusively
 {
     // unfortunately we have no way of recovering from errors here, hence the LOG_ALWAYS_FATAL
     const audio_config_base_t audioConfig = mOutput->getAudioProperties();
@@ -3202,20 +3288,21 @@
 
     // force reconfiguration of effect chains and engines to take new buffer size and audio
     // parameters into account
-    // Note that mLock is not held when readOutputParameters_l() is called from the constructor
+    // Note that mutex() is not held when readOutputParameters_l() is called from the constructor
     // but in this case nothing is done below as no audio sessions have effect yet so it doesn't
     // matter.
-    // create a copy of mEffectChains as calling moveEffectChain_l() can reorder some effect chains
-    Vector< sp<EffectChain> > effectChains = mEffectChains;
+    // create a copy of mEffectChains as calling moveEffectChain_ll()
+    // 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_ll(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)
@@ -3226,7 +3313,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
         ;
@@ -3237,14 +3324,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);
     }
@@ -3254,18 +3341,19 @@
     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;
     }
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mutex());
     if (initCheck() != NO_ERROR) {
         return INVALID_OPERATION;
     }
@@ -3287,7 +3375,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
@@ -3295,7 +3383,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());
         }
@@ -3304,15 +3392,15 @@
 }
 
 
-AudioStreamOut* AudioFlinger::PlaybackThread::getOutput() const
+AudioStreamOut* PlaybackThread::getOutput() const
 {
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mutex());
     return mOutput;
 }
 
-AudioStreamOut* AudioFlinger::PlaybackThread::clearOutput()
+AudioStreamOut* PlaybackThread::clearOutput()
 {
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mutex());
     AudioStreamOut *output = mOutput;
     mOutput = NULL;
     // FIXME FastMixer might also have a raw ptr to mOutputSink;
@@ -3323,8 +3411,8 @@
     return output;
 }
 
-// this method must always be called either with ThreadBase mLock held or inside the thread loop
-sp<StreamHalInterface> AudioFlinger::PlaybackThread::stream() const
+// this method must always be called either with ThreadBase mutex() held or inside the thread loop
+sp<StreamHalInterface> PlaybackThread::stream() const
 {
     if (mOutput == NULL) {
         return NULL;
@@ -3332,21 +3420,21 @@
     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;
     }
 
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mutex());
 
     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;
@@ -3356,14 +3444,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.
@@ -3377,7 +3464,7 @@
 #endif
 }
 
-void AudioFlinger::PlaybackThread::checkSilentMode_l()
+void PlaybackThread::checkSilentMode_l()
 {
     if (!mMasterMute) {
         char value[PROPERTY_VALUE_MAX];
@@ -3403,7 +3490,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;
@@ -3417,7 +3504,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();
@@ -3474,8 +3561,8 @@
     return bytesWritten;
 }
 
-// startMelComputation_l() must be called with AudioFlinger::mLock held
-void AudioFlinger::PlaybackThread::startMelComputation_l(
+// startMelComputation_l() must be called with AudioFlinger::mutex() held
+void PlaybackThread::startMelComputation_l(
         const sp<audio_utils::MelProcessor>& processor)
 {
     auto outputSink = static_cast<AudioStreamOutSink*>(mOutputSink.get());
@@ -3484,8 +3571,8 @@
     }
 }
 
-// stopMelComputation_l() must be called with AudioFlinger::mLock held
-void AudioFlinger::PlaybackThread::stopMelComputation_l()
+// stopMelComputation_l() must be called with AudioFlinger::mutex() held
+void PlaybackThread::stopMelComputation_l()
 {
     auto outputSink = static_cast<AudioStreamOutSink*>(mOutputSink.get());
     if (outputSink != nullptr) {
@@ -3493,7 +3580,7 @@
     }
 }
 
-void AudioFlinger::PlaybackThread::threadLoop_drain()
+void PlaybackThread::threadLoop_drain()
 {
     bool supportsDrain = false;
     if (mOutput->stream->supportsDrain(&supportsDrain) == OK && supportsDrain) {
@@ -3509,12 +3596,12 @@
     }
 }
 
-void AudioFlinger::PlaybackThread::threadLoop_exit()
+void PlaybackThread::threadLoop_exit()
 {
     {
-        Mutex::Autolock _l(mLock);
+        audio_utils::lock_guard _l(mutex());
         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.
@@ -3545,13 +3632,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.
@@ -3562,14 +3649,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;
@@ -3578,22 +3665,22 @@
     return trackMatch;
 }
 
-void AudioFlinger::PlaybackThread::invalidateTracks(audio_stream_type_t streamType)
+void PlaybackThread::invalidateTracks(audio_stream_type_t streamType)
 {
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mutex());
     invalidateTracks_l(streamType);
 }
 
-void AudioFlinger::PlaybackThread::invalidateTracks(std::set<audio_port_handle_t>& portIds) {
-    Mutex::Autolock _l(mLock);
+void PlaybackThread::invalidateTracks(std::set<audio_port_handle_t>& portIds) {
+    audio_utils::lock_guard _l(mutex());
     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());
@@ -3607,7 +3694,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) {
@@ -3617,7 +3704,7 @@
     return nullptr;
 }
 
-status_t AudioFlinger::PlaybackThread::addEffectChain_l(const sp<EffectChain>& chain)
+status_t PlaybackThread::addEffectChain_l(const sp<IAfEffectChain>& chain)
 {
     audio_session_t session = chain->sessionId();
     sp<EffectBufferHalInterface> halInBuffer, halOutBuffer;
@@ -3638,12 +3725,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);
@@ -3658,10 +3745,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;
 
@@ -3670,7 +3757,7 @@
             }
         }
     } else {
-        status_t result = mAudioFlinger->mEffectsFactoryHal->mirrorBuffer(
+        status_t result = mAfThreadCallback->getEffectsFactoryHal()->mirrorBuffer(
                 mEffectBufferEnabled ? mEffectBuffer : mSinkBuffer,
                 mEffectBufferEnabled ? mEffectBufferSize : mSinkBufferSize,
                 &halInBuffer);
@@ -3686,7 +3773,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;
@@ -3701,7 +3789,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);
@@ -3711,7 +3799,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);
@@ -3753,7 +3841,7 @@
     return NO_ERROR;
 }
 
-size_t AudioFlinger::PlaybackThread::removeEffectChain_l(const sp<EffectChain>& chain)
+size_t PlaybackThread::removeEffectChain_l(const sp<IAfEffectChain>& chain)
 {
     audio_session_t session = chain->sessionId();
 
@@ -3763,7 +3851,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);
@@ -3773,7 +3861,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();
@@ -3785,15 +3873,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);
+    audio_utils::lock_guard _l(mutex());
     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;
 
@@ -3801,7 +3889,7 @@
         track->setAuxBuffer(0, NULL);
     } else {
         // Auxiliary effects are always in audio session AUDIO_SESSION_OUTPUT_MIX
-        sp<EffectModule> effect = getEffect_l(AUDIO_SESSION_OUTPUT_MIX, EffectId);
+        sp<IAfEffectModule> effect = getEffect_l(AUDIO_SESSION_OUTPUT_MIX, EffectId);
         if (effect != 0) {
             if ((effect->desc().flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
                 track->setAuxBuffer(EffectId, (int32_t *)effect->inBuffer());
@@ -3815,22 +3903,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.
@@ -3878,27 +3966,28 @@
     {
         // 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<EffectChain> > effectChains;
+        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.
         //
-        // Note: we access outDeviceTypes() outside of mLock.
+        // Note: we access outDeviceTypes() outside of mutex().
         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().try_lock()) {
+                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();
@@ -3919,7 +4008,7 @@
                     }
                     mDownstreamLatencyStatMs.add(latencyMs);
                 }
-                mAudioFlinger->mLock.unlock();
+                mAfThreadCallback->mutex().unlock();
             }
         } else {
             if (lastDownstreamPatchHandle != AUDIO_PATCH_HANDLE_NONE) {
@@ -3934,16 +4023,16 @@
         }
 
         MetadataUpdate metadataUpdate;
-        { // scope for mLock
+        { // scope for mutex()
 
-            Mutex::Autolock _l(mLock);
+            audio_utils::unique_lock _l(mutex());
 
             processConfigEvents_l();
             if (mCheckOutputStageEffects.load()) {
                 continue;
             }
 
-            // See comment at declaration of logString for why this is done under mLock
+            // See comment at declaration of logString for why this is done under mutex()
             if (logString != NULL) {
                 mNBLogWriter->logTimestamp();
                 mNBLogWriter->log(logString);
@@ -3968,8 +4057,9 @@
 
                 const int64_t waitNs = computeWaitTimeNs_l();
                 ALOGV("wait async completion (wait time: %lld)", (long long)waitNs);
-                status_t status = mWaitWorkCV.waitRelative(mLock, waitNs);
-                if (status == TIMED_OUT) {
+                std::cv_status cvstatus =
+                        mWaitWorkCV.wait_for(_l, std::chrono::nanoseconds(waitNs));
+                if (cvstatus == std::cv_status::timeout) {
                     mSignalPending = true; // if timeout recheck everything
                 }
                 ALOGV("async completion/wake");
@@ -4011,7 +4101,7 @@
                     releaseWakeLock_l();
                     // wait until we have something to do...
                     ALOGV("%s going to sleep", myName.c_str());
-                    mWaitWorkCV.wait(mLock);
+                    mWaitWorkCV.wait(_l);
                     ALOGV("%s waking up", myName.c_str());
                     acquireWakeLock_l();
 
@@ -4048,7 +4138,7 @@
             // TODO: Write haptic data directly to sink buffer when mixing.
             if (mHapticChannelCount > 0) {
                 for (const auto& track : mActiveTracks) {
-                    sp<EffectChain> effectChain = getEffectChain_l(track->sessionId());
+                    sp<IAfEffectChain> effectChain = getEffectChain_l(track->sessionId());
                     if (effectChain != nullptr
                             && effectChain->containsHapticGeneratingEffect_l()) {
                         activeHapticSessionId = track->sessionId();
@@ -4084,9 +4174,9 @@
                     && (mKernelPositionOnStandby
                             != mTimestamp.mPosition[ExtendedTimestamp::LOCATION_KERNEL])))) {
                 mHalStarted = true;
-                mWaitHalStartCV.broadcast();
+                mWaitHalStartCV.notify_all();
             }
-        } // mLock scope ends
+        } // mutex() scope ends
 
         if (mBytesRemaining == 0) {
             mCurrentWriteLength = 0;
@@ -4103,14 +4193,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);
                         }
                     }
                 }
@@ -4279,7 +4370,7 @@
         unlockEffectChains(effectChains);
 
         if (!metadataUpdate.playbackMetadataUpdate.empty()) {
-            mAudioFlinger->mMelReporter->updateMetadataForCsd(id(),
+            mAfThreadCallback->getMelReporter()->updateMetadataForCsd(id(),
                     metadataUpdate.playbackMetadataUpdate);
         }
 
@@ -4316,7 +4407,7 @@
                                 const double processMs =
                                        (lastIoBeginNs - mLastIoEndNs) * 1e-6;
 
-                                Mutex::Autolock _l(mLock);
+                                audio_utils::lock_guard _l(mutex());
                                 mIoJitterMs.add(jitterMs);
                                 mProcessTimeMs.add(processMs);
 
@@ -4417,7 +4508,7 @@
 
             } else {
                 ATRACE_BEGIN("sleep");
-                Mutex::Autolock _l(mLock);
+                audio_utils::unique_lock _l(mutex());
                 // suspended requires accurate metering of sleep time.
                 if (isSuspended()) {
                     // advance by expected sleepTime
@@ -4442,7 +4533,7 @@
                     mSleepTimeUs = deltaNs / 1000;
                 }
                 if (!mSignalPending && mConfigEvents.isEmpty() && !exitPending()) {
-                    mWaitWorkCV.waitRelative(mLock, microseconds((nsecs_t)mSleepTimeUs));
+                    mWaitWorkCV.wait_for(_l, std::chrono::microseconds(mSleepTimeUs));
                 }
                 ATRACE_END();
             }
@@ -4480,7 +4571,7 @@
     return false;
 }
 
-void AudioFlinger::PlaybackThread::collectTimestamps_l()
+void PlaybackThread::collectTimestamps_l()
 {
     if (mStandby) {
         mTimestampVerifier.discontinuity(discontinuityForStandbyOrFlush());
@@ -4585,10 +4676,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);
@@ -4615,14 +4706,14 @@
 #endif
 }
 
-// removeTracks_l() must be called with ThreadBase::mLock held
-void AudioFlinger::PlaybackThread::removeTracks_l(const Vector< sp<Track> >& tracksToRemove)
-NO_THREAD_SAFETY_ANALYSIS  // release and re-acquire mLock
+// removeTracks_l() must be called with ThreadBase::mutex() held
+void PlaybackThread::removeTracks_l(const Vector<sp<IAfTrack>>& tracksToRemove)
+NO_THREAD_SAFETY_ANALYSIS  // release and re-acquire mutex()
 {
     for (const auto& track : tracksToRemove) {
         mActiveTracks.remove(track);
         ALOGV("%s(%d): removing track on session %d", __func__, track->id(), track->sessionId());
-        sp<EffectChain> chain = getEffectChain_l(track->sessionId());
+        sp<IAfEffectChain> chain = getEffectChain_l(track->sessionId());
         if (chain != 0) {
             ALOGV("%s(%d): stopping track on chain %p for session Id: %d",
                     __func__, track->id(), chain.get(), track->sessionId());
@@ -4643,11 +4734,11 @@
         if (mHapticChannelCount > 0 &&
                 ((track->channelMask() & AUDIO_CHANNEL_HAPTIC_ALL) != AUDIO_CHANNEL_NONE
                         || (chain != nullptr && chain->containsHapticGeneratingEffect_l()))) {
-            mLock.unlock();
+            mutex().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());
-            mLock.lock();
+            afutils::onExternalVibrationStop(track->getExternalVibration());
+            mutex().lock();
 
             // When the track is stop, set the haptic intensity as MUTE
             // for the HapticGenerator effect.
@@ -4658,7 +4749,7 @@
     }
 }
 
-status_t AudioFlinger::PlaybackThread::getTimestamp_l(AudioTimestamp& timestamp)
+status_t PlaybackThread::getTimestamp_l(AudioTimestamp& timestamp)
 {
     if (mNormalSink != 0) {
         ExtendedTimestamp ets;
@@ -4687,7 +4778,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) {
@@ -4709,7 +4800,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;
@@ -4726,7 +4817,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;
@@ -4810,7 +4901,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 */)) {
@@ -4824,7 +4915,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;
 
@@ -4843,19 +4934,19 @@
     return status;
 }
 
-void AudioFlinger::PlaybackThread::addPatchTrack(const sp<PatchTrack>& track)
+void PlaybackThread::addPatchTrack(const sp<IAfPatchTrack>& track)
 {
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mutex());
     mTracks.add(track);
 }
 
-void AudioFlinger::PlaybackThread::deletePatchTrack(const sp<PatchTrack>& track)
+void PlaybackThread::deletePatchTrack(const sp<IAfPatchTrack>& track)
 {
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mutex());
     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;
@@ -4869,9 +4960,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),
@@ -4881,7 +4979,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",
@@ -5008,7 +5106,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);
@@ -5054,7 +5152,7 @@
     }
 }
 
-AudioFlinger::MixerThread::~MixerThread()
+MixerThread::~MixerThread()
 {
     if (mFastMixer != 0) {
         FastMixerStateQueue *sq = mFastMixer->sq();
@@ -5087,14 +5185,14 @@
         }
 #endif
     }
-    mAudioFlinger->unregisterWriter(mFastMixerNBLogWriter);
+    mAfThreadCallback->unregisterWriter(mFastMixerNBLogWriter);
     delete mAudioMixer;
 }
 
-void AudioFlinger::MixerThread::onFirstRef() {
+void MixerThread::onFirstRef() {
     PlaybackThread::onFirstRef();
 
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mutex());
     if (mOutput != nullptr && mOutput->stream != nullptr) {
         status_t status = mOutput->stream->setLatencyModeCallback(this);
         if (status != INVALID_OPERATION) {
@@ -5107,7 +5205,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();
@@ -5116,7 +5214,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
@@ -5144,7 +5242,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();
@@ -5159,7 +5257,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) {
@@ -5197,24 +5295,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);
+    audio_utils::lock_guard _l(mutex());
     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();
@@ -5230,20 +5328,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();
@@ -5261,7 +5359,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
@@ -5314,9 +5412,9 @@
     // TODO add standby time extension fct of effect tail
 }
 
-// prepareTracks_l() must be called with ThreadBase::mLock held
-AudioFlinger::PlaybackThread::mixer_state AudioFlinger::MixerThread::prepareTracks_l(
-        Vector< sp<Track> > *tracksToRemove)
+// prepareTracks_l() must be called with ThreadBase::mutex() held
+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) {
@@ -5343,7 +5441,7 @@
         masterVolume = 0;
     }
     // Delegate master volume control to effect in output mix effect chain if needed
-    sp<EffectChain> chain = getEffectChain_l(AUDIO_SESSION_OUTPUT_MIX);
+    sp<IAfEffectChain> chain = getEffectChain_l(AUDIO_SESSION_OUTPUT_MIX);
     if (chain != 0) {
         uint32_t v = (uint32_t)(masterVolume * (1 << 24));
         chain->setVolume_l(&v, &v);
@@ -5392,23 +5490,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()) {
@@ -5426,7 +5524,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];
@@ -5436,13 +5534,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;
@@ -5452,30 +5550,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
@@ -5489,7 +5587,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;
@@ -5500,10 +5598,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
@@ -5520,7 +5618,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
@@ -5530,20 +5628,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();
@@ -5552,7 +5650,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;
@@ -5567,12 +5665,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,
@@ -5603,13 +5701,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();
@@ -5631,14 +5729,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;
@@ -5651,8 +5749,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);
@@ -5702,11 +5800,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;
@@ -5727,9 +5825,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;
@@ -5755,7 +5853,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,
@@ -5791,18 +5889,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);
@@ -5910,13 +6008,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
@@ -5968,7 +6067,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);
@@ -6044,7 +6143,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();
     }
@@ -6109,8 +6208,8 @@
     return mixerStatus;
 }
 
-// trackCountForUid_l() must be called with ThreadBase::mLock held
-uint32_t AudioFlinger::PlaybackThread::trackCountForUid_l(uid_t uid) const
+// trackCountForUid_l() must be called with ThreadBase::mutex() held
+uint32_t PlaybackThread::trackCountForUid_l(uid_t uid) const
 {
     uint32_t trackCount = 0;
     for (size_t i = 0; i < mTracks.size() ; i++) {
@@ -6121,7 +6220,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
@@ -6145,15 +6244,15 @@
     return mLatchedValue;
 }
 
-void AudioFlinger::PlaybackThread::IsTimestampAdvancing::clear()
+void PlaybackThread::IsTimestampAdvancing::clear()
 {
     mLatchedValue = true;
     mPreviousPosition = 0;
     mPreviousNs = 0;
 }
 
-// isTrackAllowed_l() must be called with ThreadBase::mLock held
-bool AudioFlinger::MixerThread::isTrackAllowed_l(
+// isTrackAllowed_l() must be called with ThreadBase::mutex() held
+bool MixerThread::isTrackAllowed_l(
         audio_channel_mask_t channelMask, audio_format_t format,
         audio_session_t sessionId, uid_t uid) const
 {
@@ -6172,8 +6271,8 @@
     return true;
 }
 
-// checkForNewParameter_l() must be called with ThreadBase::mLock held
-bool AudioFlinger::MixerThread::checkForNewParameter_l(const String8& keyValuePair,
+// checkForNewParameter_l() must be called with ThreadBase::mutex() held
+bool MixerThread::checkForNewParameter_l(const String8& keyValuePair,
                                                        status_t& status)
 {
     bool reconfig = false;
@@ -6187,7 +6286,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
@@ -6195,7 +6294,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
@@ -6236,14 +6335,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);
         }
@@ -6253,7 +6352,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);
@@ -6300,17 +6399,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();
 
@@ -6321,11 +6420,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
@@ -6367,7 +6466,7 @@
     }
 }
 
-void AudioFlinger::MixerThread::updateHalSupportedLatencyModes_l() {
+void MixerThread::updateHalSupportedLatencyModes_l() {
 
     if (mOutput == nullptr || mOutput->stream == nullptr) {
         return;
@@ -6385,19 +6484,19 @@
     }
 }
 
-status_t AudioFlinger::MixerThread::getSupportedLatencyModes(
+status_t MixerThread::getSupportedLatencyModes(
         std::vector<audio_latency_mode_t>* modes) {
     if (modes == nullptr) {
         return BAD_VALUE;
     }
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mutex());
     *modes = mSupportedLatencyModes;
     return NO_ERROR;
 }
 
-void AudioFlinger::MixerThread::onRecommendedLatencyModeChanged(
+void MixerThread::onRecommendedLatencyModeChanged(
         std::vector<audio_latency_mode_t> modes) {
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mutex());
     if (modes != mSupportedLatencyModes) {
         ALOGD("%s: thread(%d) supported latency modes: %s",
             __func__, mId, toString(modes).c_str());
@@ -6406,7 +6505,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;
@@ -6417,29 +6516,38 @@
 
 // ----------------------------------------------------------------------------
 
-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);
+    audio_utils::lock_guard _l(mutex());
     if (mMasterBalance != balance) {
         mMasterBalance.store(balance);
         mBalance.computeStereoBalance(balance, &mMasterBalanceLeft, &mMasterBalanceRight);
@@ -6447,12 +6555,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 int64_t frames = mTimestamp.mPosition[ExtendedTimestamp::LOCATION_KERNEL];
     const int64_t time = mTimestamp.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL];
@@ -6486,14 +6594,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,
@@ -6525,10 +6633,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) {
@@ -6550,8 +6658,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();
@@ -6560,14 +6668,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
@@ -6575,7 +6683,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()) {
@@ -6611,8 +6719,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.
@@ -6624,7 +6732,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;
@@ -6642,8 +6750,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;
@@ -6656,7 +6764,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
@@ -6668,7 +6776,7 @@
                 mPreviousTrack = track;
 
                 // reset retry count
-                track->mRetryCount = targetRetryCount;
+                track->retryCount() = targetRetryCount;
                 mActiveTrack = t;
                 mixerStatus = MIXER_TRACKS_READY;
                 if (mHwPaused) {
@@ -6683,7 +6791,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;
@@ -6701,7 +6809,7 @@
                         mOutput->presentationComplete();
                     }
                     if (track->isStopping_2()) {
-                        track->mState = TrackBase::STOPPED;
+                        track->setState(IAfTrackBase::STOPPED);
                     }
                     if (track->isStopped()) {
                         track->reset();
@@ -6714,9 +6822,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);
@@ -6773,7 +6881,7 @@
     return mixerStatus;
 }
 
-void AudioFlinger::DirectOutputThread::threadLoop_mix()
+void DirectOutputThread::threadLoop_mix()
 {
     size_t frameCount = mFrameCount;
     int8_t *curBuf = (int8_t *)mSinkBuffer;
@@ -6800,7 +6908,7 @@
     mActiveTrack.clear();
 }
 
-void AudioFlinger::DirectOutputThread::threadLoop_sleepTime()
+void DirectOutputThread::threadLoop_sleepTime()
 {
     // do not write to HAL when paused
     if (mHwPaused || (usesHwAvSync() && mStandby)) {
@@ -6816,10 +6924,10 @@
     // linear or proportional PCM direct tracks in underrun.
 }
 
-void AudioFlinger::DirectOutputThread::threadLoop_exit()
+void DirectOutputThread::threadLoop_exit()
 {
     {
-        Mutex::Autolock _l(mLock);
+        audio_utils::lock_guard _l(mutex());
         for (size_t i = 0; i < mTracks.size(); i++) {
             if (mTracks[i]->isFlushPending()) {
                 mTracks[i]->flushAck();
@@ -6834,7 +6942,7 @@
 }
 
 // must be called with thread mutex locked
-bool AudioFlinger::DirectOutputThread::shouldStandby_l()
+bool DirectOutputThread::shouldStandby_l()
 {
     bool trackPaused = false;
     bool trackStopped = false;
@@ -6844,14 +6952,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,
+// checkForNewParameter_l() must be called with ThreadBase::mutex() held
+bool DirectOutputThread::checkForNewParameter_l(const String8& keyValuePair,
                                                               status_t& status)
 {
     bool reconfig = false;
@@ -6893,7 +7001,7 @@
     return reconfig;
 }
 
-uint32_t AudioFlinger::DirectOutputThread::activeSleepTimeUs() const
+uint32_t DirectOutputThread::activeSleepTimeUs() const
 {
     uint32_t time;
     if (audio_has_proportional_frames(mFormat)) {
@@ -6904,7 +7012,7 @@
     return time;
 }
 
-uint32_t AudioFlinger::DirectOutputThread::idleSleepTimeUs() const
+uint32_t DirectOutputThread::idleSleepTimeUs() const
 {
     uint32_t time;
     if (audio_has_proportional_frames(mFormat)) {
@@ -6915,7 +7023,7 @@
     return time;
 }
 
-uint32_t AudioFlinger::DirectOutputThread::suspendSleepTimeUs() const
+uint32_t DirectOutputThread::suspendSleepTimeUs() const
 {
     uint32_t time;
     if (audio_has_proportional_frames(mFormat)) {
@@ -6926,7 +7034,7 @@
     return time;
 }
 
-void AudioFlinger::DirectOutputThread::cacheParameters_l()
+void DirectOutputThread::cacheParameters_l()
 {
     PlaybackThread::cacheParameters_l();
 
@@ -6942,7 +7050,7 @@
     }
 }
 
-void AudioFlinger::DirectOutputThread::flushHw_l()
+void DirectOutputThread::flushHw_l()
 {
     PlaybackThread::flushHw_l();
     mOutput->flush();
@@ -6953,7 +7061,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 ?
@@ -6962,8 +7070,8 @@
 
 // ----------------------------------------------------------------------------
 
-AudioFlinger::AsyncCallbackThread::AsyncCallbackThread(
-        const wp<AudioFlinger::PlaybackThread>& playbackThread)
+AsyncCallbackThread::AsyncCallbackThread(
+        const wp<PlaybackThread>& playbackThread)
     :   Thread(false /*canCallJava*/),
         mPlaybackThread(playbackThread),
         mWriteAckSequence(0),
@@ -6972,16 +7080,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;
@@ -6989,12 +7093,12 @@
         bool asyncError;
 
         {
-            Mutex::Autolock _l(mLock);
+            audio_utils::unique_lock _l(mutex());
             while (!((mWriteAckSequence & 1) ||
                      (mDrainSequence & 1) ||
                      mAsyncError ||
                      exitPending())) {
-                mWaitWorkCV.wait(mLock);
+                mWaitWorkCV.wait(_l);
             }
 
             if (exitPending()) {
@@ -7010,7 +7114,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);
@@ -7027,61 +7131,70 @@
     return false;
 }
 
-void AudioFlinger::AsyncCallbackThread::exit()
+void AsyncCallbackThread::exit()
 {
     ALOGV("AsyncCallbackThread::exit");
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mutex());
     requestExit();
-    mWaitWorkCV.broadcast();
+    mWaitWorkCV.notify_all();
 }
 
-void AudioFlinger::AsyncCallbackThread::setWriteBlocked(uint32_t sequence)
+void AsyncCallbackThread::setWriteBlocked(uint32_t sequence)
 {
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mutex());
     // bit 0 is cleared
     mWriteAckSequence = sequence << 1;
 }
 
-void AudioFlinger::AsyncCallbackThread::resetWriteBlocked()
+void AsyncCallbackThread::resetWriteBlocked()
 {
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mutex());
     // ignore unexpected callbacks
     if (mWriteAckSequence & 2) {
         mWriteAckSequence |= 1;
-        mWaitWorkCV.signal();
+        mWaitWorkCV.notify_one();
     }
 }
 
-void AudioFlinger::AsyncCallbackThread::setDraining(uint32_t sequence)
+void AsyncCallbackThread::setDraining(uint32_t sequence)
 {
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mutex());
     // bit 0 is cleared
     mDrainSequence = sequence << 1;
 }
 
-void AudioFlinger::AsyncCallbackThread::resetDraining()
+void AsyncCallbackThread::resetDraining()
 {
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mutex());
     // ignore unexpected callbacks
     if (mDrainSequence & 2) {
         mDrainSequence |= 1;
-        mWaitWorkCV.signal();
+        mWaitWorkCV.notify_one();
     }
 }
 
-void AudioFlinger::AsyncCallbackThread::setAsyncError()
+void AsyncCallbackThread::setAsyncError()
 {
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mutex());
     mAsyncError = true;
-    mWaitWorkCV.signal();
+    mWaitWorkCV.notify_one();
 }
 
 
 // ----------------------------------------------------------------------------
-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
@@ -7089,7 +7202,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
@@ -7105,8 +7218,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();
@@ -7118,8 +7231,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
@@ -7127,7 +7240,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()) {
@@ -7136,7 +7249,7 @@
             continue;
         }
 
-        if (track->mState == TrackBase::IDLE) {
+        if (track->state() == IAfTrackBase::IDLE) {
             ALOGW("An idle track shouldn't be in active list");
             continue;
         }
@@ -7168,9 +7281,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) {
@@ -7202,8 +7315,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;
@@ -7211,7 +7324,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
@@ -7237,9 +7350,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;
@@ -7247,7 +7360,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.
@@ -7255,7 +7368,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
@@ -7275,13 +7389,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();
@@ -7301,9 +7415,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());
@@ -7347,7 +7461,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);
@@ -7357,13 +7471,13 @@
     return false;
 }
 
-bool AudioFlinger::OffloadThread::waitingAsyncCallback()
+bool OffloadThread::waitingAsyncCallback()
 {
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mutex());
     return waitingAsyncCallback_l();
 }
 
-void AudioFlinger::OffloadThread::flushHw_l()
+void OffloadThread::flushHw_l()
 {
     DirectOutputThread::flushHw_l();
     // Flush anything still waiting in the mixbuffer
@@ -7384,16 +7498,16 @@
     }
 }
 
-void AudioFlinger::OffloadThread::invalidateTracks(audio_stream_type_t streamType)
+void OffloadThread::invalidateTracks(audio_stream_type_t streamType)
 {
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mutex());
     if (PlaybackThread::invalidateTracks_l(streamType)) {
         mFlushPending = true;
     }
 }
 
-void AudioFlinger::OffloadThread::invalidateTracks(std::set<audio_port_handle_t>& portIds) {
-    Mutex::Autolock _l(mLock);
+void OffloadThread::invalidateTracks(std::set<audio_port_handle_t>& portIds) {
+    audio_utils::lock_guard _l(mutex());
     if (PlaybackThread::invalidateTracks_l(portIds)) {
         mFlushPending = true;
     }
@@ -7401,23 +7515,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()) {
@@ -7435,7 +7556,7 @@
     mStandbyTimeNs = systemTime() + mStandbyDelayNs;
 }
 
-void AudioFlinger::DuplicatingThread::threadLoop_sleepTime()
+void DuplicatingThread::threadLoop_sleepTime()
 {
     if (mSleepTimeUs == 0) {
         if (mMixerStatus == MIXER_TRACKS_ENABLED) {
@@ -7455,7 +7576,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);
@@ -7483,7 +7604,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++) {
@@ -7491,7 +7612,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);
 
@@ -7501,7 +7622,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();
@@ -7516,19 +7637,19 @@
     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);
+    audio_utils::lock_guard _l(mutex());
     // The downstream MixerThread consumes thread->frameCount() amount of frames per mix pass.
     // Adjust for thread->sampleRate() to determine minimum buffer frame count.
     // Then triple buffer because Threads do not run synchronously and may not be clock locked.
@@ -7545,7 +7666,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,
@@ -7563,9 +7684,9 @@
     updateWaitTime_l();
 }
 
-void AudioFlinger::DuplicatingThread::removeOutputTrack(MixerThread *thread)
+void DuplicatingThread::removeOutputTrack(IAfPlaybackThread* thread)
 {
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mutex());
     for (size_t i = 0; i < mOutputTracks.size(); i++) {
         if (mOutputTracks[i]->thread() == thread) {
             mOutputTracks[i]->destroy();
@@ -7580,12 +7701,12 @@
     ALOGV("removeOutputTrack(): unknown thread: %p", thread);
 }
 
-// caller must hold mLock
-void AudioFlinger::DuplicatingThread::updateWaitTime_l()
+// caller must hold mutex()
+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) {
@@ -7595,18 +7716,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;
@@ -7615,7 +7736,7 @@
     return true;
 }
 
-void AudioFlinger::DuplicatingThread::sendMetadataToBackend_l(
+void DuplicatingThread::sendMetadataToBackend_l(
         const StreamOutHalInterface::SourceMetadata& metadata)
 {
     for (auto& outputTrack : outputTracks) { // not mOutputTracks
@@ -7623,12 +7744,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();
@@ -7638,16 +7759,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();
@@ -7662,7 +7793,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()) {
@@ -7700,23 +7831,25 @@
     }
 }
 
-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;
     }
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mutex());
     mRequestedLatencyMode = mode;
     return NO_ERROR;
 }
 
-void AudioFlinger::SpatializerThread::checkOutputStageEffects()
+void SpatializerThread::checkOutputStageEffects()
+NO_THREAD_SAFETY_ANALYSIS
+//  'createEffect_l' requires holding mutex 'AudioFlinger_Mutex' exclusively
 {
     bool hasVirtualizer = false;
     bool hasDownMixer = false;
-    sp<EffectHandle> finalDownMixer;
+    sp<IAfEffectHandle> finalDownMixer;
     {
-        Mutex::Autolock _l(mLock);
-        sp<EffectChain> chain = getEffectChain_l(AUDIO_SESSION_OUTPUT_STAGE);
+        audio_utils::lock_guard _l(mutex());
+        sp<IAfEffectChain> chain = getEffectChain_l(AUDIO_SESSION_OUTPUT_STAGE);
         if (chain != 0) {
             hasVirtualizer = chain->getEffectFromType_l(FX_IID_SPATIALIZER) != nullptr;
             hasDownMixer = chain->getEffectFromType_l(EFFECT_UIID_DOWNMIX) != nullptr;
@@ -7729,12 +7862,12 @@
     if (hasVirtualizer) {
         if (finalDownMixer != nullptr) {
             int32_t ret;
-            finalDownMixer->disable(&ret);
+            finalDownMixer->asIEffect()->disable(&ret);
         }
         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;
@@ -7751,12 +7884,12 @@
             finalDownMixer.clear();
         } else {
             int32_t ret;
-            finalDownMixer->enable(&ret);
+            finalDownMixer->asIEffect()->enable(&ret);
         }
     }
 
     {
-        Mutex::Autolock _l(mLock);
+        audio_utils::lock_guard _l(mutex());
         mFinalDownMixer = finalDownMixer;
     }
 }
@@ -7765,12 +7898,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),
@@ -7791,7 +7931,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(
@@ -7899,7 +8039,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);
@@ -7924,7 +8065,7 @@
     // FIXME mNormalSource
 }
 
-AudioFlinger::RecordThread::~RecordThread()
+RecordThread::~RecordThread()
 {
     if (mFastCapture != 0) {
         FastCaptureStateQueue *sq = mFastCapture->sq();
@@ -7941,38 +8082,38 @@
         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);
+    audio_utils::lock_guard _l(mutex());
     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();
+    mStartStopCV.notify_all();
 }
 
-bool AudioFlinger::RecordThread::threadLoop()
+bool RecordThread::threadLoop()
 {
     nsecs_t lastWarning = 0;
 
     inputStandBy();
 
 reacquire_wakelock:
-    sp<RecordTrack> activeTrack;
+    sp<IAfRecordTrack> activeTrack;
     {
-        Mutex::Autolock _l(mLock);
+        audio_utils::lock_guard _l(mutex());
         acquireWakeLock_l();
     }
 
@@ -7983,26 +8124,26 @@
 
     // loop while there is work to do
     for (int64_t loopCount = 0;; ++loopCount) {  // loopCount used for statistics tracking
-        Vector< sp<EffectChain> > effectChains;
+        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;
 
-        { // scope for mLock
-            Mutex::Autolock _l(mLock);
+        { // scope for mutex()
+            audio_utils::unique_lock _l(mutex());
 
             processConfigEvents_l();
 
             // check exitPending here because checkForNewParameters_l() and
-            // checkForNewParameters_l() can temporarily release mLock
+            // checkForNewParameters_l() can temporarily release mutex()
             if (exitPending()) {
                 break;
             }
@@ -8010,7 +8151,7 @@
             // sleep with mutex unlocked
             if (sleepUs > 0) {
                 ATRACE_BEGIN("sleepC");
-                mWaitWorkCV.waitRelative(mLock, microseconds((nsecs_t)sleepUs));
+                (void)mWaitWorkCV.wait_for(_l, std::chrono::microseconds(sleepUs));
                 ATRACE_END();
                 sleepUs = 0;
                 continue;
@@ -8024,7 +8165,7 @@
                 releaseWakeLock_l();
                 ALOGV("RecordThread: loop stopping");
                 // go to sleep
-                mWaitWorkCV.wait(mLock);
+                mWaitWorkCV.wait(_l);
                 ALOGV("RecordThread: loop starting");
                 goto reacquire_wakelock;
             }
@@ -8045,40 +8186,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);
@@ -8131,7 +8272,7 @@
                 standbyIfNotAlreadyInStandby();
             }
             if (doBroadcast) {
-                mStartStopCond.broadcast();
+                mStartStopCV.notify_all();
             }
 
             // sleep if there are no active tracks to process
@@ -8170,7 +8311,7 @@
                 }
                 state->mCommand = FastCaptureState::READ_WRITE;
 #if 0   // FIXME
-                mFastCaptureDumpState.increaseSamplingN(mAudioFlinger->isLowRamDevice() ?
+                mFastCaptureDumpState.increaseSamplingN(mAfThreadCallback->isLowRamDevice() ?
                         FastThreadDumpState::kSamplingNforLowRamDevice :
                         FastThreadDumpState::kSamplingN);
 #endif
@@ -8325,7 +8466,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);
@@ -8382,16 +8523,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;
                 }
@@ -8405,7 +8546,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
@@ -8413,14 +8554,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",
@@ -8429,9 +8571,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);
                 }
 
@@ -8441,17 +8583,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) {
@@ -8480,7 +8623,7 @@
 
             // update frame information and push timestamp out
             activeTrack->updateTrackFrameInfo(
-                    activeTrack->mServerProxy->framesReleased(),
+                    activeTrack->serverProxy()->framesReleased(),
                     mTimestamp.mPosition[ExtendedTimestamp::LOCATION_SERVER],
                     mSampleRate, mTimestamp);
         }
@@ -8498,7 +8641,7 @@
                     {0, 0} /* lastTimestamp */, mSampleRate);
             const double processMs = (lastIoBeginNs - mLastIoEndNs) * 1e-6;
 
-            Mutex::Autolock _l(mLock);
+            audio_utils::lock_guard _l(mutex());
             mIoJitterMs.add(jitterMs);
             mProcessTimeMs.add(processMs);
         }
@@ -8511,13 +8654,13 @@
     standbyIfNotAlreadyInStandby();
 
     {
-        Mutex::Autolock _l(mLock);
+        audio_utils::lock_guard _l(mutex());
         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();
+        mStartStopCV.notify_all();
     }
 
     releaseWakeLock();
@@ -8526,7 +8669,7 @@
     return false;
 }
 
-void AudioFlinger::RecordThread::standbyIfNotAlreadyInStandby()
+void RecordThread::standbyIfNotAlreadyInStandby()
 {
     if (!mStandby) {
         inputStandBy();
@@ -8536,7 +8679,7 @@
     }
 }
 
-void AudioFlinger::RecordThread::inputStandBy()
+void RecordThread::inputStandBy()
 {
     // Idle the fast capture if it's currently running
     if (mFastCapture != 0) {
@@ -8576,9 +8719,9 @@
     }
 }
 
-// RecordThread::createRecordTrack_l() must be called with AudioFlinger::mLock held
-sp<AudioFlinger::RecordThread::RecordTrack> AudioFlinger::RecordThread::createRecordTrack_l(
-        const sp<AudioFlinger::Client>& client,
+// RecordThread::createRecordTrack_l() must be called with AudioFlinger::mutex() held
+sp<IAfRecordTrack> RecordThread::createRecordTrack_l(
+        const sp<Client>& client,
         const audio_attributes_t& attr,
         uint32_t *pSampleRate,
         audio_format_t format,
@@ -8596,7 +8739,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;
@@ -8620,7 +8763,7 @@
             goto Exit;
         }
         if (maxSharedAudioHistoryMs < 0
-                || maxSharedAudioHistoryMs > AudioFlinger::kMaxSharedAudioHistoryMs) {
+                || maxSharedAudioHistoryMs > kMaxSharedAudioHistoryMs) {
             lStatus = BAD_VALUE;
             goto Exit;
         }
@@ -8668,9 +8811,9 @@
             mFastTrackAvail
         ) {
           // check compatibility with audio effects.
-          Mutex::Autolock _l(mLock);
+          audio_utils::lock_guard _l(mutex());
           // Do not accept FAST flag if the session has software effects
-          sp<EffectChain> chain = getEffectChain_l(sessionId);
+          sp<IAfEffectChain> chain = getEffectChain_l(sessionId);
           if (chain != 0) {
               audio_input_flags_t old = *flags;
               chain->checkInputFlagCompatibility(flags);
@@ -8732,8 +8875,8 @@
     *pFrameCount = frameCount;
     *pNotificationFrameCount = notificationFrameCount;
 
-    { // scope for mLock
-        Mutex::Autolock _l(mLock);
+    { // scope for mutex()
+        audio_utils::lock_guard _l(mutex());
         int32_t startFrames = -1;
         if (!mSharedAudioPackageName.empty()
                 && mSharedAudioPackageName == attributionSource.packageName
@@ -8742,10 +8885,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();
@@ -8775,7 +8918,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)
 {
@@ -8786,28 +8929,28 @@
     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));
     }
 
     {
         // This section is a rendezvous between binder thread executing start() and RecordThread
-        AutoMutex lock(mLock);
+         audio_utils::lock_guard lock(mutex());
         if (recordTrack->isInvalid()) {
             recordTrack->clearSyncStartEvent();
             ALOGW("%s track %d: invalidated before startInput", __func__, recordTrack->portId());
             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;
         }
@@ -8815,24 +8958,24 @@
         // 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();
+            mutex().unlock();
             status = AudioSystem::startInput(recordTrack->portId());
-            mLock.lock();
+            mutex().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();
@@ -8859,67 +9002,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();
+        mWaitWorkCV.notify_all();
         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 = 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);
+    audio_utils::unique_lock _l(mutex());
     // 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()) {
-        mWaitWorkCV.broadcast(); // signal thread to stop
-        mStartStopCond.wait(mLock);
+    while (recordTrack->state() == IAfTrackBase::PAUSING && !recordTrack->isInvalid()) {
+        mWaitWorkCV.notify_all(); // signal thread to stop
+        mStartStopCV.wait(_l);
     }
 
-    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)) {
@@ -8929,10 +9071,10 @@
     audio_session_t eventSession = event->triggerSession();
     status_t ret = NAME_NOT_FOUND;
 
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mutex());
 
     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;
@@ -8944,11 +9086,11 @@
 #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);
+     audio_utils::lock_guard _l(mutex());
     if (!isStreamInitialized()) {
         return NO_INIT;
     }
@@ -8956,35 +9098,35 @@
     return status;
 }
 
-status_t AudioFlinger::RecordThread::setPreferredMicrophoneDirection(
+status_t RecordThread::setPreferredMicrophoneDirection(
             audio_microphone_direction_t direction)
 {
     ALOGV("setPreferredMicrophoneDirection(%d)", direction);
-    AutoMutex _l(mLock);
+     audio_utils::lock_guard _l(mutex());
     if (!isStreamInitialized()) {
         return NO_INIT;
     }
     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);
+     audio_utils::lock_guard _l(mutex());
     if (!isStreamInitialized()) {
         return NO_INIT;
     }
     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);
+     audio_utils::lock_guard _l(mutex());
     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) {
 
@@ -9024,20 +9166,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);
@@ -9046,11 +9188,11 @@
     return change;
 }
 
-// destroyTrack_l() must be called with ThreadBase::mLock held
-void AudioFlinger::RecordThread::destroyTrack_l(const sp<RecordTrack>& track)
+// destroyTrack_l() must be called with ThreadBase::mutex() held
+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) {
@@ -9058,7 +9200,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 */);
@@ -9072,7 +9214,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;
@@ -9100,7 +9242,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();
@@ -9113,7 +9255,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) {
@@ -9133,7 +9275,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 */);
@@ -9144,21 +9286,21 @@
     write(fd, result.c_str(), 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);
+    audio_utils::lock_guard _l(mutex());
     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;
@@ -9178,11 +9320,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);
@@ -9212,16 +9354,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);
@@ -9255,7 +9397,7 @@
 }
 
 // AudioBufferProvider interface
-void AudioFlinger::RecordThread::ResamplerBufferProvider::releaseBuffer(
+void ResamplerBufferProvider::releaseBuffer(
         AudioBufferProvider::Buffer* buffer)
 {
     int32_t stepCount = static_cast<int32_t>(buffer->frameCount);
@@ -9269,18 +9411,18 @@
     buffer->frameCount = 0;
 }
 
-void AudioFlinger::RecordThread::checkBtNrec()
+void RecordThread::checkBtNrec()
 {
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mutex());
     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());
@@ -9290,7 +9432,7 @@
 }
 
 
-bool AudioFlinger::RecordThread::checkForNewParameter_l(const String8& keyValuePair,
+bool RecordThread::checkForNewParameter_l(const String8& keyValuePair,
                                                         status_t& status)
 {
     bool reconfig = false;
@@ -9378,9 +9520,9 @@
     return reconfig;
 }
 
-String8 AudioFlinger::RecordThread::getParameters(const String8& keys)
+String8 RecordThread::getParameters(const String8& keys)
 {
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mutex());
     if (initCheck() == NO_ERROR) {
         String8 out_s8;
         if (mInput->stream->getParameters(keys, &out_s8) == OK) {
@@ -9390,7 +9532,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) {
@@ -9408,10 +9550,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);
@@ -9445,7 +9587,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)
@@ -9454,9 +9596,9 @@
         .record();
 }
 
-uint32_t AudioFlinger::RecordThread::getInputFramesLost()
+uint32_t RecordThread::getInputFramesLost() const
 {
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mutex());
     uint32_t result;
     if (initCheck() == NO_ERROR && mInput->stream->getInputFramesLost(&result) == OK) {
         return result;
@@ -9464,12 +9606,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);
+    audio_utils::lock_guard _l(mutex());
     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);
@@ -9478,17 +9620,17 @@
     return ids;
 }
 
-AudioFlinger::AudioStreamIn* AudioFlinger::RecordThread::clearInput()
+AudioStreamIn* RecordThread::clearInput()
 {
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mutex());
     AudioStreamIn *input = mInput;
     mInput = NULL;
     mInputSource.clear();
     return input;
 }
 
-// this method must always be called either with ThreadBase mLock held or inside the thread loop
-sp<StreamHalInterface> AudioFlinger::RecordThread::stream() const
+// this method must always be called either with ThreadBase mutex() held or inside the thread loop
+sp<StreamHalInterface> RecordThread::stream() const
 {
     if (mInput == NULL) {
         return NULL;
@@ -9496,7 +9638,7 @@
     return mInput->stream;
 }
 
-status_t AudioFlinger::RecordThread::addEffectChain_l(const sp<EffectChain>& chain)
+status_t RecordThread::addEffectChain_l(const sp<IAfEffectChain>& chain)
 {
     ALOGV("addEffectChain_l() %p on thread %p", chain.get(), this);
     chain->setThread(this);
@@ -9514,7 +9656,7 @@
     return NO_ERROR;
 }
 
-size_t AudioFlinger::RecordThread::removeEffectChain_l(const sp<EffectChain>& chain)
+size_t RecordThread::removeEffectChain_l(const sp<IAfEffectChain>& chain)
 {
     ALOGV("removeEffectChain_l() %p from thread %p", chain.get(), this);
 
@@ -9527,7 +9669,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;
@@ -9584,7 +9726,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;
 
@@ -9603,9 +9745,9 @@
     return status;
 }
 
-void AudioFlinger::RecordThread::updateOutDevices(const DeviceDescriptorBaseVector& outDevices)
+void RecordThread::updateOutDevices(const DeviceDescriptorBaseVector& outDevices)
 {
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mutex());
     mOutDevices = outDevices;
     mOutDeviceTypeAddrs = deviceTypeAddrsFromDescriptors(mOutDevices);
     for (size_t i = 0; i < mEffectChains.size(); i++) {
@@ -9613,7 +9755,7 @@
     }
 }
 
-int32_t AudioFlinger::RecordThread::getOldestFront_l()
+int32_t RecordThread::getOldestFront_l()
 {
     if (mTracks.size() == 0) {
         return mRsmpInRear;
@@ -9621,7 +9763,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) {
@@ -9635,19 +9777,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
@@ -9671,7 +9813,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) {
@@ -9740,25 +9882,25 @@
     mRsmpInBuffer = rsmpInBuffer;
 }
 
-void AudioFlinger::RecordThread::addPatchTrack(const sp<PatchRecord>& record)
+void RecordThread::addPatchTrack(const sp<IAfPatchRecord>& record)
 {
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mutex());
     mTracks.add(record);
     if (record->getSource()) {
         mSource = record->getSource();
     }
 }
 
-void AudioFlinger::RecordThread::deletePatchTrack(const sp<PatchRecord>& record)
+void RecordThread::deletePatchTrack(const sp<IAfPatchRecord>& record)
 {
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mutex());
     if (mSource == record->getSource()) {
         mSource = mInput;
     }
     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;
@@ -9774,59 +9916,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),
@@ -9838,25 +10009,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) {
+        audio_utils::lock_guard _l(mutex());
+        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.
@@ -9868,7 +10035,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,
@@ -9882,7 +10049,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) {
@@ -9892,7 +10059,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;
@@ -9900,7 +10067,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();
@@ -9917,7 +10084,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)
 {
@@ -9938,7 +10105,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()) {
@@ -9995,24 +10162,24 @@
         {
             // Add the track record before starting input so that the silent status for the
             // client can be cached.
-            Mutex::Autolock _l(mLock);
+            audio_utils::lock_guard _l(mutex());
             setClientSilencedState_l(portId, false /*silenced*/);
         }
         ret = AudioSystem::startInput(portId);
     }
 
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mutex());
     // abort if start is rejected by audio policy manager
     if (ret != NO_ERROR) {
         ALOGE("%s: error start rejected by AudioPolicyManager = %d", __FUNCTION__, ret);
         if (!mActiveTracks.isEmpty()) {
-            mLock.unlock();
+            mutex().unlock();
             if (isOutput()) {
                 AudioSystem::releaseOutput(portId);
             } else {
                 AudioSystem::releaseInput(portId);
             }
-            mLock.lock();
+            mutex().lock();
         } else {
             mHalStream->stop();
         }
@@ -10021,7 +10188,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);
@@ -10033,7 +10201,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 +10210,7 @@
     }
 
     mActiveTracks.add(track);
-    sp<EffectChain> chain = getEffectChain_l(mSessionId);
+    sp<IAfEffectChain> chain = getEffectChain_l(mSessionId);
     if (chain != 0) {
         chain->setStrategy(getStrategyForStream(streamType()));
         chain->incTrackCnt();
@@ -10063,7 +10231,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);
 
@@ -10076,10 +10244,10 @@
         return NO_ERROR;
     }
 
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mutex());
 
-    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;
@@ -10092,7 +10260,7 @@
     mActiveTracks.remove(track);
     eraseClientSilencedState_l(track->portId());
 
-    mLock.unlock();
+    mutex().unlock();
     if (isOutput()) {
         AudioSystem::stopOutput(track->portId());
         AudioSystem::releaseOutput(track->portId());
@@ -10100,9 +10268,9 @@
         AudioSystem::stopInput(track->portId());
         AudioSystem::releaseInput(track->portId());
     }
-    mLock.lock();
+    mutex().lock();
 
-    sp<EffectChain> chain = getEffectChain_l(track->sessionId());
+    sp<IAfEffectChain> chain = getEffectChain_l(track->sessionId());
     if (chain != 0) {
         chain->decActiveTrackCnt();
         chain->decTrackCnt();
@@ -10117,7 +10285,7 @@
     return NO_ERROR;
 }
 
-status_t AudioFlinger::MmapThread::standby()
+status_t MmapThread::standby()
 {
     ALOGV("%s", __FUNCTION__);
 
@@ -10137,12 +10305,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);
@@ -10159,7 +10327,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)
@@ -10172,13 +10340,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();
 
@@ -10186,10 +10354,10 @@
 
     while (!exitPending())
     {
-        Vector< sp<EffectChain> > effectChains;
+        Vector<sp<IAfEffectChain>> effectChains;
 
         { // under Thread lock
-        Mutex::Autolock _l(mLock);
+        audio_utils::unique_lock _l(mutex());
 
         if (mSignalPending) {
             // A signal was raised while we were unlocked
@@ -10205,7 +10373,7 @@
 
                 // wait until we have something to do...
                 ALOGV("%s going to sleep", myName.c_str());
-                mWaitWorkCV.wait(mLock);
+                mWaitWorkCV.wait(_l);
                 ALOGV("%s waking up", myName.c_str());
 
                 checkSilentMode_l();
@@ -10248,8 +10416,8 @@
     return false;
 }
 
-// checkForNewParameter_l() must be called with ThreadBase::mLock held
-bool AudioFlinger::MmapThread::checkForNewParameter_l(const String8& keyValuePair,
+// checkForNewParameter_l() must be called with ThreadBase::mutex() held
+bool MmapThread::checkForNewParameter_l(const String8& keyValuePair,
                                                               status_t& status)
 {
     AudioParameter param = AudioParameter(keyValuePair);
@@ -10267,9 +10435,9 @@
     return false;
 }
 
-String8 AudioFlinger::MmapThread::getParameters(const String8& keys)
+String8 MmapThread::getParameters(const String8& keys)
 {
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mutex());
     String8 out_s8;
     if (initCheck() == NO_ERROR && mHalStream->getParameters(keys, &out_s8) == OK) {
         return out_s8;
@@ -10277,7 +10445,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;
@@ -10299,12 +10467,12 @@
         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
+NO_THREAD_SAFETY_ANALYSIS  // elease and re-acquire mutex()
 {
     status_t status = NO_ERROR;
 
@@ -10380,9 +10548,9 @@
         }
         sp<MmapStreamCallback> callback = mCallback.promote();
         if (mDeviceId != deviceId && callback != 0) {
-            mLock.unlock();
+            mutex().unlock();
             callback->onRoutingChanged(deviceId);
-            mLock.lock();
+            mutex().lock();
         }
         mPatch = *patch;
         mDeviceId = deviceId;
@@ -10393,7 +10561,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;
 
@@ -10415,7 +10583,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()) {
@@ -10429,14 +10597,14 @@
     }
 }
 
-status_t AudioFlinger::MmapThread::addEffectChain_l(const sp<EffectChain>& 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();
@@ -10453,7 +10621,7 @@
     return NO_ERROR;
 }
 
-size_t AudioFlinger::MmapThread::removeEffectChain_l(const sp<EffectChain>& chain)
+size_t MmapThread::removeEffectChain_l(const sp<IAfEffectChain>& chain)
 {
     audio_session_t session = chain->sessionId();
 
@@ -10464,7 +10632,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();
@@ -10476,29 +10644,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
@@ -10524,7 +10692,7 @@
         return BAD_VALUE;
     }
 
-    if (EffectModule::isHapticGenerator(&desc->type)) {
+    if (IAfEffectModule::isHapticGenerator(&desc->type)) {
         ALOGE("%s(): HapticGenerator is not supported for MmapThread", __func__);
         return BAD_VALUE;
     }
@@ -10532,11 +10700,11 @@
     return NO_ERROR;
 }
 
-void AudioFlinger::MmapThread::checkInvalidTracks_l()
-NO_THREAD_SAFETY_ANALYSIS  // release and re-acquire mLock
+void MmapThread::checkInvalidTracks_l()
+NO_THREAD_SAFETY_ANALYSIS  // release and re-acquire mutex()
 {
     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) {
@@ -10547,13 +10715,13 @@
         }
     }
     if (callback != 0) {
-        mLock.unlock();
+        mutex().unlock();
         callback->onRoutingChanged(AUDIO_PORT_HANDLE_NONE);
-        mLock.lock();
+        mutex().lock();
     }
 }
 
-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);
@@ -10563,7 +10731,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();
@@ -10573,7 +10741,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 */);
         }
@@ -10583,10 +10751,17 @@
     write(fd, result.c_str(), 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),
@@ -10594,8 +10769,8 @@
 {
     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();
     if (mAudioHwDev) {
         if (mAudioHwDev->canSetMasterVolume()) {
             mMasterVolume = 1.0;
@@ -10607,7 +10782,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,
@@ -10618,17 +10793,17 @@
     mStreamType = streamType;
 }
 
-AudioStreamOut* AudioFlinger::MmapPlaybackThread::clearOutput()
+AudioStreamOut* MmapPlaybackThread::clearOutput()
 {
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mutex());
     AudioStreamOut *output = mOutput;
     mOutput = NULL;
     return output;
 }
 
-void AudioFlinger::MmapPlaybackThread::setMasterVolume(float value)
+void MmapPlaybackThread::setMasterVolume(float value)
 {
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mutex());
     // Don't apply master volume in SW if our HAL can do it for us.
     if (mAudioHwDev &&
             mAudioHwDev->canSetMasterVolume()) {
@@ -10638,9 +10813,9 @@
     }
 }
 
-void AudioFlinger::MmapPlaybackThread::setMasterMute(bool muted)
+void MmapPlaybackThread::setMasterMute(bool muted)
 {
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mutex());
     // Don't apply master mute in SW if our HAL can do it for us.
     if (mAudioHwDev && mAudioHwDev->canSetMasterMute()) {
         mMasterMute = false;
@@ -10649,49 +10824,49 @@
     }
 }
 
-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);
+    audio_utils::lock_guard _l(mutex());
     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);
+    audio_utils::lock_guard _l(mutex());
     if (stream == mStreamType) {
         return mStreamVolume;
     }
     return 0.0f;
 }
 
-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);
+    audio_utils::lock_guard _l(mutex());
     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);
+    audio_utils::lock_guard _l(mutex());
     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);
+    audio_utils::lock_guard _l(mutex());
     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;
@@ -10706,7 +10881,7 @@
     }
 }
 
-void AudioFlinger::MmapPlaybackThread::processVolume_l()
+void MmapPlaybackThread::processVolume_l()
 NO_THREAD_SAFETY_ANALYSIS // access of track->processMuteEvent_l
 {
     float volume;
@@ -10738,9 +10913,9 @@
             if (callback != 0) {
                 mHalVolFloat = volume; // SW volume control worked, so update value.
                 mNoCallbackWarningCount = 0;
-                mLock.unlock();
+                mutex().unlock();
                 callback->onVolumeChanged(volume);
-                mLock.lock();
+                mutex().lock();
             } else {
                 if (mNoCallbackWarningCount < kMaxNoCallbackWarnings) {
                     ALOGW("Could not set MMAP stream volume: no volume callback!");
@@ -10748,9 +10923,9 @@
                 }
             }
         }
-        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,
@@ -10762,13 +10937,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 = {
@@ -10787,7 +10962,7 @@
     return change;
 };
 
-void AudioFlinger::MmapPlaybackThread::checkSilentMode_l()
+void MmapPlaybackThread::checkSilentMode_l()
 {
     if (!mMasterMute) {
         char value[PROPERTY_VALUE_MAX];
@@ -10804,7 +10979,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) {
@@ -10813,8 +10988,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;
@@ -10827,7 +11002,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) {
@@ -10837,8 +11012,8 @@
     return NO_ERROR;
 }
 
-// startMelComputation_l() must be called with AudioFlinger::mLock held
-void AudioFlinger::MmapPlaybackThread::startMelComputation_l(
+// startMelComputation_l() must be called with AudioFlinger::mutex() held
+void MmapPlaybackThread::startMelComputation_l(
         const sp<audio_utils::MelProcessor>& processor)
 {
     ALOGV("%s: starting mel processor for thread %d", __func__, id());
@@ -10851,8 +11026,8 @@
     // assigned constant for each thread
 }
 
-// stopMelComputation_l() must be called with AudioFlinger::mLock held
-void AudioFlinger::MmapPlaybackThread::stopMelComputation_l()
+// stopMelComputation_l() must be called with AudioFlinger::mutex() held
+void MmapPlaybackThread::stopMelComputation_l()
 {
     ALOGV("%s: pausing mel processor for thread %d", __func__, id());
     auto melProcessor = mMelProcessor.load();
@@ -10861,7 +11036,7 @@
     }
 }
 
-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);
 
@@ -10870,17 +11045,24 @@
     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()
@@ -10891,16 +11073,15 @@
     return MmapThread::exitStandby_l();
 }
 
-AudioFlinger::AudioStreamIn* AudioFlinger::MmapCaptureThread::clearInput()
+AudioStreamIn* MmapCaptureThread::clearInput()
 {
-    Mutex::Autolock _l(mLock);
+    audio_utils::lock_guard _l(mutex());
     AudioStreamIn *input = mInput;
     mInput = NULL;
     return input;
 }
 
-
-void AudioFlinger::MmapCaptureThread::processVolume_l()
+void MmapCaptureThread::processVolume_l()
 {
     bool changed = false;
     bool silenced = false;
@@ -10927,13 +11108,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 = {
@@ -10950,9 +11131,9 @@
     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);
+    audio_utils::lock_guard _l(mutex());
     for (size_t i = 0; i < mActiveTracks.size() ; i++) {
         if (mActiveTracks[i]->portId() == portId) {
             mActiveTracks[i]->setSilenced_l(silenced);
@@ -10962,7 +11143,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) {
@@ -10971,8 +11152,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;
@@ -10982,12 +11163,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;
@@ -11019,7 +11207,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 6795a13..0a960c4 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -15,37 +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
 
-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 {
@@ -71,26 +77,24 @@
 
     // Config event sequence by client if status needed (e.g binder thread calling setParameters()):
     //  1. create SetParameterConfigEvent. This sets mWaitStatus in config event
-    //  2. Lock mLock
+    //  2. Lock mutex()
     //  3. Call sendConfigEvent_l(): Append to mConfigEvents and mWaitWorkCV.signal
     //  4. sendConfigEvent_l() reads status from event->mStatus;
     //  5. sendConfigEvent_l() returns status
     //  6. Unlock
     //
     // Parameter sequence by server: threadLoop calling processConfigEvents_l():
-    // 1. Lock mLock
+    // 1. Lock mutex()
     // 2. If there is an entry in mConfigEvents proceed ...
     // 3. Read first entry in mConfigEvents
     // 4. Remove first entry from mConfigEvents
     // 5. Process
     // 6. Set event->mStatus
-    // 7. event->mCond.signal
+    // 7. event->mCondition.notify_one()
     // 8. Unlock
 
     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) {
@@ -99,9 +103,10 @@
             }
         }
 
+        audio_utils::mutex& mutex() const { return mMutex; }
         const int mType; // event type e.g. CFG_EVENT_IO
-        Mutex mLock;     // mutex associated with mCond
-        Condition mCond; // condition for status return
+        mutable audio_utils::mutex mMutex; // mutex associated with mCondition
+        audio_utils::condition_variable mCondition; // condition for status return
         status_t mStatus; // status communicated to sender
         bool mWaitStatus; // true if sender is waiting for status
         bool mRequiresSystemReady; // true if must wait for system ready to enter event queue
@@ -134,7 +139,6 @@
             ConfigEvent(CFG_EVENT_IO) {
             mData = new IoConfigEventData(event, pid, portId);
         }
-        virtual ~IoConfigEvent() {}
     };
 
     class PrioConfigEventData : public ConfigEventData {
@@ -159,7 +163,6 @@
             ConfigEvent(CFG_EVENT_PRIO, true) {
             mData = new PrioConfigEventData(pid, tid, prio, forApp);
         }
-        virtual ~PrioConfigEvent() {}
     };
 
     class SetParameterConfigEventData : public ConfigEventData {
@@ -181,7 +184,6 @@
             mData = new SetParameterConfigEventData(keyValuePairs);
             mWaitStatus = true;
         }
-        virtual ~SetParameterConfigEvent() {}
     };
 
     class CreateAudioPatchConfigEventData : public ConfigEventData {
@@ -206,7 +208,6 @@
             mData = new CreateAudioPatchConfigEventData(patch, handle);
             mWaitStatus = true;
         }
-        virtual ~CreateAudioPatchConfigEvent() {}
     };
 
     class ReleaseAudioPatchConfigEventData : public ConfigEventData {
@@ -228,7 +229,6 @@
             mData = new ReleaseAudioPatchConfigEventData(handle);
             mWaitStatus = true;
         }
-        virtual ~ReleaseAudioPatchConfigEvent() {}
     };
 
     class UpdateOutDevicesConfigEventData : public ConfigEventData {
@@ -249,8 +249,6 @@
             ConfigEvent(CFG_EVENT_UPDATE_OUT_DEVICE) {
             mData = new UpdateOutDevicesConfigEventData(outDevices);
         }
-
-        virtual ~UpdateOutDevicesConfigEvent();
     };
 
     class ResizeBufferConfigEventData : public ConfigEventData {
@@ -271,8 +269,6 @@
             ConfigEvent(CFG_EVENT_RESIZE_BUFFER) {
             mData = new ResizeBufferConfigEventData(maxSharedAudioHistoryMs);
         }
-
-        virtual ~ResizeBufferConfigEvent() {}
     };
 
     class CheckOutputStageEffectsEvent : public ConfigEvent {
@@ -280,8 +276,6 @@
         CheckOutputStageEffectsEvent() :
             ConfigEvent(CFG_EVENT_CHECK_OUTPUT_STAGE_EFFECTS) {
         }
-
-        virtual ~CheckOutputStageEffectsEvent() {}
     };
 
     class HalLatencyModesChangedEvent : public ConfigEvent {
@@ -289,8 +283,6 @@
         HalLatencyModesChangedEvent() :
             ConfigEvent(CFG_EVENT_HAL_LATENCY_MODES_CHANGED) {
         }
-
-        virtual ~HalLatencyModesChangedEvent() {}
     };
 
 
@@ -308,109 +300,88 @@
         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;
-                // sendConfigEvent_l() must be called with ThreadBase::mLock held
+    void exit() final;
+    status_t setParameters(const String8& keyValuePairs) final;
+
+                // sendConfigEvent_l() must be called with ThreadBase::mutex() 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<EffectHandle> createEffect_l(
-                                    const sp<AudioFlinger::Client>& client,
+    sp<IAfEffectHandle> createEffect_l(
+                                    const sp<Client>& client,
                                     const sp<media::IEffectClient>& effectClient,
                                     int32_t priority,
                                     audio_session_t sessionId,
@@ -419,7 +390,8 @@
                                     status_t *status /*non-NULL*/,
                                     bool pinned,
                                     bool probe,
-                                    bool notifyFramesProcessed);
+                                    bool notifyFramesProcessed) final
+            REQUIRES(audio_utils::AudioFlinger_Mutex);
 
                 // return values for hasAudioSession (bit field)
                 enum effect_state {
@@ -435,48 +407,42 @@
                                                // bit-perfect track
                 };
 
-                // get effect chain corresponding to session Id.
-                sp<EffectChain> getEffectChain(audio_session_t sessionId);
-                // same as getEffectChain() but must be called with ThreadBase mutex locked
-                sp<EffectChain> 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<EffectChain>& chain) = 0;
-                // remove an effect chain from the chain list (mEffectChains)
-    virtual     size_t removeEffectChain_l(const sp<EffectChain>& 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<EffectChain> >& effectChains);
+    void lockEffectChains_l(Vector<sp<IAfEffectChain>>& effectChains) final;
                 // unlock effect chains after process
-                void unlockEffectChains(const Vector< sp<EffectChain> >& effectChains);
+    void unlockEffectChains(const Vector<sp<IAfEffectChain>>& effectChains) final;
                 // get a copy of mEffectChains vector
-                Vector< sp<EffectChain> > 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<AudioFlinger::EffectModule> getEffect(audio_session_t sessionId, int effectId);
-                sp<AudioFlinger::EffectModule> 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< EffectModule>& effect);
+    status_t addEffect_ll(const sp<IAfEffectModule>& effect) final
+            REQUIRES(audio_utils::AudioFlinger_Mutex, mutex());
                 // remove and effect module. Also removes the effect chain is this was the last
                 // effect
-                void removeEffect_l(const sp< EffectModule>& 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(EffectHandle *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 {
-                    Mutex::Autolock _l(mLock);
+    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 {
+                    std::lock_guard _l(mutex());
                     return hasAudioSession_l(sessionId);
                 }
 
@@ -487,7 +453,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()) {
@@ -509,19 +475,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,
@@ -529,37 +493,36 @@
                 // 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;
 
-    mutable     Mutex                   mLock;
+    audio_utils::mutex& mutex() const final RETURN_CAPABILITY(audio_utils::ThreadBase_Mutex) {
+        return mMutex;
+    }
+    mutable audio_utils::mutex mMutex;
 
-                void onEffectEnable(const sp<EffectModule>& 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 { }
+                // invalidateTracksForAudioSession_l must be called with holding mutex().
+    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 {
-                    Mutex::Autolock _l(mLock);
+    void invalidateTracksForAudioSession(audio_session_t sessionId) const final {
+                    std::lock_guard _l(mutex());
                     invalidateTracksForAudioSession_l(sessionId);
                 }
 
@@ -567,17 +530,17 @@
                 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
+            REQUIRES(audio_utils::AudioFlinger_Mutex);
+    void stopMelComputation_l() override
+            REQUIRES(audio_utils::AudioFlinger_Mutex);
 
 protected:
 
@@ -601,13 +564,13 @@
                 // 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,
                                                       audio_session_t sessionId);
                 // check if some effects must be suspended when an effect chain is added
-                void checkSuspendOnAddEffectChain_l(const sp<EffectChain>& chain);
+                void checkSuspendOnAddEffectChain_l(const sp<IAfEffectChain>& chain);
 
                 // sends the metadata of the active tracks to the HAL
                 struct MetadataUpdate {
@@ -627,8 +590,10 @@
                                     ExtendedTimestamp *timestamp __unused) const {
                                 return INVALID_OPERATION;
                             }
-
+public:
+// TODO(b/291317898) organize with publics
                 product_strategy_t getStrategyForStream(audio_stream_type_t stream) const;
+protected:
 
     virtual     void        onHalLatencyModesChanged_l() {}
 
@@ -636,15 +601,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;
+                audio_utils::condition_variable mWaitWorkCV;
 
-                const sp<AudioFlinger>  mAudioFlinger;
+                const sp<IAfThreadCallback>  mAfThreadCallback;
                 ThreadMetrics           mThreadMetrics;
                 const bool              mIsOut;
 
@@ -680,7 +642,7 @@
                 audio_source_t          mAudioSource;
 
                 const audio_io_handle_t mId;
-                Vector< sp<EffectChain> > mEffectChains;
+                Vector<sp<IAfEffectChain>> mEffectChains;
 
                 static const int        kThreadNameLength = 16; // prctl(PR_SET_NAME) limit
                 char                    mThreadName[kThreadNameLength]; // guaranteed NUL-terminated
@@ -781,7 +743,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 {
@@ -844,35 +806,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
@@ -880,7 +821,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;
 
@@ -890,19 +830,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()
@@ -912,14 +856,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
@@ -927,18 +871,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();
@@ -953,30 +900,29 @@
     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(
-                                const sp<AudioFlinger::Client>& client,
+    sp<IAfTrack> createTrack_l(
+                                const sp<Client>& client,
                                 audio_stream_type_t streamType,
                                 const audio_attributes_t& attr,
                                 uint32_t *sampleRate,
@@ -996,15 +942,21 @@
                                 audio_port_handle_t portId,
                                 const sp<media::IAudioTrackCallback>& callback,
                                 bool isSpatialized,
-                                bool isBitPerfect);
+                                bool isBitPerfect) final
+            REQUIRES(audio_utils::AudioFlinger_Mutex);
 
-                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
@@ -1012,124 +964,130 @@
                                         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<EffectChain>& chain);
-                virtual size_t removeEffectChain_l(const sp<EffectChain>& 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) {
-                    Mutex::Autolock _l(mLock);
+    void setDownStreamPatch(const struct audio_patch* patch) final {
+                    std::lock_guard _l(mutex());
                     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
+            REQUIRES(audio_utils::AudioFlinger_Mutex);
+    void stopMelComputation_l() override
+            REQUIRES(audio_utils::AudioFlinger_Mutex);
 
-                void setStandby() {
-                    Mutex::Autolock _l(mLock);
+    void setStandby() final {
+                    std::lock_guard _l(mutex());
                     setStandby_l();
                 }
 
-                void setStandby_l() {
+    void setStandby_l() final {
                     mStandby = true;
                     mHalStarted = false;
                     mKernelPositionOnStandby =
                         mTimestamp.mPosition[ExtendedTimestamp::LOCATION_KERNEL];
                 }
 
-                bool waitForHalStart() {
-                    Mutex::Autolock _l(mLock);
+    bool waitForHalStart() final {
+                    audio_utils::unique_lock _l(mutex());
                     static const nsecs_t kWaitHalTimeoutNs = seconds(2);
                     nsecs_t endWaitTimetNs = systemTime() + kWaitHalTimeoutNs;
                     while (!mHalStarted) {
@@ -1138,7 +1096,7 @@
                             break;
                         }
                         nsecs_t waitTimeLeftNs = endWaitTimetNs - timeNs;
-                        mWaitHalStartCV.waitRelative(mLock, waitTimeLeftNs);
+                        mWaitHalStartCV.wait_for(_l, std::chrono::nanoseconds(waitTimeLeftNs));
                     }
                     return mHalStarted;
                 }
@@ -1243,7 +1201,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.
@@ -1257,8 +1214,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
@@ -1268,7 +1224,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() { }
@@ -1286,26 +1242,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;
@@ -1363,9 +1316,10 @@
         SortedVector<sp<T>> mTracks; // wrapped SortedVector.
     };
 
-    Tracks<Track>                   mTracks;
+    Tracks<IAfTrack>                   mTracks;
 
     stream_type_t                   mStreamTypes[AUDIO_STREAM_CNT];
+
     AudioStreamOut                  *mOutput;
 
     float                           mMasterVolume;
@@ -1420,19 +1374,21 @@
     // 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;
+    audio_utils::mutex& audioTrackCbMutex() const { return mAudioTrackCbMutex; }
+    mutable audio_utils::mutex mAudioTrackCbMutex;
     // 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;
@@ -1443,21 +1399,21 @@
 
     // output stream start detection based on render position returned by the kernel
     // condition signalled when the output stream has started
-    Condition                mWaitHalStartCV;
+    audio_utils::condition_variable mWaitHalStartCV;
     // true when the output stream render position has moved, reset to false in standby
     bool                     mHalStarted = false;
     // last kernel render position saved when entering standby
     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;
@@ -1508,36 +1464,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(
@@ -1548,15 +1503,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
 
@@ -1632,17 +1587,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
 
@@ -1662,7 +1621,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();
@@ -1675,16 +1634,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;
@@ -1716,7 +1675,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() {};
@@ -1724,7 +1683,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();
@@ -1742,11 +1701,8 @@
 
 class AsyncCallbackThread : public Thread {
 public:
-
     explicit AsyncCallbackThread(const wp<PlaybackThread>& playbackThread);
 
-    virtual             ~AsyncCallbackThread();
-
     // Thread virtuals
     virtual bool        threadLoop();
 
@@ -1770,21 +1726,28 @@
     // setDraining(). The sequence is shifted one bit to the left and the lsb is used
     // to indicate that the callback has been received via resetDraining()
     uint32_t                   mDrainSequence;
-    Condition                  mWaitWorkCV;
-    Mutex                      mLock;
+    audio_utils::condition_variable mWaitWorkCV;
+    mutable audio_utils::mutex mMutex;
     bool                       mAsyncError;
+
+    audio_utils::mutex& mutex() const { return mMutex; }
 };
 
-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;
@@ -1811,8 +1774,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(
@@ -1835,110 +1798,65 @@
 
 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
             audio_latency_mode_t mRequestedLatencyMode = AUDIO_LATENCY_MODE_FREE;
 
-            sp<EffectHandle> mFinalDownMixer;
+            sp<IAfEffectHandle> mFinalDownMixer;
 };
 
 // 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(
-                    const sp<AudioFlinger::Client>& client,
+    sp<IAfRecordTrack> createRecordTrack_l(
+                    const sp<Client>& client,
                     const audio_attributes_t& attr,
                     uint32_t *pSampleRate,
                     audio_format_t format,
@@ -1952,17 +1870,20 @@
                     pid_t tid,
                     status_t *status /*non-NULL*/,
                     audio_port_handle_t portId,
-                    int32_t maxSharedAudioHistoryMs);
+                    int32_t maxSharedAudioHistoryMs) final
+            REQUIRES(audio_utils::AudioFlinger_Mutex);
 
-            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;
 
 
@@ -1970,22 +1891,22 @@
                                                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<EffectChain>& chain);
-    virtual size_t removeEffectChain_l(const sp<EffectChain>& chain);
+    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 {
                          return ThreadBase::hasAudioSession_l(sessionId, mTracks);
                      }
@@ -2001,7 +1922,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,
@@ -2012,20 +1933,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.
@@ -2035,15 +1956,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);
                         }
 
@@ -2065,12 +1986,12 @@
 
             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;
+            // is used together with mStartStopCV to indicate start()/stop() progress
+            ActiveTracks<IAfRecordTrack>           mActiveTracks;
 
-            Condition                           mStartStopCond;
+            audio_utils::condition_variable mStartStopCV;
 
             // resampler converts input at HAL Hz to output at AudioRecord client Hz
             void                               *mRsmpInBuffer;  // size = mRsmpInFramesOA
@@ -2135,90 +2056,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(mutex());
 
-    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<EffectChain>& chain);
-    virtual     size_t      removeEffectChain_l(const sp<EffectChain>& 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;
@@ -2241,8 +2157,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
@@ -2257,7 +2173,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;
 
@@ -2265,56 +2181,61 @@
      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
+            REQUIRES(audio_utils::AudioFlinger_Mutex);
+    void stopMelComputation_l() final
+            REQUIRES(audio_utils::AudioFlinger_Mutex);
 
 protected:
-                void        dumpInternals_l(int fd, const Vector<String16>& args) override;
+    void dumpInternals_l(int fd, const Vector<String16>& args) final;
 
                 audio_stream_type_t         mStreamType;
                 float                       mMasterVolume;
@@ -2326,28 +2247,29 @@
                 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(mutex()) 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);
                                }
 
@@ -2358,15 +2280,17 @@
 
 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;
     float mVolumeLeft = 0.f;
     float mVolumeRight = 0.f;
 };
+
+} // namespace android
diff --git a/services/audioflinger/TrackBase.h b/services/audioflinger/TrackBase.h
index d5b6a98..4e37953 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,10 +231,10 @@
      *          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(); }
 
 protected:
     DISALLOW_COPY_AND_ASSIGN(TrackBase);
@@ -285,31 +251,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;
     }
 
@@ -351,7 +317,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;
@@ -415,37 +381,28 @@
     std::atomic_flag    mChangeNotified = ATOMIC_FLAG_INIT;
 };
 
-// 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:
@@ -453,5 +410,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 30c8240..31246ec 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);
+        audio_utils::lock_guard _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;
 }
@@ -337,14 +341,58 @@
 #undef LOG_TAG
 #define LOG_TAG "AF::TrackHandle"
 
-AudioFlinger::TrackHandle::TrackHandle(const sp<AudioFlinger::PlaybackThread::Track>& track)
+class TrackHandle : public android::media::BnAudioTrack {
+public:
+    explicit TrackHandle(const sp<IAfTrack>& track);
+    ~TrackHandle() override;
+
+    binder::Status getCblk(std::optional<media::SharedFileRegion>* _aidl_return) final;
+    binder::Status start(int32_t* _aidl_return) final;
+    binder::Status stop() final;
+    binder::Status flush() final;
+    binder::Status pause() final;
+    binder::Status attachAuxEffect(int32_t effectId, int32_t* _aidl_return) final;
+    binder::Status setParameters(const std::string& keyValuePairs,
+                                 int32_t* _aidl_return) final;
+    binder::Status selectPresentation(int32_t presentationId, int32_t programId,
+                                      int32_t* _aidl_return) final;
+    binder::Status getTimestamp(media::AudioTimestampInternal* timestamp,
+                                int32_t* _aidl_return) final;
+    binder::Status signal() final;
+    binder::Status applyVolumeShaper(const media::VolumeShaperConfiguration& configuration,
+                                     const media::VolumeShaperOperation& operation,
+                                     int32_t* _aidl_return) final;
+    binder::Status getVolumeShaperState(
+            int32_t id,
+            std::optional<media::VolumeShaperState>* _aidl_return) final;
+    binder::Status getDualMonoMode(
+            media::audio::common::AudioDualMonoMode* _aidl_return) final;
+    binder::Status setDualMonoMode(
+            media::audio::common::AudioDualMonoMode mode) final;
+    binder::Status getAudioDescriptionMixLevel(float* _aidl_return) final;
+    binder::Status setAudioDescriptionMixLevel(float leveldB) final;
+    binder::Status getPlaybackRateParameters(
+            media::audio::common::AudioPlaybackRate* _aidl_return) final;
+    binder::Status setPlaybackRateParameters(
+            const media::audio::common::AudioPlaybackRate& playbackRate) final;
+
+private:
+    const sp<IAfTrack> mTrack;
+};
+
+/* static */
+sp<media::IAudioTrack> IAfTrack::createIAudioTrackAdapter(const sp<IAfTrack>& track) {
+    return sp<TrackHandle>::make(track);
+}
+
+TrackHandle::TrackHandle(const sp<IAfTrack>& track)
     : BnAudioTrack(),
       mTrack(track)
 {
     setMinSchedulerPolicy(SCHED_NORMAL, ANDROID_PRIORITY_AUDIO);
 }
 
-AudioFlinger::TrackHandle::~TrackHandle() {
+TrackHandle::~TrackHandle() {
     // just stop the track on deletion, associated resources
     // will be freed from the main thread once all pending buffers have
     // been played. Unless it's not in the active track list, in which
@@ -352,51 +400,51 @@
     mTrack->destroy();
 }
 
-Status AudioFlinger::TrackHandle::getCblk(
+Status TrackHandle::getCblk(
         std::optional<media::SharedFileRegion>* _aidl_return) {
     *_aidl_return = legacy2aidl_NullableIMemory_SharedFileRegion(mTrack->getCblk()).value();
     return Status::ok();
 }
 
-Status AudioFlinger::TrackHandle::start(int32_t* _aidl_return) {
+Status TrackHandle::start(int32_t* _aidl_return) {
     *_aidl_return = mTrack->start();
     return Status::ok();
 }
 
-Status AudioFlinger::TrackHandle::stop() {
+Status TrackHandle::stop() {
     mTrack->stop();
     return Status::ok();
 }
 
-Status AudioFlinger::TrackHandle::flush() {
+Status TrackHandle::flush() {
     mTrack->flush();
     return Status::ok();
 }
 
-Status AudioFlinger::TrackHandle::pause() {
+Status TrackHandle::pause() {
     mTrack->pause();
     return Status::ok();
 }
 
-Status AudioFlinger::TrackHandle::attachAuxEffect(int32_t effectId,
+Status TrackHandle::attachAuxEffect(int32_t effectId,
                                                   int32_t* _aidl_return) {
     *_aidl_return = mTrack->attachAuxEffect(effectId);
     return Status::ok();
 }
 
-Status AudioFlinger::TrackHandle::setParameters(const std::string& keyValuePairs,
+Status TrackHandle::setParameters(const std::string& keyValuePairs,
                                                 int32_t* _aidl_return) {
     *_aidl_return = mTrack->setParameters(String8(keyValuePairs.c_str()));
     return Status::ok();
 }
 
-Status AudioFlinger::TrackHandle::selectPresentation(int32_t presentationId, int32_t programId,
+Status TrackHandle::selectPresentation(int32_t presentationId, int32_t programId,
                                                      int32_t* _aidl_return) {
     *_aidl_return = mTrack->selectPresentation(presentationId, programId);
     return Status::ok();
 }
 
-Status AudioFlinger::TrackHandle::getTimestamp(media::AudioTimestampInternal* timestamp,
+Status TrackHandle::getTimestamp(media::AudioTimestampInternal* timestamp,
                                                int32_t* _aidl_return) {
     AudioTimestamp legacy;
     *_aidl_return = mTrack->getTimestamp(legacy);
@@ -407,12 +455,12 @@
     return Status::ok();
 }
 
-Status AudioFlinger::TrackHandle::signal() {
+Status TrackHandle::signal() {
     mTrack->signal();
     return Status::ok();
 }
 
-Status AudioFlinger::TrackHandle::applyVolumeShaper(
+Status TrackHandle::applyVolumeShaper(
         const media::VolumeShaperConfiguration& configuration,
         const media::VolumeShaperOperation& operation,
         int32_t* _aidl_return) {
@@ -432,7 +480,7 @@
     return Status::ok();
 }
 
-Status AudioFlinger::TrackHandle::getVolumeShaperState(
+Status TrackHandle::getVolumeShaperState(
         int32_t id,
         std::optional<media::VolumeShaperState>* _aidl_return) {
     sp<VolumeShaper::State> legacy = mTrack->getVolumeShaperState(id);
@@ -446,7 +494,7 @@
     return Status::ok();
 }
 
-Status AudioFlinger::TrackHandle::getDualMonoMode(
+Status TrackHandle::getDualMonoMode(
         media::audio::common::AudioDualMonoMode* _aidl_return)
 {
     audio_dual_mono_mode_t mode = AUDIO_DUAL_MONO_MODE_OFF;
@@ -459,7 +507,7 @@
     return binderStatusFromStatusT(status);
 }
 
-Status AudioFlinger::TrackHandle::setDualMonoMode(
+Status TrackHandle::setDualMonoMode(
         media::audio::common::AudioDualMonoMode mode)
 {
     const auto localMonoMode = VALUE_OR_RETURN_BINDER_STATUS(
@@ -468,7 +516,7 @@
             ?: mTrack->setDualMonoMode(localMonoMode));
 }
 
-Status AudioFlinger::TrackHandle::getAudioDescriptionMixLevel(float* _aidl_return)
+Status TrackHandle::getAudioDescriptionMixLevel(float* _aidl_return)
 {
     float leveldB = -std::numeric_limits<float>::infinity();
     const status_t status = mTrack->getAudioDescriptionMixLevel(&leveldB)
@@ -477,13 +525,13 @@
     return binderStatusFromStatusT(status);
 }
 
-Status AudioFlinger::TrackHandle::setAudioDescriptionMixLevel(float leveldB)
+Status TrackHandle::setAudioDescriptionMixLevel(float leveldB)
 {
     return binderStatusFromStatusT(AudioValidator::validateAudioDescriptionMixLevel(leveldB)
              ?: mTrack->setAudioDescriptionMixLevel(leveldB));
 }
 
-Status AudioFlinger::TrackHandle::getPlaybackRateParameters(
+Status TrackHandle::getPlaybackRateParameters(
         media::audio::common::AudioPlaybackRate* _aidl_return)
 {
     audio_playback_rate_t localPlaybackRate{};
@@ -496,7 +544,7 @@
     return binderStatusFromStatusT(status);
 }
 
-Status AudioFlinger::TrackHandle::setPlaybackRateParameters(
+Status TrackHandle::setPlaybackRateParameters(
         const media::audio::common::AudioPlaybackRate& playbackRate)
 {
     const audio_playback_rate_t localPlaybackRate = VALUE_OR_RETURN_BINDER_STATUS(
@@ -510,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)
 {
@@ -542,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),
@@ -555,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);
@@ -563,7 +609,7 @@
     mOpCallback.clear();
 }
 
-void AudioFlinger::PlaybackThread::OpPlayAudioMonitor::onFirstRef()
+void OpPlayAudioMonitor::onFirstRef()
 {
     // make sure not to broadcast the initial state since it is not needed and could
     // cause a deadlock since this method can be called with the mThread->mLock held
@@ -575,14 +621,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(bool doBroadcast)
+void OpPlayAudioMonitor::checkPlayAudioForUsage(bool doBroadcast)
 {
     const bool hasAppOps = mAttributionSource.packageName.has_value()
         && mAppOpsManager.checkAudioOpNoThrow(
@@ -594,20 +640,20 @@
         ALOGD("OpPlayAudio: track:%d usage:%d %smuted", mId, mUsage, hasAppOps ? "not " : "");
         if (doBroadcast) {
             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);
+                audio_utils::lock_guard _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);
@@ -621,7 +667,7 @@
 }
 
 // static
-void AudioFlinger::PlaybackThread::OpPlayAudioMonitor::getPackagesForUid(
+void OpPlayAudioMonitor::getPackagesForUid(
     uid_t uid, Vector<String16>& packages)
 {
     PermissionController permissionController;
@@ -632,9 +678,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,
@@ -668,7 +762,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),
@@ -725,15 +819,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);
@@ -758,7 +852,7 @@
     mTrackMetrics.logConstructor(creatorPid, uid, id(), traits, streamType);
 }
 
-AudioFlinger::PlaybackThread::Track::~Track()
+Track::~Track()
 {
     ALOGV("%s(%d)", __func__, mId);
 
@@ -771,7 +865,7 @@
     }
 }
 
-status_t AudioFlinger::PlaybackThread::Track::initCheck() const
+status_t Track::initCheck() const
 {
     status_t status = TrackBase::initCheck();
     if (status == NO_ERROR && mCblk == nullptr) {
@@ -780,7 +874,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
@@ -793,10 +887,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();
+            audio_utils::lock_guard _l(thread->mutex());
+            auto* const playbackThread = thread->asIAfPlaybackThread().get();
             wasActive = playbackThread->destroyTrack_l(this);
         }
         if (isExternalTrack() && !wasActive) {
@@ -806,7 +900,7 @@
     forEachTeePatchTrack([](auto patchTrack) { patchTrack->destroy(); });
 }
 
-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 "
@@ -817,7 +911,7 @@
                         isServerLatencySupported() ? "   Latency" : "");
 }
 
-void AudioFlinger::PlaybackThread::Track::appendDump(String8& result, bool active)
+void Track::appendDump(String8& result, bool active) const
 {
     char trackType;
     switch (mType) {
@@ -859,7 +953,7 @@
     }
 
     char fillingStatus;
-    switch (mFillingUpStatus) {
+    switch (mFillingStatus) {
     case FS_INVALID:
         fillingStatus = 'I';
         break;
@@ -945,12 +1039,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;
@@ -968,14 +1062,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;
@@ -985,12 +1079,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);
@@ -1006,7 +1100,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.
@@ -1015,12 +1109,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.
@@ -1037,14 +1131,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;
     }
@@ -1058,33 +1152,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);
-            sp<EffectChain> ec = thread->getEffectChain_l(mSessionId);
-            if (thread->mAudioFlinger->isNonOffloadableGlobalEffectEnabled_l() ||
+            audio_utils::lock_guard _laf(thread->afThreadCallback()->mutex());
+            audio_utils::lock_guard _lth(thread->mutex());
+            sp<IAfEffectChain> ec = thread->getEffectChain_l(mSessionId);
+            if (thread->afThreadCallback()->isNonOffloadableGlobalEffectEnabled_l() ||
                     (ec != 0 && ec->isNonOffloadableEnabled())) {
                 invalidate();
                 return PERMISSION_DENIED;
             }
         }
-        Mutex::Autolock _lth(thread->mLock);
+        audio_utils::lock_guard _lth(thread->mutex());
         track_state state = mState;
         // here the track could be either new, or restarted
         // in both cases "unstop" the track
@@ -1116,7 +1210,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)
@@ -1183,7 +1277,8 @@
         forEachTeePatchTrack([](auto patchTrack) { patchTrack->start(); });
 
         // 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>();
@@ -1202,17 +1297,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);
+        audio_utils::lock_guard _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()) {
@@ -1224,7 +1319,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();
@@ -1235,13 +1330,13 @@
     forEachTeePatchTrack([](auto patchTrack) { patchTrack->stop(); });
 }
 
-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();
+        audio_utils::lock_guard _l(thread->mutex());
+        auto* const playbackThread = thread->asIAfPlaybackThread().get();
         switch (mState) {
         case STOPPING_1:
         case STOPPING_2:
@@ -1272,18 +1367,18 @@
     forEachTeePatchTrack([](auto patchTrack) { patchTrack->pause(); });
 }
 
-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();
+        audio_utils::lock_guard _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();
         }
 
@@ -1322,7 +1417,7 @@
             if (isDirect()) {
                 mFlushHwPending = true;
             }
-            if (playbackThread->mActiveTracks.indexOf(this) < 0) {
+            if (!playbackThread->isTrackActive(this)) {
                 reset();
             }
         }
@@ -1336,7 +1431,7 @@
 }
 
 // must be called with thread lock held
-void AudioFlinger::PlaybackThread::Track::flushAck()
+void Track::flushAck()
 {
     if (!isOffloaded() && !isDirect()) {
         return;
@@ -1349,12 +1444,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.
@@ -1362,7 +1457,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;
@@ -1370,34 +1465,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)
 {
@@ -1405,16 +1501,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);
+            audio_utils::lock_guard _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.
 
@@ -1422,7 +1518,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;
@@ -1438,7 +1534,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) {
@@ -1510,7 +1606,7 @@
     *backInserter++ = metadata;
 }
 
-void AudioFlinger::PlaybackThread::Track::updateTeePatches() {
+void Track::updateTeePatches() {
     if (mTeePatchesToUpdate.has_value()) {
         forEachTeePatchTrack([](auto patchTrack) { patchTrack->destroy(); });
         mTeePatches = mTeePatchesToUpdate.value();
@@ -1522,14 +1618,14 @@
     }
 }
 
-void AudioFlinger::PlaybackThread::Track::setTeePatchesToUpdate(TeePatches teePatchesToUpdate) {
+void Track::setTeePatchesToUpdate(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) {
@@ -1561,31 +1657,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();
+    audio_utils::lock_guard _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) {
@@ -1601,14 +1698,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.
@@ -1651,7 +1748,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.
 
@@ -1683,14 +1780,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) {
@@ -1705,7 +1802,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));
@@ -1730,7 +1827,7 @@
     return vlr;
 }
 
-status_t AudioFlinger::PlaybackThread::Track::setSyncEvent(
+status_t Track::setSyncEvent(
         const sp<audioflinger::SyncEvent>& event)
 {
     if (isTerminated() || mState == PAUSED ||
@@ -1746,19 +1843,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;
@@ -1768,25 +1865,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();
+        audio_utils::lock_guard _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();
+            audio_utils::lock_guard _l(t->mutex());
+            status = t->getOutput_l()->stream->getDualMonoMode(mode);
             ALOGD_IF((status == NO_ERROR) && (mDualMonoMode != *mode),
                     "%s: mode %d inconsistent", __func__, mDualMonoMode);
         }
@@ -1794,15 +1891,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();
+            audio_utils::lock_guard lock(t->mutex());
+            status = t->getOutput_l()->stream->setDualMonoMode(mode);
             if (status == NO_ERROR) {
                 mDualMonoMode = mode;
             }
@@ -1811,15 +1908,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();
+            audio_utils::lock_guard lock(t->mutex());
+            status = t->getOutput_l()->stream->getAudioDescriptionMixLevel(leveldB);
             ALOGD_IF((status == NO_ERROR) && (mAudioDescriptionMixLevel != *leveldB),
                     "%s: level %.3f inconsistent", __func__, mAudioDescriptionMixLevel);
         }
@@ -1827,15 +1924,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();
+            audio_utils::lock_guard lock(t->mutex());
+            status = t->getOutput_l()->stream->setAudioDescriptionMixLevel(leveldB);
             if (status == NO_ERROR) {
                 mAudioDescriptionMixLevel = leveldB;
             }
@@ -1844,16 +1941,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();
+            audio_utils::lock_guard lock(t->mutex());
+            status = t->getOutput_l()->stream->getPlaybackRateParameters(playbackRate);
             ALOGD_IF((status == NO_ERROR) &&
                     !isAudioPlaybackRateEqual(mPlaybackRateParameters, *playbackRate),
                     "%s: playbackRate inconsistent", __func__);
@@ -1862,16 +1959,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();
+            audio_utils::lock_guard lock(t->mutex());
+            status = t->getOutput_l()->stream->setPlaybackRateParameters(playbackRate);
             if (status == NO_ERROR) {
                 mPlaybackRateParameters = playbackRate;
             }
@@ -1881,7 +1978,7 @@
 }
 
 //To be called with thread lock held
-bool AudioFlinger::PlaybackThread::Track::isResumePending() {
+bool Track::isResumePending() const {
     if (mState == RESUMING) {
         return true;
     }
@@ -1895,7 +1992,7 @@
 }
 
 //To be called with thread lock held
-void AudioFlinger::PlaybackThread::Track::resumeAck() {
+void Track::resumeAck() {
     if (mState == RESUMING) {
         mState = ACTIVE;
     }
@@ -1909,7 +2006,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.
@@ -1989,14 +2086,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();
+        audio_utils::lock_guard _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);
@@ -2006,13 +2103,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();
@@ -2022,9 +2119,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,
@@ -2041,7 +2157,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,
@@ -2059,13 +2175,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);
@@ -2078,7 +2194,7 @@
     return status;
 }
 
-void AudioFlinger::PlaybackThread::OutputTrack::stop()
+void OutputTrack::stop()
 {
     Track::stop();
     clearBufferQueue();
@@ -2086,11 +2202,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);
@@ -2108,7 +2224,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();
@@ -2197,8 +2313,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);
         }
     }
@@ -2212,7 +2328,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;
@@ -2235,22 +2351,22 @@
     }
 }
 
-void AudioFlinger::PlaybackThread::OutputTrack::copyMetadataTo(MetadataInserter& backInserter) const
+void OutputTrack::copyMetadataTo(MetadataInserter& backInserter) const
 {
-    std::lock_guard<std::mutex> lock(mTrackMetadatasMutex);
+    audio_utils::lock_guard lock(trackMetadataMutex());
     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);
+        audio_utils::lock_guard lock(trackMetadataMutex());
         mTrackMetadatas = metadatas;
     }
     // No need to adjust metadata track volumes as OutputTrack volumes are always 0dBFS.
     setMetadataHasChanged();
 }
 
-status_t AudioFlinger::PlaybackThread::OutputTrack::obtainBuffer(
+status_t OutputTrack::obtainBuffer(
         AudioBufferProvider::Buffer* buffer, uint32_t waitTimeMs)
 {
     ClientProxy::Buffer buf;
@@ -2264,7 +2380,7 @@
     return status;
 }
 
-void AudioFlinger::PlaybackThread::OutputTrack::clearBufferQueue()
+void OutputTrack::clearBufferQueue()
 {
     size_t size = mBufferQueue.size();
 
@@ -2276,7 +2392,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)) {
@@ -2288,7 +2404,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,
@@ -2307,7 +2454,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,
@@ -2315,12 +2462,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();
@@ -2329,7 +2476,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);
@@ -2341,7 +2488,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);
@@ -2367,7 +2514,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;
@@ -2377,7 +2524,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;
@@ -2394,7 +2541,7 @@
     return status;
 }
 
-void AudioFlinger::PlaybackThread::PatchTrack::releaseBuffer(Proxy::Buffer* buffer)
+void PatchTrack::releaseBuffer(Proxy::Buffer* buffer)
 {
     mProxy->releaseBuffer(buffer);
     restartIfDisabled();
@@ -2403,23 +2550,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);
@@ -2435,55 +2582,83 @@
 #undef LOG_TAG
 #define LOG_TAG "AF::RecordHandle"
 
-AudioFlinger::RecordHandle::RecordHandle(
-        const sp<AudioFlinger::RecordThread::RecordTrack>& recordTrack)
+class RecordHandle : public android::media::BnAudioRecord {
+public:
+    explicit RecordHandle(const sp<IAfRecordTrack>& recordTrack);
+    ~RecordHandle() override;
+    binder::Status start(int /*AudioSystem::sync_event_t*/ event,
+            int /*audio_session_t*/ triggerSession) final;
+    binder::Status stop() final;
+    binder::Status getActiveMicrophones(
+            std::vector<media::MicrophoneInfoFw>* activeMicrophones) final;
+    binder::Status setPreferredMicrophoneDirection(
+            int /*audio_microphone_direction_t*/ direction) final;
+    binder::Status setPreferredMicrophoneFieldDimension(float zoom) final;
+    binder::Status shareAudioHistory(
+            const std::string& sharedAudioPackageName, int64_t sharedAudioStartMs) final;
+
+private:
+    const sp<IAfRecordTrack> mRecordTrack;
+
+    // for use from destructor
+    void stop_nonvirtual();
+};
+
+/* static */
+sp<media::IAudioRecord> IAfRecordTrack::createIAudioRecordAdapter(
+        const sp<IAfRecordTrack>& recordTrack) {
+    return sp<RecordHandle>::make(recordTrack);
+}
+
+RecordHandle::RecordHandle(
+        const sp<IAfRecordTrack>& recordTrack)
     : BnAudioRecord(),
     mRecordTrack(recordTrack)
 {
     setMinSchedulerPolicy(SCHED_NORMAL, ANDROID_PRIORITY_AUDIO);
 }
 
-AudioFlinger::RecordHandle::~RecordHandle() {
+RecordHandle::~RecordHandle() {
     stop_nonvirtual();
     mRecordTrack->destroy();
 }
 
-binder::Status AudioFlinger::RecordHandle::start(int /*AudioSystem::sync_event_t*/ event,
+binder::Status RecordHandle::start(int /*AudioSystem::sync_event_t*/ event,
         int /*audio_session_t*/ triggerSession) {
     ALOGV("%s()", __func__);
     return binderStatusFromStatusT(
         mRecordTrack->start((AudioSystem::sync_event_t)event, (audio_session_t) triggerSession));
 }
 
-binder::Status AudioFlinger::RecordHandle::stop() {
+binder::Status RecordHandle::stop() {
     stop_nonvirtual();
     return binder::Status::ok();
 }
 
-void AudioFlinger::RecordHandle::stop_nonvirtual() {
+void RecordHandle::stop_nonvirtual() {
     ALOGV("%s()", __func__);
     mRecordTrack->stop();
 }
 
-binder::Status AudioFlinger::RecordHandle::getActiveMicrophones(
+binder::Status RecordHandle::getActiveMicrophones(
         std::vector<media::MicrophoneInfoFw>* activeMicrophones) {
     ALOGV("%s()", __func__);
     return binderStatusFromStatusT(mRecordTrack->getActiveMicrophones(activeMicrophones));
 }
 
-binder::Status AudioFlinger::RecordHandle::setPreferredMicrophoneDirection(
+binder::Status RecordHandle::setPreferredMicrophoneDirection(
         int /*audio_microphone_direction_t*/ direction) {
     ALOGV("%s()", __func__);
     return binderStatusFromStatusT(mRecordTrack->setPreferredMicrophoneDirection(
             static_cast<audio_microphone_direction_t>(direction)));
 }
 
-binder::Status AudioFlinger::RecordHandle::setPreferredMicrophoneFieldDimension(float zoom) {
+binder::Status RecordHandle::setPreferredMicrophoneFieldDimension(float zoom) {
     ALOGV("%s()", __func__);
     return binderStatusFromStatusT(mRecordTrack->setPreferredMicrophoneFieldDimension(zoom));
 }
 
-binder::Status AudioFlinger::RecordHandle::shareAudioHistory(
+binder::Status RecordHandle::shareAudioHistory(
         const std::string& sharedAudioPackageName, int64_t sharedAudioStartMs) {
     return binderStatusFromStatusT(
             mRecordTrack->shareAudioHistory(sharedAudioPackageName, sharedAudioStartMs));
@@ -2493,9 +2668,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,
@@ -2534,7 +2747,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.
@@ -2554,8 +2767,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);
@@ -2570,14 +2783,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) {
@@ -2587,7 +2800,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;
@@ -2601,12 +2814,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());
@@ -2614,27 +2827,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();
+            audio_utils::lock_guard _l(thread->mutex());
+            auto* const recordThread = thread->asIAfRecordThread().get();
             priorState = mState;
             if (!mSharedAudioPackageName.empty()) {
                 recordThread->resetAudioHistory_l();
@@ -2665,7 +2878,7 @@
     }
 }
 
-void AudioFlinger::RecordThread::RecordTrack::invalidate()
+void RecordTrack::invalidate()
 {
     TrackBase::invalidate();
     // FIXME should use proxy, and needs work
@@ -2677,7 +2890,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  "
@@ -2685,7 +2898,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 "
@@ -2724,26 +2937,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)
 {
@@ -2783,40 +2996,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();
@@ -2833,9 +3046,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) {
@@ -2847,7 +3060,7 @@
     }
 }
 
-void AudioFlinger::RecordThread::RecordTrack::copyMetadataTo(MetadataInserter& backInserter) const
+void RecordTrack::copyMetadataTo(MetadataInserter& backInserter) const
 {
 
     // Do not forward PatchRecord metadata with unspecified audio source
@@ -2871,7 +3084,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,
@@ -2888,7 +3127,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,
@@ -2896,7 +3135,7 @@
                                       (int)(mPeerTimeout.tv_nsec / 1000000));
 }
 
-AudioFlinger::RecordThread::PatchRecord::~PatchRecord()
+PatchRecord::~PatchRecord()
 {
     ALOGV("%s(%d)", __func__, mId);
 }
@@ -2920,7 +3159,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);
@@ -2935,7 +3174,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);
@@ -2957,7 +3196,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;
@@ -2967,13 +3206,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);
 }
@@ -2988,8 +3227,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,
@@ -3005,18 +3264,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();
+    audio_utils::lock_guard _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) {
@@ -3034,7 +3293,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.
 
@@ -3048,7 +3307,7 @@
     }
 
     {
-        std::lock_guard<std::mutex> lock(mReadLock);
+        audio_utils::lock_guard lock(readMutex());
         mReadBytes += bytesRead;
         mReadError = NO_ERROR;
     }
@@ -3075,14 +3334,14 @@
 stream_error:
     stream->standby();
     {
-        std::lock_guard<std::mutex> lock(mReadLock);
+        audio_utils::lock_guard lock(readMutex());
         mReadError = result;
     }
     mReadCV.notify_one();
     return result;
 }
 
-void AudioFlinger::RecordThread::PassthruPatchRecord::releaseBuffer(Proxy::Buffer* buffer)
+void PassthruPatchRecord::releaseBuffer(Proxy::Buffer* buffer)
 {
     if (buffer->mFrameCount <= mUnconsumedFrames) {
         mUnconsumedFrames -= buffer->mFrameCount;
@@ -3099,12 +3358,12 @@
 // 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);
     {
-        std::unique_lock<std::mutex> lock(mReadLock);
+        audio_utils::unique_lock lock(readMutex());
         mReadCV.wait(lock, [&]{ return mReadError != NO_ERROR || mReadBytes != 0; });
         if (mReadError != NO_ERROR) {
             mLastReadFrames = 0;
@@ -3118,15 +3377,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'.
@@ -3138,7 +3397,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;
@@ -3146,7 +3405,7 @@
     return NO_ERROR;
 }
 
-void AudioFlinger::RecordThread::PassthruPatchRecord::releaseBuffer(
+void PassthruPatchRecord::releaseBuffer(
         AudioBufferProvider::Buffer* buffer)
 {
     buffer->frameCount = 0;
@@ -3157,7 +3416,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,
@@ -3183,27 +3467,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;
@@ -3211,21 +3495,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
@@ -3256,13 +3539,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..e4ad112
--- /dev/null
+++ b/services/audioflinger/afutils/DumpTryLock.h
@@ -0,0 +1,48 @@
+/*
+ *
+ * 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 <audio_utils/mutex.h>
+#include <utils/Mutex.h>
+#include <utils/Timers.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;
+}
+
+// Note: the std::timed_mutex try_lock_for and try_lock_until methods are inefficient.
+// It is better to use std::mutex and call this method.
+//
+inline bool dumpTryLock(audio_utils::mutex& mutex) TRY_ACQUIRE(true, mutex)
+{
+    static constexpr int64_t kDumpLockTimeoutNs = 1'000'000'000;
+
+    const int64_t timeoutNs = kDumpLockTimeoutNs + systemTime(SYSTEM_TIME_REALTIME);
+    const struct timespec ts = {
+        .tv_sec = static_cast<time_t>(timeoutNs / 1000000000),
+        .tv_nsec = static_cast<long>(timeoutNs % 1000000000),
+    };
+    return pthread_mutex_timedlock(mutex.native_handle(), &ts) == 0;
+}
+
+}  // android::afutils
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/audioflinger/timing/SyncEvent.h b/services/audioflinger/timing/SyncEvent.h
index b5a3b40..ededb26 100644
--- a/services/audioflinger/timing/SyncEvent.h
+++ b/services/audioflinger/timing/SyncEvent.h
@@ -16,6 +16,7 @@
 
 #pragma once
 
+#include <any>
 #include <functional>
 #include <mutex>
 
@@ -33,7 +34,7 @@
               audio_session_t triggerSession,
               audio_session_t listenerSession,
               const SyncEventCallback& callBack,
-              const wp<RefBase>& cookie)
+              const std::any& cookie)
     : mType(type), mTriggerSession(triggerSession), mListenerSession(listenerSession),
       mCookie(cookie), mCallback(callBack)
     {}
@@ -56,13 +57,13 @@
     AudioSystem::sync_event_t type() const { return mType; }
     audio_session_t triggerSession() const { return mTriggerSession; }
     audio_session_t listenerSession() const { return mListenerSession; }
-    const wp<RefBase>& cookie() const { return mCookie; }
+    const std::any& cookie() const { return mCookie; }
 
 private:
       const AudioSystem::sync_event_t mType;
       const audio_session_t mTriggerSession;
       const audio_session_t mListenerSession;
-      const wp<RefBase> mCookie;
+      const std::any mCookie;
       mutable std::mutex mLock;
       SyncEventCallback mCallback GUARDED_BY(mLock);
 };
diff --git a/services/audioflinger/timing/tests/mediasyncevent_tests.cpp b/services/audioflinger/timing/tests/mediasyncevent_tests.cpp
index 8a6cf68..ab2d88f 100644
--- a/services/audioflinger/timing/tests/mediasyncevent_tests.cpp
+++ b/services/audioflinger/timing/tests/mediasyncevent_tests.cpp
@@ -56,7 +56,7 @@
     ASSERT_EQ(type, syncEvent->type());
     ASSERT_EQ(triggerSession, syncEvent->triggerSession());
     ASSERT_EQ(listenerSession, syncEvent->listenerSession());
-    ASSERT_EQ(cookie, syncEvent->cookie());
+    ASSERT_EQ(cookie, std::any_cast<decltype(cookie)>(syncEvent->cookie()));
     ASSERT_FALSE(triggered);
 
     syncEvent->trigger();
diff --git a/services/audioflinger/timing/tests/synchronizedrecordstate_tests.cpp b/services/audioflinger/timing/tests/synchronizedrecordstate_tests.cpp
index e9e1edf..82df059 100644
--- a/services/audioflinger/timing/tests/synchronizedrecordstate_tests.cpp
+++ b/services/audioflinger/timing/tests/synchronizedrecordstate_tests.cpp
@@ -59,6 +59,7 @@
     ASSERT_EQ(0, recordState.updateRecordFrames(1'000'000'000));
     ASSERT_FALSE(triggered);
     ASSERT_TRUE(syncEvent->isCancelled());
+    ASSERT_EQ(cookie, std::any_cast<decltype(cookie)>(syncEvent->cookie()));
 
     // Check count down after track is complete.
     syncEvent = sp<SyncEvent>::make(
diff --git a/services/mediaresourcemanager/test/Android.bp b/services/mediaresourcemanager/test/Android.bp
index de24e1e..f903c62 100644
--- a/services/mediaresourcemanager/test/Android.bp
+++ b/services/mediaresourcemanager/test/Android.bp
@@ -20,7 +20,6 @@
         "libmedia",
         "libmediautils",
         "libutils",
-        "libmediautils",
         "libstats_media_metrics",
         "libstatspull",
         "libstatssocket",