AudioFlinger: Create PatchPanel callback

Test: atest AudioTrackTest AudioRecordTest
Test: Camera YouTube
Bug: 291319167
Merged-In: I3b851a1b1b50edd76305957c8b91521e0cb1d23d
Change-Id: I3b851a1b1b50edd76305957c8b91521e0cb1d23d
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index f16a02a..6763519 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -412,6 +412,7 @@
         mAAudioHwBurstMinMicros = getAAudioHardwareBurstMinUsecFromSystemProperty();
     }
 
+    mPatchPanel = IAfPatchPanel::create(sp<IAfPatchPanelCallback>::fromExisting(this));
     mMelReporter = sp<MelReporter>::make(sp<IAfMelReporterCallback>::fromExisting(this));
 }
 
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index 9d96035..9e34410 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -167,10 +167,10 @@
     , public IAfClientCallback
     , public IAfDeviceEffectManagerCallback
     , public IAfMelReporterCallback
+    , public IAfPatchPanelCallback
 {
     friend class sp<AudioFlinger>;
     // TODO(b/291319167) Create interface and remove friends.
-    friend class PatchPanel;
     // TODO(b/291012167) replace the Thread friends with an interface.
     friend class DirectOutputThread;
     friend class MixerThread;
@@ -375,7 +375,7 @@
     // ---- begin IAfDeviceEffectManagerCallback interface
 
     bool isAudioPolicyReady() const final { return mAudioPolicyReady.load(); }
-    // below also used by IAfMelReporterCallback
+    // 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;
@@ -391,6 +391,41 @@
 
     // ---- end of IAfMelReporterCallback interface
 
+    // ---- begin IAfPatchPanelCallback interface
+
+    void closeThreadInternal_l(const sp<IAfPlaybackThread>& thread) final;
+    void closeThreadInternal_l(const sp<IAfRecordThread>& thread) final;
+    // return thread associated with primary hardware device, or NULL
+    IAfPlaybackThread* primaryPlaybackThread_l() const final;
+    IAfPlaybackThread* checkPlaybackThread_l(audio_io_handle_t output) const final;
+    IAfRecordThread* checkRecordThread_l(audio_io_handle_t input) const final;
+    IAfMmapThread* checkMmapThread_l(audio_io_handle_t io) const final;
+    void lock() const final ACQUIRE(mLock) { mLock.lock(); }
+    void unlock() const final RELEASE(mLock) { mLock.unlock(); }
+    sp<IAfThreadBase> openInput_l(audio_module_handle_t module,
+            audio_io_handle_t* input,
+            audio_config_t* config,
+            audio_devices_t device,
+            const char* address,
+            audio_source_t source,
+            audio_input_flags_t flags,
+            audio_devices_t outputDevice,
+            const String8& outputDeviceAddress) final;
+    sp<IAfThreadBase> openOutput_l(audio_module_handle_t module,
+            audio_io_handle_t* output,
+            audio_config_t* halConfig,
+            audio_config_base_t* mixerConfig,
+            audio_devices_t deviceType,
+            const String8& address,
+            audio_output_flags_t flags) final;
+    const DefaultKeyedVector<audio_module_handle_t, AudioHwDevice*>&
+            getAudioHwDevs_l() const final { return mAudioHwDevs; }
+    void updateDownStreamPatches_l(const struct audio_patch* patch,
+            const std::set<audio_io_handle_t>& streams) final;
+    void updateOutDevicesForRecordThreads_l(const DeviceDescriptorBaseVector& devices) final;
+
+    // ---- end of IAfPatchPanelCallback interface
+
     /* List available audio ports and their attributes */
     status_t listAudioPorts(unsigned int* num_ports, struct audio_port* ports) const;
 
@@ -412,9 +447,6 @@
         const sp<os::ExternalVibration>& externalVibration);
     static void onExternalVibrationStop(const sp<os::ExternalVibration>& externalVibration);
 
-    void updateDownStreamPatches_l(const struct audio_patch *patch,
-                                   const std::set<audio_io_handle_t>& streams);
-
     std::optional<media::AudioVibratorInfo> getDefaultVibratorInfo_l();
 
 private:
@@ -454,9 +486,6 @@
 
     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; }
@@ -628,29 +657,11 @@
     }
 
     IAfThreadBase* checkThread_l(audio_io_handle_t ioHandle) const;
-    IAfPlaybackThread* checkPlaybackThread_l(audio_io_handle_t output) const;
     IAfPlaybackThread* checkMixerThread_l(audio_io_handle_t output) const;
