PatchPanel: Cleanup and refactoring

  * Unified software patch endpoints management code.

  * Noticed that Patch::clearConnections is only called before
    getting rid of Patch instance, so there is no need
    to explicitly clear references to endpoints' Track and Thread.

  * Fixed out-of-memory handling when creating tracks for
    a software patch.

  * Factored out finding HAL Device by module handle.

Test: verify transitions to/from BT while playing media and making calls
Change-Id: If6459c477054d6dff60dfa13f2d99ee2d6e887ad
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index f28132d..e3e53b7 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -2293,7 +2293,7 @@
     delete out;
 }
 
-void AudioFlinger::closeOutputInternal_l(const sp<PlaybackThread>& thread)
+void AudioFlinger::closeThreadInternal_l(const sp<PlaybackThread>& thread)
 {
     mPlaybackThreads.removeItem(thread->mId);
     thread->exit();
@@ -2586,7 +2586,7 @@
     delete in;
 }
 
-void AudioFlinger::closeInputInternal_l(const sp<RecordThread>& thread)
+void AudioFlinger::closeThreadInternal_l(const sp<RecordThread>& thread)
 {
     mRecordThreads.removeItem(thread->mId);
     closeInputFinish(thread);
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index 692a904..7cfe542 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -791,9 +791,9 @@
 
     // for use from destructor
     status_t    closeOutput_nonvirtual(audio_io_handle_t output);
-    void        closeOutputInternal_l(const sp<PlaybackThread>& thread);
+    void        closeThreadInternal_l(const sp<PlaybackThread>& thread);
     status_t    closeInput_nonvirtual(audio_io_handle_t input);
-    void        closeInputInternal_l(const sp<RecordThread>& thread);
+    void        closeThreadInternal_l(const sp<RecordThread>& thread);
     void        setAudioHwSyncForSession_l(PlaybackThread *thread, audio_session_t sessionId);
 
     status_t    checkStreamType(audio_stream_type_t stream) const;
diff --git a/services/audioflinger/PatchPanel.cpp b/services/audioflinger/PatchPanel.cpp
index 3ae198b..eaf1120 100644
--- a/services/audioflinger/PatchPanel.cpp
+++ b/services/audioflinger/PatchPanel.cpp
@@ -125,18 +125,16 @@
         if (iter != mPatches.end()) {
             ALOGV("%s() removing patch handle %d", __func__, *handle);
             Patch &removedPatch = iter->second;
-            halHandle = removedPatch.mHalHandle;
             // free resources owned by the removed patch if applicable
             // 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.mRecordPatchHandle != AUDIO_PATCH_HANDLE_NONE) ||
-                    (removedPatch.mPlaybackPatchHandle != AUDIO_PATCH_HANDLE_NONE)) {
+            if (removedPatch.isSoftware()) {
                 removedPatch.clearConnections(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
             // by call to create_audio_patch() below which will happen on a different HW module
-            if (halHandle != AUDIO_PATCH_HANDLE_NONE) {
+            if (removedPatch.mHalHandle != AUDIO_PATCH_HANDLE_NONE) {
                 audio_module_handle_t hwModule = AUDIO_MODULE_HANDLE_NONE;
                 const struct audio_patch &oldPatch = removedPatch.mAudioPatch;
                 if (oldPatch.sources[0].type == AUDIO_PORT_TYPE_DEVICE &&
@@ -153,16 +151,12 @@
                     // these special patches are only created by the policy manager but just
                     // in case, systematically clear the HAL patch.
                     // Note that removedPatch.mAudioPatch.num_sinks cannot be 0 here because
-                    // halHandle would be AUDIO_PATCH_HANDLE_NONE in this case.
+                    // removedPatch.mHalHandle would be AUDIO_PATCH_HANDLE_NONE in this case.
                     hwModule = oldPatch.sinks[0].ext.device.hw_module;
                 }
-                if (hwModule != AUDIO_MODULE_HANDLE_NONE) {
-                    ssize_t index = mAudioFlinger.mAudioHwDevs.indexOfKey(hwModule);
-                    if (index >= 0) {
-                        sp<DeviceHalInterface> hwDevice =
-                                mAudioFlinger.mAudioHwDevs.valueAt(index)->hwDevice();
-                        hwDevice->releaseAudioPatch(halHandle);
-                    }
+                sp<DeviceHalInterface> hwDevice = findHwDeviceByModule(hwModule);
+                if (hwDevice != 0) {
+                    hwDevice->releaseAudioPatch(removedPatch.mHalHandle);
                 }
             }
             mPatches.erase(iter);
@@ -217,12 +211,14 @@
 
                     sp<ThreadBase> thread =
                             mAudioFlinger.checkPlaybackThread_l(patch->sources[1].ext.mix.handle);
-                    newPatch.mPlaybackThread = (MixerThread *)thread.get();
                     if (thread == 0) {
                         ALOGW("%s() cannot get playback thread", __func__);
                         status = INVALID_OPERATION;
                         goto exit;
                     }
+                    // existing playback thread is reused, so it is not closed when patch is cleared
+                    newPatch.mPlayback.setThread(
+                            reinterpret_cast<PlaybackThread*>(thread.get()), false /*closeThread*/);
                 } else {
                     audio_config_t config = AUDIO_CONFIG_INITIALIZER;
                     audio_devices_t device = patch->sinks[0].ext.device.type;
@@ -235,13 +231,12 @@
                                                             device,
                                                             address,
                                                             AUDIO_OUTPUT_FLAG_NONE);
-                    newPatch.mPlaybackThread = (PlaybackThread *)thread.get();
-                    ALOGV("mAudioFlinger.openOutput_l() returned %p",
-                                          newPatch.mPlaybackThread.get());
-                    if (newPatch.mPlaybackThread == 0) {
+                    ALOGV("mAudioFlinger.openOutput_l() returned %p", thread.get());
+                    if (thread == 0) {
                         status = NO_MEMORY;
                         goto exit;
                     }
+                    newPatch.mPlayback.setThread(reinterpret_cast<PlaybackThread*>(thread.get()));
                 }
                 audio_devices_t device = patch->sources[0].ext.device.type;
                 String8 address = String8(patch->sources[0].ext.device.address);
@@ -251,18 +246,18 @@
                 if (patch->sources[0].config_mask & AUDIO_PORT_CONFIG_SAMPLE_RATE) {
                     config.sample_rate = patch->sources[0].sample_rate;
                 } else {
-                    config.sample_rate = newPatch.mPlaybackThread->sampleRate();
+                    config.sample_rate = newPatch.mPlayback.thread()->sampleRate();
                 }
                 if (patch->sources[0].config_mask & AUDIO_PORT_CONFIG_CHANNEL_MASK) {
                     config.channel_mask = patch->sources[0].channel_mask;
                 } else {
-                    config.channel_mask =
-                        audio_channel_in_mask_from_count(newPatch.mPlaybackThread->channelCount());
+                    config.channel_mask = audio_channel_in_mask_from_count(
+                            newPatch.mPlayback.thread()->channelCount());
                 }
                 if (patch->sources[0].config_mask & AUDIO_PORT_CONFIG_FORMAT) {
                     config.format = patch->sources[0].format;
                 } else {
-                    config.format = newPatch.mPlaybackThread->format();
+                    config.format = newPatch.mPlayback.thread()->format();
                 }
                 audio_io_handle_t input = AUDIO_IO_HANDLE_NONE;
                 sp<ThreadBase> thread = mAudioFlinger.openInput_l(srcModule,
@@ -272,13 +267,13 @@
                                                                     address,
                                                                     AUDIO_SOURCE_MIC,
                                                                     AUDIO_INPUT_FLAG_NONE);
-                newPatch.mRecordThread = (RecordThread *)thread.get();
                 ALOGV("mAudioFlinger.openInput_l() returned %p inChannelMask %08x",
-                      newPatch.mRecordThread.get(), config.channel_mask);
-                if (newPatch.mRecordThread == 0) {
+                      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);
                 if (status != NO_ERROR) {
                     goto exit;
@@ -369,6 +364,12 @@
     return status;
 }
 
+AudioFlinger::PatchPanel::Patch::~Patch()
+{
+    ALOGE_IF(isSoftware(), "Software patch connections leaked %d %d",
+            mRecord.handle(), mPlayback.handle());
+}
+
 status_t AudioFlinger::PatchPanel::Patch::createConnections(PatchPanel *panel)
 {
     // create patch from source device to record thread input
@@ -377,32 +378,32 @@
     subPatch.sources[0] = mAudioPatch.sources[0];
     subPatch.num_sinks = 1;
 
-    mRecordThread->getAudioPortConfig(&subPatch.sinks[0]);
+    mRecord.thread()->getAudioPortConfig(&subPatch.sinks[0]);
     subPatch.sinks[0].ext.mix.usecase.source = AUDIO_SOURCE_MIC;
 
-    status_t status = panel->createAudioPatch(&subPatch, &mRecordPatchHandle);
+    status_t status = panel->createAudioPatch(&subPatch, mRecord.handlePtr());
     if (status != NO_ERROR) {
-        mRecordPatchHandle = AUDIO_PATCH_HANDLE_NONE;
+        *mRecord.handlePtr() = AUDIO_PATCH_HANDLE_NONE;
         return status;
     }
 
     // create patch from playback thread output to sink device
     if (mAudioPatch.num_sinks != 0) {
-        mPlaybackThread->getAudioPortConfig(&subPatch.sources[0]);
+        mPlayback.thread()->getAudioPortConfig(&subPatch.sources[0]);
         subPatch.sinks[0] = mAudioPatch.sinks[0];
-        status = panel->createAudioPatch(&subPatch, &mPlaybackPatchHandle);
+        status = panel->createAudioPatch(&subPatch, mPlayback.handlePtr());
         if (status != NO_ERROR) {
-            mPlaybackPatchHandle = AUDIO_PATCH_HANDLE_NONE;
+            *mPlayback.handlePtr() = AUDIO_PATCH_HANDLE_NONE;
             return status;
         }
     } else {
-        mPlaybackPatchHandle = AUDIO_PATCH_HANDLE_NONE;
+        *mPlayback.handlePtr() = AUDIO_PATCH_HANDLE_NONE;
     }
 
     // use a pseudo LCM between input and output framecount
-    size_t playbackFrameCount = mPlaybackThread->frameCount();
+    size_t playbackFrameCount = mPlayback.thread()->frameCount();
     int playbackShift = __builtin_ctz(playbackFrameCount);
-    size_t recordFramecount = mRecordThread->frameCount();
+    size_t recordFramecount = mRecord.thread()->frameCount();
     int shift = __builtin_ctz(recordFramecount);
     if (playbackShift < shift) {
         shift = playbackShift;
@@ -412,14 +413,14 @@
             __func__, playbackFrameCount, recordFramecount, frameCount);
 
     // create a special record track to capture from record thread
-    uint32_t channelCount = mPlaybackThread->channelCount();
+    uint32_t channelCount = mPlayback.thread()->channelCount();
     audio_channel_mask_t inChannelMask = audio_channel_in_mask_from_count(channelCount);
-    audio_channel_mask_t outChannelMask = mPlaybackThread->channelMask();
-    uint32_t sampleRate = mPlaybackThread->sampleRate();
-    audio_format_t format = mPlaybackThread->format();
+    audio_channel_mask_t outChannelMask = mPlayback.thread()->channelMask();
+    uint32_t sampleRate = mPlayback.thread()->sampleRate();
+    audio_format_t format = mPlayback.thread()->format();
 
-    mPatchRecord = new RecordThread::PatchRecord(
-                                             mRecordThread.get(),
+    sp<RecordThread::PatchRecord> tempRecordTrack = new (std::nothrow) RecordThread::PatchRecord(
+                                             mRecord.thread().get(),
                                              sampleRate,
                                              inChannelMask,
                                              format,
@@ -427,91 +428,47 @@
                                              NULL,
                                              (size_t)0 /* bufferSize */,
                                              AUDIO_INPUT_FLAG_NONE);
-    if (mPatchRecord == 0) {
-        return NO_MEMORY;
-    }
-    status = mPatchRecord->initCheck();
+    status = mRecord.checkTrack(tempRecordTrack.get());
     if (status != NO_ERROR) {
         return status;
     }
-    mRecordThread->addPatchRecord(mPatchRecord);
 
     // create a special playback track to render to playback thread.
     // this track is given the same buffer as the PatchRecord buffer
-    mPatchTrack = new PlaybackThread::PatchTrack(
-                                           mPlaybackThread.get(),
+    sp<PlaybackThread::PatchTrack> tempPatchTrack = new (std::nothrow) PlaybackThread::PatchTrack(
+                                           mPlayback.thread().get(),
                                            mAudioPatch.sources[1].ext.mix.usecase.stream,
                                            sampleRate,
                                            outChannelMask,
                                            format,
                                            frameCount,
-                                           mPatchRecord->buffer(),
-                                           mPatchRecord->bufferSize(),
+                                           tempRecordTrack->buffer(),
+                                           tempRecordTrack->bufferSize(),
                                            AUDIO_OUTPUT_FLAG_NONE);
-    status = mPatchTrack->initCheck();
+    status = mPlayback.checkTrack(tempPatchTrack.get());
     if (status != NO_ERROR) {
         return status;
     }
-    mPlaybackThread->addPatchTrack(mPatchTrack);
 
     // tie playback and record tracks together
-    mPatchRecord->setPeerProxy(mPatchTrack.get());
-    mPatchTrack->setPeerProxy(mPatchRecord.get());
+    mRecord.setTrackAndPeer(tempRecordTrack, tempPatchTrack.get());
+    mPlayback.setTrackAndPeer(tempPatchTrack, tempRecordTrack.get());
 
     // start capture and playback
-    mPatchRecord->start(AudioSystem::SYNC_EVENT_NONE, AUDIO_SESSION_NONE);
-    mPatchTrack->start();
+    mRecord.track()->start(AudioSystem::SYNC_EVENT_NONE, AUDIO_SESSION_NONE);
+    mPlayback.track()->start();
 
     return status;
 }
 
 void AudioFlinger::PatchPanel::Patch::clearConnections(PatchPanel *panel)
 {
-    ALOGV("%s() mRecordPatchHandle %d mPlaybackPatchHandle %d",
-            __func__, mRecordPatchHandle, mPlaybackPatchHandle);
-
-    if (mPatchRecord != 0) {
-        mPatchRecord->stop();
-    }
-    if (mPatchTrack != 0) {
-        mPatchTrack->stop();
-    }
-    if (mRecordPatchHandle != AUDIO_PATCH_HANDLE_NONE) {
-        panel->releaseAudioPatch(mRecordPatchHandle);
-        mRecordPatchHandle = AUDIO_PATCH_HANDLE_NONE;
-    }
-    if (mPlaybackPatchHandle != AUDIO_PATCH_HANDLE_NONE) {
-        panel->releaseAudioPatch(mPlaybackPatchHandle);
-        mPlaybackPatchHandle = AUDIO_PATCH_HANDLE_NONE;
-    }
-    if (mRecordThread != 0) {
-        if (mPatchRecord != 0) {
-            mRecordThread->deletePatchRecord(mPatchRecord);
-        }
-        panel->mAudioFlinger.closeInputInternal_l(mRecordThread);
-    }
-    if (mPlaybackThread != 0) {
-        if (mPatchTrack != 0) {
-            mPlaybackThread->deletePatchTrack(mPatchTrack);
-        }
-        // if num sources == 2 we are reusing an existing playback thread so we do not close it
-        if (mAudioPatch.num_sources != 2) {
-            panel->mAudioFlinger.closeOutputInternal_l(mPlaybackThread);
-        }
-    }
-    if (mRecordThread != 0) {
-        if (mPatchRecord != 0) {
-            mPatchRecord.clear();
-        }
-        mRecordThread.clear();
-    }
-    if (mPlaybackThread != 0) {
-        if (mPatchTrack != 0) {
-            mPatchTrack.clear();
-        }
-        mPlaybackThread.clear();
-    }
-
+    ALOGV("%s() mRecord.handle %d mPlayback.handle %d",
+            __func__, mRecord.handle(), mPlayback.handle());
+    mRecord.stopTrack();
+    mPlayback.stopTrack();
+    mRecord.closeConnections(panel);
+    mPlayback.closeConnections(panel);
 }
 
 /* Disconnect a patch */
@@ -527,18 +484,17 @@
     Patch &removedPatch = iter->second;
     const struct audio_patch &patch = removedPatch.mAudioPatch;
 
-    switch (patch.sources[0].type) {
+    const struct audio_port_config &src = patch.sources[0];
+    switch (src.type) {
         case AUDIO_PORT_TYPE_DEVICE: {
-            audio_module_handle_t srcModule = patch.sources[0].ext.device.hw_module;
-            ssize_t index = mAudioFlinger.mAudioHwDevs.indexOfKey(srcModule);
-            if (index < 0) {
-                ALOGW("%s() bad src hw module %d", __func__, srcModule);
+            sp<DeviceHalInterface> hwDevice = findHwDeviceByModule(src.ext.device.hw_module);
+            if (hwDevice == 0) {
+                ALOGW("%s() bad src hw module %d", __func__, src.ext.device.hw_module);
                 status = BAD_VALUE;
                 break;
             }
 
-            if (removedPatch.mRecordPatchHandle != AUDIO_PATCH_HANDLE_NONE ||
-                    removedPatch.mPlaybackPatchHandle != AUDIO_PATCH_HANDLE_NONE) {
+            if (removedPatch.isSoftware()) {
                 removedPatch.clearConnections(this);
                 break;
             }
@@ -556,20 +512,16 @@
                 }
                 status = thread->sendReleaseAudioPatchConfigEvent(removedPatch.mHalHandle);
             } else {
-                AudioHwDevice *audioHwDevice = mAudioFlinger.mAudioHwDevs.valueAt(index);
-                sp<DeviceHalInterface> hwDevice = audioHwDevice->hwDevice();
                 status = hwDevice->releaseAudioPatch(removedPatch.mHalHandle);
             }
         } 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);
-            if (index < 0) {
-                ALOGW("%s() bad src hw module %d", __func__, srcModule);
+            if (findHwDeviceByModule(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 = patch.sources[0].ext.mix.handle;
+            audio_io_handle_t ioHandle = src.ext.mix.handle;
             sp<ThreadBase> thread = mAudioFlinger.checkPlaybackThread_l(ioHandle);
             if (thread == 0) {
                 thread = mAudioFlinger.checkMmapThread_l(ioHandle);
@@ -597,4 +549,14 @@
     return NO_ERROR;
 }
 
+sp<DeviceHalInterface> AudioFlinger::PatchPanel::findHwDeviceByModule(audio_module_handle_t module)
+{
+    if (module == AUDIO_MODULE_HANDLE_NONE) return nullptr;
+    ssize_t index = mAudioFlinger.mAudioHwDevs.indexOfKey(module);
+    if (index < 0) {
+        return nullptr;
+    }
+    return mAudioFlinger.mAudioHwDevs.valueAt(index)->hwDevice();
+}
+
 } // namespace android
diff --git a/services/audioflinger/PatchPanel.h b/services/audioflinger/PatchPanel.h
index c2cb7ac..5a68960 100644
--- a/services/audioflinger/PatchPanel.h
+++ b/services/audioflinger/PatchPanel.h
@@ -43,12 +43,61 @@
                                       struct audio_patch *patches);
 
 private:
+    template<typename ThreadType, typename TrackType>
+    class Endpoint {
+    public:
+        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() { return mThread; }
+        sp<TrackType> track() { return mTrack; }
+
+        void closeConnections(PatchPanel *panel) {
+            if (mHandle != AUDIO_PATCH_HANDLE_NONE) {
+                panel->releaseAudioPatch(mHandle);
+                mHandle = AUDIO_PATCH_HANDLE_NONE;
+            }
+            if (mThread != 0) {
+                if (mTrack != 0) {
+                    mThread->deletePatchTrack(mTrack);
+                }
+                if (mCloseThread) {
+                    panel->mAudioFlinger.closeThreadInternal_l(mThread);
+                }
+            }
+        }
+        audio_patch_handle_t* handlePtr() { return &mHandle; }
+        void setThread(const sp<ThreadType>& thread, bool closeThread = true) {
+            mThread = thread;
+            mCloseThread = closeThread;
+        }
+        void setTrackAndPeer(const sp<TrackType>& track,
+                             ThreadBase::PatchProxyBufferProvider *peer) {
+            mTrack = track;
+            mThread->addPatchTrack(mTrack);
+            mTrack->setPeerProxy(peer);
+        }
+        void stopTrack() { if (mTrack) mTrack->stop(); }
+
+    private:
+        sp<ThreadType> mThread;
+        bool mCloseThread = true;
+        audio_patch_handle_t mHandle = AUDIO_PATCH_HANDLE_NONE;
+        sp<TrackType> mTrack;
+    };
+
     class Patch {
     public:
         explicit Patch(const struct audio_patch &patch) : mAudioPatch(patch) {}
+        ~Patch();
 
         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; }
 
         // Note that audio_patch::id is only unique within a HAL module
         struct audio_patch              mAudioPatch;
@@ -58,17 +107,14 @@
         // 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
-        sp<PlaybackThread>              mPlaybackThread;
-        sp<PlaybackThread::PatchTrack>  mPatchTrack;
-        sp<RecordThread>                mRecordThread;
-        sp<RecordThread::PatchRecord>   mPatchRecord;
-        // handle for audio patch connecting source device to record thread input.
-        audio_patch_handle_t            mRecordPatchHandle = AUDIO_PATCH_HANDLE_NONE;
-        // handle for audio patch connecting playback thread output to sink device
-        audio_patch_handle_t            mPlaybackPatchHandle = AUDIO_PATCH_HANDLE_NONE;
-
+        // connects playback thread output to sink device
+        Endpoint<PlaybackThread, PlaybackThread::PatchTrack> mPlayback;
+        // connects source device to record thread input
+        Endpoint<RecordThread, RecordThread::PatchRecord> mRecord;
     };
 
+    sp<DeviceHalInterface> findHwDeviceByModule(audio_module_handle_t module);
+
     AudioFlinger &mAudioFlinger;
     std::map<audio_patch_handle_t, Patch> mPatches;
 };
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index c47aa01..998cf4e 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -7835,13 +7835,13 @@
     return status;
 }
 
-void AudioFlinger::RecordThread::addPatchRecord(const sp<PatchRecord>& record)
+void AudioFlinger::RecordThread::addPatchTrack(const sp<PatchRecord>& record)
 {
     Mutex::Autolock _l(mLock);
     mTracks.add(record);
 }
 
-void AudioFlinger::RecordThread::deletePatchRecord(const sp<PatchRecord>& record)
+void AudioFlinger::RecordThread::deletePatchTrack(const sp<PatchRecord>& record)
 {
     Mutex::Autolock _l(mLock);
     destroyTrack_l(record);
diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h
index 28d4482..c490fb5 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -1437,8 +1437,8 @@
                                            audio_patch_handle_t *handle);
     virtual status_t    releaseAudioPatch_l(const audio_patch_handle_t handle);
 
-            void        addPatchRecord(const sp<PatchRecord>& record);
-            void        deletePatchRecord(const sp<PatchRecord>& record);
+            void        addPatchTrack(const sp<PatchRecord>& record);
+            void        deletePatchTrack(const sp<PatchRecord>& record);
 
             void        readInputParameters_l();
     virtual uint32_t    getInputFramesLost();