audio policy: fix redundant call routing
Do not teardown and re-create the call RX and RX audio sources
if call routing remains unchanged.
Bug: 292492229
Flag: com.android.media.audioserver.fix_call_audio_patch
Test: make
Change-Id: Ia6fca5cb9776dae4e5942e99f1490550aba42dc4
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index 0627d91..e27eba8 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -66,6 +66,7 @@
using android::media::audio::common::AudioDeviceAddress;
using android::media::audio::common::AudioPortDeviceExt;
using android::media::audio::common::AudioPortExt;
+using com::android::media::audioserver::fix_call_audio_patch;
using content::AttributionSourceState;
//FIXME: workaround for truncated touch sounds
@@ -704,8 +705,10 @@
audio_attributes_t attr = { .source = AUDIO_SOURCE_VOICE_COMMUNICATION };
auto txSourceDevice = mEngine->getInputDeviceForAttributes(attr);
- disconnectTelephonyAudioSource(mCallRxSourceClient);
- disconnectTelephonyAudioSource(mCallTxSourceClient);
+ if (!fix_call_audio_patch()) {
+ disconnectTelephonyAudioSource(mCallRxSourceClient);
+ disconnectTelephonyAudioSource(mCallTxSourceClient);
+ }
if (rxDevices.isEmpty()) {
ALOGW("%s() no selected output device", __func__);
@@ -758,6 +761,9 @@
// Use legacy routing method for voice calls via setOutputDevice() on primary output.
// Otherwise, create two audio patches for TX and RX path.
if (!createRxPatch) {
+ if (fix_call_audio_patch()) {
+ disconnectTelephonyAudioSource(mCallRxSourceClient);
+ }
if (!hasPrimaryOutput()) {
ALOGW("%s() no primary output available", __func__);
return INVALID_OPERATION;
@@ -780,6 +786,8 @@
}
}
connectTelephonyTxAudioSource(txSourceDevice, txSinkDevice, delayMs);
+ } else if (fix_call_audio_patch()) {
+ disconnectTelephonyAudioSource(mCallTxSourceClient);
}
if (waitMs != nullptr) {
*waitMs = muteWaitMs;
@@ -801,18 +809,38 @@
void AudioPolicyManager::connectTelephonyRxAudioSource()
{
- disconnectTelephonyAudioSource(mCallRxSourceClient);
+ const auto aa = mEngine->getAttributesForStreamType(AUDIO_STREAM_VOICE_CALL);
+
+ if (fix_call_audio_patch()) {
+ if (mCallRxSourceClient != nullptr) {
+ DeviceVector rxDevices =
+ mEngine->getOutputDevicesForAttributes(aa, nullptr, false /*fromCache*/);
+ ALOG_ASSERT(!rxDevices.isEmpty() || !mCallRxSourceClient->isConnected(),
+ "connectTelephonyRxAudioSource(): no device found for call RX source");
+ sp<DeviceDescriptor> rxDevice = rxDevices.itemAt(0);
+ if (mCallRxSourceClient->isConnected()
+ && mCallRxSourceClient->sinkDevice()->equals(rxDevice)) {
+ return;
+ }
+ disconnectTelephonyAudioSource(mCallRxSourceClient);
+ }
+ } else {
+ disconnectTelephonyAudioSource(mCallRxSourceClient);
+ }
+
const struct audio_port_config source = {
.role = AUDIO_PORT_ROLE_SOURCE, .type = AUDIO_PORT_TYPE_DEVICE,
.ext.device.type = AUDIO_DEVICE_IN_TELEPHONY_RX, .ext.device.address = ""
};
- const auto aa = mEngine->getAttributesForStreamType(AUDIO_STREAM_VOICE_CALL);
-
audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE;
+
status_t status = startAudioSourceInternal(&source, &aa, &portId, 0 /*uid*/,
true /*internal*/, true /*isCallRx*/);
ALOGE_IF(status != OK, "%s: failed to start audio source (%d)", __func__, status);
mCallRxSourceClient = mAudioSources.valueFor(portId);
+ ALOGV("%s portdID %d between source %s and sink %s", __func__, portId,
+ mCallRxSourceClient->srcDevice()->toString().c_str(),
+ mCallRxSourceClient->sinkDevice()->toString().c_str());
ALOGE_IF(mCallRxSourceClient == nullptr,
"%s failed to start Telephony Rx AudioSource", __func__);
}
@@ -831,15 +859,26 @@
const sp<DeviceDescriptor> &srcDevice, const sp<DeviceDescriptor> &sinkDevice,
uint32_t delayMs)
{
- disconnectTelephonyAudioSource(mCallTxSourceClient);
if (srcDevice == nullptr || sinkDevice == nullptr) {
ALOGW("%s could not create patch, invalid sink and/or source device(s)", __func__);
return;
}
+
+ if (fix_call_audio_patch()) {
+ if (mCallTxSourceClient != nullptr) {
+ if (mCallTxSourceClient->isConnected()
+ && mCallTxSourceClient->srcDevice()->equals(srcDevice)) {
+ return;
+ }
+ disconnectTelephonyAudioSource(mCallTxSourceClient);
+ }
+ } else {
+ disconnectTelephonyAudioSource(mCallTxSourceClient);
+ }
+
PatchBuilder patchBuilder;
patchBuilder.addSource(srcDevice).addSink(sinkDevice);
- ALOGV("%s between source %s and sink %s", __func__,
- srcDevice->toString().c_str(), sinkDevice->toString().c_str());
+
auto callTxSourceClientPortId = PolicyAudioPort::getNextUniqueId();
const auto aa = mEngine->getAttributesForStreamType(AUDIO_STREAM_VOICE_CALL);
@@ -856,6 +895,8 @@
mCallTxSourceClient, sinkDevice, patchBuilder.patch(), patchHandle, mUidCached,
delayMs);
ALOGE_IF(status != NO_ERROR, "%s() error %d creating TX audio patch", __func__, status);
+ ALOGV("%s portdID %d between source %s and sink %s", __func__, callTxSourceClientPortId,
+ srcDevice->toString().c_str(), sinkDevice->toString().c_str());
if (status == NO_ERROR) {
mAudioSources.add(callTxSourceClientPortId, mCallTxSourceClient);
}