-    IAfRecordThread* checkRecordThread_l(audio_io_handle_t input) const;
-    IAfMmapThread* checkMmapThread_l(audio_io_handle_t io) const;
+
               sp<VolumeInterface> getVolumeInterface_l(audio_io_handle_t output) const;
               std::vector<sp<VolumeInterface>> getAllVolumeInterfaces_l() const;
 
-    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);
-    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);
 
     void closeOutputFinish(const sp<IAfPlaybackThread>& thread);
     void closeInputFinish(const sp<IAfRecordThread>& thread);
@@ -675,14 +686,13 @@
               //       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().
-    // used by IAfDeviceEffectManagerCallback
+    // used by IAfDeviceEffectManagerCallback, IAfPatchPanelCallback
     audio_unique_id_t nextUniqueId(audio_unique_id_use_t use) final;
 
               status_t moveEffectChain_l(audio_session_t sessionId,
             IAfPlaybackThread* srcThread, IAfPlaybackThread* dstThread);
 
               // return thread associated with primary hardware device, or NULL
-              IAfPlaybackThread* primaryPlaybackThread_l() const;
               DeviceTypeSet primaryOutputDevice_l() const;
 
               // return the playback thread with smallest HAL buffer size, and prefer fast
@@ -726,7 +736,6 @@
                 std::vector< sp<IAfEffectModule> > purgeStaleEffects_l();
 
                 void broadcastParametersToRecordThreads_l(const String8& keyValuePairs);
-                void updateOutDevicesForRecordThreads_l(const DeviceDescriptorBaseVector& devices);
                 void forwardParametersToDownstreamPatches_l(
                         audio_io_handle_t upStream, const String8& keyValuePairs,
             const std::function<bool(const sp<IAfPlaybackThread>&)>& useThread = nullptr);
@@ -844,9 +853,7 @@
 
     // for use from destructor
     status_t    closeOutput_nonvirtual(audio_io_handle_t output);
-    void closeThreadInternal_l(const sp<IAfPlaybackThread>& thread);
     status_t    closeInput_nonvirtual(audio_io_handle_t input);
-    void closeThreadInternal_l(const sp<IAfRecordThread>& thread);
     void setAudioHwSyncForSession_l(IAfPlaybackThread* thread, audio_session_t sessionId);
 
     status_t    checkStreamType(audio_stream_type_t stream) const;
@@ -873,8 +880,7 @@
 
     nsecs_t mGlobalEffectEnableTime;  // when a global effect was last enabled
 
-    // protected by mLock
-    const sp<IAfPatchPanel> mPatchPanel = IAfPatchPanel::create(this);
+    /* const */ sp<IAfPatchPanel> mPatchPanel;
 
 public:
     // TODO(b/291319167) access by getter.
