diff --git a/services/audioflinger/PatchPanel.cpp b/services/audioflinger/PatchPanel.cpp index d8abb49f00..786c27999c 100644 --- a/services/audioflinger/PatchPanel.cpp +++ b/services/audioflinger/PatchPanel.cpp @@ -496,10 +496,12 @@ status_t AudioFlinger::PatchPanel::Patch::createConnections(PatchPanel *panel) } sp tempRecordTrack; + const bool usePassthruPatchRecord = + (inputFlags & AUDIO_INPUT_FLAG_DIRECT) && (outputFlags & AUDIO_OUTPUT_FLAG_DIRECT); const size_t playbackFrameCount = mPlayback.thread()->frameCount(); const size_t recordFrameCount = mRecord.thread()->frameCount(); size_t frameCount = 0; - if ((inputFlags & AUDIO_INPUT_FLAG_DIRECT) && (outputFlags & AUDIO_OUTPUT_FLAG_DIRECT)) { + if (usePassthruPatchRecord) { // PassthruPatchRecord producesBufferOnDemand, so use // maximum of playback and record thread framecounts frameCount = std::max(playbackFrameCount, recordFrameCount); @@ -556,8 +558,14 @@ status_t AudioFlinger::PatchPanel::Patch::createConnections(PatchPanel *panel) } // tie playback and record tracks together - mRecord.setTrackAndPeer(tempRecordTrack, tempPatchTrack); - mPlayback.setTrackAndPeer(tempPatchTrack, tempRecordTrack); + // In the case of PassthruPatchRecord no I/O activity happens on RecordThread, + // everything is driven from PlaybackThread. Thus AudioBufferProvider methods + // of PassthruPatchRecord can only be called if the corresponding PatchTrack + // is alive. There is no need to hold a reference, and there is no need + // to clear it. In fact, since playback stopping is asynchronous, there is + // no proper time when clearing could be done. + mRecord.setTrackAndPeer(tempRecordTrack, tempPatchTrack, !usePassthruPatchRecord); + mPlayback.setTrackAndPeer(tempPatchTrack, tempRecordTrack, true /*holdReference*/); // start capture and playback mRecord.track()->start(AudioSystem::SYNC_EVENT_NONE, AUDIO_SESSION_NONE); diff --git a/services/audioflinger/PatchPanel.h b/services/audioflinger/PatchPanel.h index 4e0d243f7e..89d4eb19de 100644 --- a/services/audioflinger/PatchPanel.h +++ b/services/audioflinger/PatchPanel.h @@ -128,18 +128,20 @@ public: mCloseThread = closeThread; } template - void setTrackAndPeer(const sp& track, const sp &peer) { + void setTrackAndPeer(const sp& track, const sp &peer, bool holdReference) { mTrack = track; mThread->addPatchTrack(mTrack); - mTrack->setPeerProxy(peer, true /* holdReference */); + mTrack->setPeerProxy(peer, holdReference); + mClearPeerProxy = holdReference; } - void clearTrackPeer() { if (mTrack) mTrack->clearPeerProxy(); } + void clearTrackPeer() { if (mClearPeerProxy && mTrack) mTrack->clearPeerProxy(); } void stopTrack() { if (mTrack) mTrack->stop(); } void swap(Endpoint &other) noexcept { using std::swap; swap(mThread, other.mThread); swap(mCloseThread, other.mCloseThread); + swap(mClearPeerProxy, other.mClearPeerProxy); swap(mHandle, other.mHandle); swap(mTrack, other.mTrack); } @@ -151,6 +153,7 @@ public: private: sp mThread; bool mCloseThread = true; + bool mClearPeerProxy = true; audio_patch_handle_t mHandle = AUDIO_PATCH_HANDLE_NONE; sp mTrack; };