Merge "[BUG] AudioFlinger: Patch Panel: Fix SwBridge Patch leak" am: 8dd7969b8f
Original change: https://android-review.googlesource.com/c/platform/frameworks/av/+/1650308
Change-Id: I762b7b1d1df06a72e3620e50d6307a134bf1bb3e
diff --git a/services/audioflinger/PatchPanel.cpp b/services/audioflinger/PatchPanel.cpp
index 37aa13e..030c929 100644
--- a/services/audioflinger/PatchPanel.cpp
+++ b/services/audioflinger/PatchPanel.cpp
@@ -111,7 +111,8 @@
/* Connect a patch between several source and sink ports */
status_t AudioFlinger::PatchPanel::createAudioPatch(const struct audio_patch *patch,
- audio_patch_handle_t *handle)
+ audio_patch_handle_t *handle,
+ bool endpointPatch)
{
if (handle == NULL || patch == NULL) {
return BAD_VALUE;
@@ -174,7 +175,7 @@
}
}
- Patch newPatch{*patch};
+ Patch newPatch{*patch, endpointPatch};
audio_module_handle_t insertedModule = AUDIO_MODULE_HANDLE_NONE;
switch (patch->sources[0].type) {
@@ -396,10 +397,15 @@
}
// remove stale audio patch with same output as source if any
- for (auto& iter : mPatches) {
- if (iter.second.mAudioPatch.sources[0].ext.mix.handle == thread->id()) {
- erasePatch(iter.first);
- break;
+ // Prevent to remove endpoint patches (involved in a SwBridge)
+ // Prevent to remove AudioPatch used to route an output involved in an endpoint.
+ if (!endpointPatch) {
+ for (auto& iter : mPatches) {
+ if (iter.second.mAudioPatch.sources[0].ext.mix.handle == thread->id() &&
+ !iter.second.mIsEndpointPatch) {
+ erasePatch(iter.first);
+ break;
+ }
}
}
} break;
@@ -435,7 +441,8 @@
status_t status = panel->createAudioPatch(
PatchBuilder().addSource(mAudioPatch.sources[0]).
addSink(mRecord.thread(), { .source = AUDIO_SOURCE_MIC }).patch(),
- mRecord.handlePtr());
+ mRecord.handlePtr(),
+ true /*endpointPatch*/);
if (status != NO_ERROR) {
*mRecord.handlePtr() = AUDIO_PATCH_HANDLE_NONE;
return status;
@@ -445,7 +452,8 @@
if (mAudioPatch.num_sinks != 0) {
status = panel->createAudioPatch(
PatchBuilder().addSource(mPlayback.thread()).addSink(mAudioPatch.sinks[0]).patch(),
- mPlayback.handlePtr());
+ mPlayback.handlePtr(),
+ true /*endpointPatch*/);
if (status != NO_ERROR) {
*mPlayback.handlePtr() = AUDIO_PATCH_HANDLE_NONE;
return status;
diff --git a/services/audioflinger/PatchPanel.h b/services/audioflinger/PatchPanel.h
index ea38559..38f0615 100644
--- a/services/audioflinger/PatchPanel.h
+++ b/services/audioflinger/PatchPanel.h
@@ -56,7 +56,8 @@
/* Create a patch between several source and sink ports */
status_t createAudioPatch(const struct audio_patch *patch,
- audio_patch_handle_t *handle);
+ audio_patch_handle_t *handle,
+ bool endpointPatch = false);
/* Release a patch */
status_t releaseAudioPatch(audio_patch_handle_t handle);
@@ -161,7 +162,8 @@
class Patch final {
public:
- explicit Patch(const struct audio_patch &patch) : mAudioPatch(patch) {}
+ Patch(const struct audio_patch &patch, bool endpointPatch) :
+ mAudioPatch(patch), mIsEndpointPatch(endpointPatch) {}
Patch() = default;
~Patch();
Patch(const Patch& other) noexcept {
@@ -170,6 +172,7 @@
mPlayback = other.mPlayback;
mRecord = other.mRecord;
mThread = other.mThread;
+ mIsEndpointPatch = other.mIsEndpointPatch;
}
Patch(Patch&& other) noexcept { swap(other); }
Patch& operator=(Patch&& other) noexcept {
@@ -184,6 +187,7 @@
swap(mPlayback, other.mPlayback);
swap(mRecord, other.mRecord);
swap(mThread, other.mThread);
+ swap(mIsEndpointPatch, other.mIsEndpointPatch);
}
friend void swap(Patch &a, Patch &b) noexcept {
@@ -218,6 +222,7 @@
Endpoint<RecordThread, RecordThread::PatchRecord> mRecord;
wp<ThreadBase> mThread;
+ bool mIsEndpointPatch;
};
// Call with AudioFlinger mLock held