diff --git a/services/audioflinger/IAfPatchPanel.h b/services/audioflinger/IAfPatchPanel.h
index 29bd4ab..bc116a9 100644
--- a/services/audioflinger/IAfPatchPanel.h
+++ b/services/audioflinger/IAfPatchPanel.h
@@ -18,12 +18,14 @@
 
 namespace android {
 
+class IAfMmapThread;
 class IAfPatchPanel;
 class IAfPatchRecord;
 class IAfPatchTrack;
 class IAfPlaybackThread;
 class IAfRecordThread;
 class IAfThreadBase;
+class PatchCommandThread;
 
 class SoftwarePatch {
 public:
@@ -51,9 +53,44 @@
     const audio_io_handle_t mRecordThreadHandle;
 };
 
+class IAfPatchPanelCallback : public virtual RefBase {
+public:
+    virtual void closeThreadInternal_l(const sp<IAfPlaybackThread>& thread) = 0;
+    virtual void closeThreadInternal_l(const sp<IAfRecordThread>& thread) = 0;
+    virtual IAfPlaybackThread* primaryPlaybackThread_l() const = 0;
+    virtual IAfPlaybackThread* checkPlaybackThread_l(audio_io_handle_t output) const = 0;
+    virtual IAfRecordThread* checkRecordThread_l(audio_io_handle_t input) const = 0;
+    virtual IAfMmapThread* checkMmapThread_l(audio_io_handle_t io) const = 0;
+    virtual sp<IAfThreadBase> openInput_l(audio_module_handle_t module,
+            audio_io_handle_t* input,
+            audio_config_t* config,
+            audio_devices_t device,
+            const char* address,
+            audio_source_t source,
+            audio_input_flags_t flags,
+            audio_devices_t outputDevice,
+            const String8& outputDeviceAddress) = 0;
+    virtual sp<IAfThreadBase> openOutput_l(audio_module_handle_t module,
+            audio_io_handle_t* output,
+            audio_config_t* halConfig,
+            audio_config_base_t* mixerConfig,
+            audio_devices_t deviceType,
+            const String8& address,
+            audio_output_flags_t flags) = 0;
+    virtual void lock() const = 0;
+    virtual void unlock() const = 0;
+    virtual const DefaultKeyedVector<audio_module_handle_t, AudioHwDevice*>&
+            getAudioHwDevs_l() const = 0;
+    virtual audio_unique_id_t nextUniqueId(audio_unique_id_use_t use) = 0;
+    virtual const sp<PatchCommandThread>& getPatchCommandThread() = 0;
+    virtual void updateDownStreamPatches_l(
+            const struct audio_patch* patch, const std::set<audio_io_handle_t>& streams) = 0;
+    virtual void updateOutDevicesForRecordThreads_l(const DeviceDescriptorBaseVector& devices) = 0;
+};
+
 class IAfPatchPanel : public virtual RefBase {
 public:
-    static sp<IAfPatchPanel> create(AudioFlinger* audioFlinger);
+    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
diff --git a/services/audioflinger/PatchPanel.cpp b/services/audioflinger/PatchPanel.cpp
index 1bd2a15..7d9049a 100644
--- a/services/audioflinger/PatchPanel.cpp
+++ b/services/audioflinger/PatchPanel.cpp
@@ -96,8 +96,8 @@
 }
 
 /* static */
-sp<IAfPatchPanel> IAfPatchPanel::create(AudioFlinger* audioFlinger) {
-    return sp<PatchPanel>::make(audioFlinger);
+sp<IAfPatchPanel> IAfPatchPanel::create(const sp<IAfPatchPanelCallback>& afPatchPanelCallback) {
+    return sp<PatchPanel>::make(afPatchPanelCallback);
 }
 
 status_t SoftwarePatch::getLatencyMs_l(double* latencyMs) const {
@@ -119,10 +119,10 @@
 {
     if (const auto recordThread = thread->asIAfRecordThread();
             recordThread) {
-        mAudioFlinger.closeThreadInternal_l(recordThread);
+        mAfPatchPanelCallback->closeThreadInternal_l(recordThread);
     } else if (const auto playbackThread = thread->asIAfPlaybackThread();
             playbackThread) {
-        mAudioFlinger.closeThreadInternal_l(playbackThread);
+        mAfPatchPanelCallback->closeThreadInternal_l(playbackThread);
     } else {
         LOG_ALWAYS_FATAL("%s: Endpoints only accept IAfPlayback and IAfRecord threads, "
                 "invalid thread, id: %d  type: %d",
@@ -275,8 +275,8 @@
                         status = INVALID_OPERATION;
                         goto exit;
                     }
-                    const sp<IAfThreadBase> 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;
@@ -302,7 +302,7 @@
                     if (patch->sinks[0].config_mask & AUDIO_PORT_CONFIG_FLAGS) {
                         flags = patch->sinks[0].flags.output;
                     }
-                    const sp<IAfThreadBase> thread = mAudioFlinger.openOutput_l(
+                    const sp<IAfThreadBase> thread = mAfPatchPanelCallback->openOutput_l(
                                                             patch->sinks[0].ext.device.hw_module,
                                                             &output,
                                                             &config,
@@ -310,7 +310,7 @@
                                                             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;
@@ -349,7 +349,7 @@
                                 == AUDIO_STREAM_VOICE_CALL) {
                     source = AUDIO_SOURCE_VOICE_COMMUNICATION;
                 }
-                const sp<IAfThreadBase> thread = mAudioFlinger.openInput_l(srcModule,
+                const sp<IAfThreadBase> thread = mAfPatchPanelCallback->openInput_l(srcModule,
                                                                     &input,
                                                                     &config,
                                                                     device,
@@ -358,7 +358,7 @@
                                                                     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;
@@ -374,10 +374,11 @@
                 }
             } else {
                 if (patch->sinks[0].type == AUDIO_PORT_TYPE_MIX) {
-                    sp<IAfThreadBase> 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);
@@ -385,9 +386,9 @@
                             goto exit;
                         }
                     }
-                    mAudioFlinger.unlock();
+                    mAfPatchPanelCallback->unlock();
                     status = thread->sendCreateAudioPatchConfigEvent(patch, &halHandle);
-                    mAudioFlinger.lock();
+                    mAfPatchPanelCallback->lock();
                     if (status == NO_ERROR) {
                         newPatch.setThread(thread);
                     }
@@ -411,7 +412,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;
@@ -437,10 +438,11 @@
                 device->applyAudioPortConfig(&patch->sinks[i]);
                 devices.push_back(device);
             }
-            sp<IAfThreadBase> 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);
@@ -448,13 +450,13 @@
                     goto exit;
                 }
             }
-            if (thread == mAudioFlinger.primaryPlaybackThread_l()) {
-                mAudioFlinger.updateOutDevicesForRecordThreads_l(devices);
+            if (thread == mAfPatchPanelCallback->primaryPlaybackThread_l()) {
+                mAfPatchPanelCallback->updateOutDevicesForRecordThreads_l(devices);
             }
 
-            mAudioFlinger.unlock();
+            mAfPatchPanelCallback->unlock();
             status = thread->sendCreateAudioPatchConfigEvent(patch, &halHandle);
-            mAudioFlinger.lock();
+            mAfPatchPanelCallback->lock();
             if (status == NO_ERROR) {
                 newPatch.setThread(thread);
             }
@@ -479,9 +481,10 @@
 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);
         }
