Merge "[BUG] AudioPolicy: fix AudioDeviceCallback" into tm-qpr-dev
diff --git a/services/audiopolicy/common/managerdefinitions/include/ClientDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/ClientDescriptor.h
index 0431619..7119b85 100644
--- a/services/audiopolicy/common/managerdefinitions/include/ClientDescriptor.h
+++ b/services/audiopolicy/common/managerdefinitions/include/ClientDescriptor.h
@@ -239,12 +239,13 @@
}
void setUseSwBridge() { mUseSwBridge = true; }
bool useSwBridge() const { return mUseSwBridge; }
+ bool canCloseOutput() const { return mCloseOutput; }
bool isConnected() const { return mPatchHandle != AUDIO_PATCH_HANDLE_NONE; }
audio_patch_handle_t getPatchHandle() const { return mPatchHandle; }
sp<DeviceDescriptor> srcDevice() const { return mSrcDevice; }
sp<DeviceDescriptor> sinkDevice() const { return mSinkDevice; }
wp<SwAudioOutputDescriptor> swOutput() const { return mSwOutput; }
- void setSwOutput(const sp<SwAudioOutputDescriptor>& swOutput);
+ void setSwOutput(const sp<SwAudioOutputDescriptor>& swOutput, bool closeOutput = false);
wp<HwAudioOutputDescriptor> hwOutput() const { return mHwOutput; }
void setHwOutput(const sp<HwAudioOutputDescriptor>& hwOutput);
@@ -258,6 +259,15 @@
wp<SwAudioOutputDescriptor> mSwOutput;
wp<HwAudioOutputDescriptor> mHwOutput;
bool mUseSwBridge = false;
+ /**
+ * For either HW bridge associated to a SwOutput for activity / volume or SwBridge for also
+ * sample rendering / activity & volume, an existing playback thread may be reused (e.g.
+ * not already opened at APM startup or Direct Output).
+ * If reusing an already opened output, when this output is not used anymore, the AudioFlinger
+ * patch must be updated to refine the output device(s) information and ensure the right
+ * behavior of AudioDeviceCallback.
+ */
+ bool mCloseOutput = false;
};
/**
diff --git a/services/audiopolicy/common/managerdefinitions/src/ClientDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/ClientDescriptor.cpp
index 713b0ac..8b6866e 100644
--- a/services/audiopolicy/common/managerdefinitions/src/ClientDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/ClientDescriptor.cpp
@@ -105,9 +105,11 @@
{
}
-void SourceClientDescriptor::setSwOutput(const sp<SwAudioOutputDescriptor>& swOutput)
+void SourceClientDescriptor::setSwOutput(
+ const sp<SwAudioOutputDescriptor>& swOutput, bool closeOutput)
{
mSwOutput = swOutput;
+ mCloseOutput = closeOutput;
}
void SourceClientDescriptor::setHwOutput(const sp<HwAudioOutputDescriptor>& hwOutput)
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index 49a6159..31dabd9 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -4564,7 +4564,8 @@
ALOGE("%s output is duplicated", __func__);
return INVALID_OPERATION;
}
- sourceDesc->setSwOutput(outputDesc);
+ bool closeOutput = outputDesc->mDirectOpenCount != 0;
+ sourceDesc->setSwOutput(outputDesc, closeOutput);
} else {
// Same for "raw patches" aka created from createAudioPatch API
SortedVector<audio_io_handle_t> outputs =
@@ -4583,7 +4584,7 @@
__func__, sinkDevice->toString().c_str());
return INVALID_OPERATION;
}
- sourceDesc->setSwOutput(outputDesc);
+ sourceDesc->setSwOutput(outputDesc, /* closeOutput= */ false);
}
// create a software bridge in PatchPanel if:
// - source and sink devices are on different HW modules OR
@@ -4713,17 +4714,29 @@
// releaseOutput has already called closeOutput in case of direct output
return NO_ERROR;
}
- if (!outputDesc->isActive() && !sourceDesc->useSwBridge()) {
- resetOutputDevice(outputDesc);
- } else {
- // Reuse patch handle if still valid / do not force rerouting if still routed
- patchHandle = outputDesc->getPatchHandle();
- setOutputDevices(outputDesc,
- getNewOutputDevices(outputDesc, true /*fromCache*/),
- patchHandle == AUDIO_PATCH_HANDLE_NONE, /*force*/
- 0,
- patchHandle == AUDIO_PATCH_HANDLE_NONE ? nullptr : &patchHandle);
- }
+ patchHandle = outputDesc->getPatchHandle();
+ // When a Sw bridge is released, the mixer used by this bridge will release its
+ // patch at AudioFlinger side. Hence, the mixer audio patch must be recreated
+ // Reuse patch handle to force audio flinger removing initial mixer patch removal
+ // updating hal patch handle (prevent leaks).
+ // While using a HwBridge, force reconsidering device only if not reusing an existing
+ // output and no more activity on output (will force to close).
+ bool force = sourceDesc->useSwBridge() ||
+ (sourceDesc->canCloseOutput() && !outputDesc->isActive());
+ // APM pattern is to have always outputs opened / patch realized for reachable devices.
+ // Update device may result to NONE (empty), coupled with force, it releases the patch.
+ // Reconsider device only for cases:
+ // 1 / Active Output
+ // 2 / Inactive Output previously hosting HwBridge
+ // 3 / Inactive Output previously hosting SwBridge that can be closed.
+ bool updateDevice = outputDesc->isActive() || !sourceDesc->useSwBridge() ||
+ sourceDesc->canCloseOutput();
+ setOutputDevices(outputDesc,
+ updateDevice ? getNewOutputDevices(outputDesc, true /*fromCache*/) :
+ outputDesc->devices(),
+ force,
+ 0,
+ patchHandle == AUDIO_PATCH_HANDLE_NONE ? nullptr : &patchHandle);
} else {
return BAD_VALUE;
}