AudioPolicyManager: voice call routing fail safe
Bug: 298609303
Test: make
When devices involved in a call are disconnected, since APM
does not expect such cases, assertion happens.
This CL allows to fail safe on voice call routing.
Change-Id: I14b1ec245e640eeae14390ea62d93a4bdfe5bade
Signed-off-by: François Gaffie <francois.gaffie@renault.com>
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index a72598e..795406a 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -658,7 +658,7 @@
status_t AudioPolicyManager::updateCallRouting(bool fromCache, uint32_t delayMs, uint32_t *waitMs)
{
- if (mEngine->getPhoneState() == AUDIO_MODE_IN_CALL && hasPrimaryOutput()) {
+ if (mEngine->getPhoneState() == AUDIO_MODE_IN_CALL) {
DeviceVector rxDevices = selectBestRxSinkDevicesForCall(fromCache);
return updateCallRoutingInternal(rxDevices, delayMs, waitMs);
}
@@ -671,14 +671,21 @@
bool createTxPatch = false;
bool createRxPatch = false;
uint32_t muteWaitMs = 0;
- if(!hasPrimaryOutput() ||
+ if (hasPrimaryOutput() &&
mPrimaryOutput->devices().onlyContainsDevicesWithType(AUDIO_DEVICE_OUT_STUB)) {
return INVALID_OPERATION;
}
- ALOG_ASSERT(!rxDevices.isEmpty(), "%s() no selected output device", __func__);
audio_attributes_t attr = { .source = AUDIO_SOURCE_VOICE_COMMUNICATION };
auto txSourceDevice = mEngine->getInputDeviceForAttributes(attr);
+
+ disconnectTelephonyAudioSource(mCallRxSourceClient);
+ disconnectTelephonyAudioSource(mCallTxSourceClient);
+
+ if (rxDevices.isEmpty()) {
+ ALOGW("%s() no selected output device", __func__);
+ return INVALID_OPERATION;
+ }
if (txSourceDevice == nullptr) {
ALOGE("%s() selected input device not available", __func__);
return INVALID_OPERATION;
@@ -687,9 +694,6 @@
ALOGV("%s device rxDevice %s txDevice %s", __func__,
rxDevices.itemAt(0)->toString().c_str(), txSourceDevice->toString().c_str());
- disconnectTelephonyAudioSource(mCallRxSourceClient);
- disconnectTelephonyAudioSource(mCallTxSourceClient);
-
auto telephonyRxModule =
mHwModules.getModuleForDeviceType(AUDIO_DEVICE_IN_TELEPHONY_RX, AUDIO_FORMAT_DEFAULT);
auto telephonyTxModule =
@@ -729,6 +733,10 @@
// 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 (!hasPrimaryOutput()) {
+ ALOGW("%s() no primary output available", __func__);
+ return INVALID_OPERATION;
+ }
muteWaitMs = setOutputDevices(__func__, mPrimaryOutput, rxDevices, true, delayMs);
} else { // create RX path audio patch
connectTelephonyRxAudioSource();
@@ -875,20 +883,20 @@
}
}
- if (hasPrimaryOutput()) {
- if (state == AUDIO_MODE_IN_CALL) {
- (void)updateCallRouting(false /*fromCache*/, delayMs);
- } else {
+ if (state == AUDIO_MODE_IN_CALL) {
+ (void)updateCallRouting(false /*fromCache*/, delayMs);
+ } else {
+ if (oldState == AUDIO_MODE_IN_CALL) {
+ disconnectTelephonyAudioSource(mCallRxSourceClient);
+ disconnectTelephonyAudioSource(mCallTxSourceClient);
+ }
+ if (hasPrimaryOutput()) {
DeviceVector rxDevices = getNewOutputDevices(mPrimaryOutput, false /*fromCache*/);
// force routing command to audio hardware when ending call
// even if no device change is needed
if (isStateInCall(oldState) && rxDevices.isEmpty()) {
rxDevices = mPrimaryOutput->devices();
}
- if (oldState == AUDIO_MODE_IN_CALL) {
- disconnectTelephonyAudioSource(mCallRxSourceClient);
- disconnectTelephonyAudioSource(mCallTxSourceClient);
- }
setOutputDevices(__func__, mPrimaryOutput, rxDevices, force, 0);
}
}
@@ -6280,6 +6288,7 @@
if (mPrimaryOutput == nullptr &&
outProfile->getFlags() & AUDIO_OUTPUT_FLAG_PRIMARY) {
mPrimaryOutput = outputDesc;
+ mPrimaryModuleHandle = mPrimaryOutput->getModuleHandle();
}
if ((outProfile->getFlags() & AUDIO_OUTPUT_FLAG_DIRECT) != 0) {
outputDesc->close();
@@ -7114,7 +7123,9 @@
DeviceVector AudioPolicyManager::getNewOutputDevices(const sp<SwAudioOutputDescriptor>& outputDesc,
bool fromCache)
{
- DeviceVector devices;
+ if (outputDesc == nullptr) {
+ return DeviceVector{};
+ }
ssize_t index = mAudioPatches.indexOfKey(outputDesc->getPatchHandle());
if (index >= 0) {
@@ -7148,6 +7159,7 @@
return DeviceVector(device);
}
+ DeviceVector devices;
for (const auto &productStrategy : mEngine->getOrderedProductStrategies()) {
StreamTypeVector streams = mEngine->getStreamTypesForProductStrategy(productStrategy);
auto attr = mEngine->getAllAttributesForProductStrategy(productStrategy).front();
@@ -8442,6 +8454,7 @@
if (mPrimaryOutput == nullptr && profile->getFlags() & AUDIO_OUTPUT_FLAG_PRIMARY) {
ALOGV("%s(): re-assigning mPrimaryOutput", __func__);
mPrimaryOutput = desc;
+ mPrimaryModuleHandle = mPrimaryOutput->getModuleHandle();
}
return desc;
}