@@ -793,18 +796,18 @@
 
             if (patch.sinks[0].type == AUDIO_PORT_TYPE_MIX) {
                 audio_io_handle_t ioHandle = patch.sinks[0].ext.mix.handle;
-                sp<IAfThreadBase> thread = mAudioFlinger.checkRecordThread_l(ioHandle);
+                sp<IAfThreadBase> thread = mAfPatchPanelCallback->checkRecordThread_l(ioHandle);
                 if (thread == 0) {
-                    thread = mAudioFlinger.checkMmapThread_l(ioHandle);
+                    thread = mAfPatchPanelCallback->checkMmapThread_l(ioHandle);
                     if (thread == 0) {
                         ALOGW("%s() bad capture I/O handle %d", __func__, ioHandle);
                         status = BAD_VALUE;
                         break;
                     }
                 }
-                mAudioFlinger.unlock();
+                mAfPatchPanelCallback->unlock();
                 status = thread->sendReleaseAudioPatchConfigEvent(removedPatch.mHalHandle);
-                mAudioFlinger.lock();
+                mAfPatchPanelCallback->lock();
             } else {
                 status = hwDevice->releaseAudioPatch(removedPatch.mHalHandle);
             }
@@ -816,18 +819,18 @@
                 break;
             }
             audio_io_handle_t ioHandle = src.ext.mix.handle;
-            sp<IAfThreadBase> thread = mAudioFlinger.checkPlaybackThread_l(ioHandle);
+            sp<IAfThreadBase> thread = mAfPatchPanelCallback->checkPlaybackThread_l(ioHandle);
             if (thread == 0) {
-                thread = mAudioFlinger.checkMmapThread_l(ioHandle);
+                thread = mAfPatchPanelCallback->checkMmapThread_l(ioHandle);
                 if (thread == 0) {
                     ALOGW("%s() bad playback I/O handle %d", __func__, ioHandle);
                     status = BAD_VALUE;
                     break;
                 }
             }
-            mAudioFlinger.unlock();
+            mAfPatchPanelCallback->unlock();
             status = thread->sendReleaseAudioPatchConfigEvent(removedPatch.mHalHandle);
-            mAudioFlinger.lock();
+            mAfPatchPanelCallback->lock();
         } break;
         default:
             status = BAD_VALUE;
@@ -840,7 +843,7 @@
 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 */
@@ -904,12 +907,12 @@
 AudioHwDevice* PatchPanel::findAudioHwDeviceByModule(audio_module_handle_t module)
 {
     if (module == AUDIO_MODULE_HANDLE_NONE) return nullptr;
-    ssize_t index = mAudioFlinger.mAudioHwDevs.indexOfKey(module);
+    ssize_t index = mAfPatchPanelCallback->getAudioHwDevs_l().indexOfKey(module);
     if (index < 0) {
         ALOGW("%s() bad hw module %d", __func__, module);
         return nullptr;
     }
-    return mAudioFlinger.mAudioHwDevs.valueAt(index);
+    return mAfPatchPanelCallback->getAudioHwDevs_l().valueAt(index);
 }
 
 sp<DeviceHalInterface> PatchPanel::findHwDeviceByModule(audio_module_handle_t module)
@@ -924,7 +927,7 @@
 {
     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);
     }
 }
 
diff --git a/services/audioflinger/PatchPanel.h b/services/audioflinger/PatchPanel.h
index 14b96c9..890b87d 100644
--- a/services/audioflinger/PatchPanel.h
+++ b/services/audioflinger/PatchPanel.h
@@ -21,7 +21,8 @@
 
 class PatchPanel : public IAfPatchPanel {
 public:
-    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,
@@ -71,7 +72,7 @@
     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