233 lines
12 KiB
Diff
233 lines
12 KiB
Diff
From f9be27ef60cd4ccca6803458ff29ee7a2236769c Mon Sep 17 00:00:00 2001
|
|
From: Peter Cai <peter@typeblog.net>
|
|
Date: Thu, 18 Aug 2022 15:44:46 -0400
|
|
Subject: [PATCH 1/4] APM: Restore S, R and Q behavior respectively for
|
|
telephony audio
|
|
|
|
This conditionally reverts part of b2e5cb (T), 51c9cc (S) and afd4ce (R)
|
|
when the VNDK version is equal to or before S, R and Q respectively.
|
|
|
|
On R, commit afd4ce made it so that both HW and SW bridging go through
|
|
`createAudioPatch()`, which is broken on some devices such as on MTK Q
|
|
vendor, because their HAL do not support HW patching via the newer
|
|
`createAudioPatch()` method. Instead, the patching on Q was done through
|
|
`setOutputDevices()`.
|
|
|
|
On S, commit 51c9cc refactored the related code again such that HW
|
|
bridging for the Rx direction is essentially removed, replaced with SW
|
|
bridging through `startAudioSource()`. This is, again, broken on MTK R
|
|
vendor devices.
|
|
|
|
On T, commit b2e5cb applied the same SW bridging to the Tx direction.
|
|
|
|
All of these commits rely on assumptions that are not tested through
|
|
VTS and just presumed to be true. Although we can blame MTK for not
|
|
supporting all the possible cases in their HAL, it will not fix
|
|
anything, and really frameworks code should not depend on such untested
|
|
assumptions.
|
|
|
|
To work around said issues, we restore old behavior from S, R and Q
|
|
relying on the value of `ro.vndk.version`.
|
|
|
|
Change-Id: I56d36d2aef4319935cb88a3e4771b23c6d5b2145
|
|
---
|
|
.../managerdefault/AudioPolicyManager.cpp | 103 ++++++++++++++++--
|
|
.../managerdefault/AudioPolicyManager.h | 3 +
|
|
2 files changed, 96 insertions(+), 10 deletions(-)
|
|
|
|
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
|
|
index 4573382a06..c218c7ce2d 100644
|
|
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
|
|
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
|
|
@@ -675,6 +675,17 @@ status_t AudioPolicyManager::updateCallRoutingInternal(
|
|
disconnectTelephonyAudioSource(mCallRxSourceClient);
|
|
disconnectTelephonyAudioSource(mCallTxSourceClient);
|
|
|
|
+ // release existing RX patch if any
|
|
+ if (mCallRxPatch != 0) {
|
|
+ releaseAudioPatchInternal(mCallRxPatch->getHandle());
|
|
+ mCallRxPatch.clear();
|
|
+ }
|
|
+ // release TX patch if any
|
|
+ if (mCallTxPatch != 0) {
|
|
+ releaseAudioPatchInternal(mCallTxPatch->getHandle());
|
|
+ mCallTxPatch.clear();
|
|
+ }
|
|
+
|
|
auto telephonyRxModule =
|
|
mHwModules.getModuleForDeviceType(AUDIO_DEVICE_IN_TELEPHONY_RX, AUDIO_FORMAT_DEFAULT);
|
|
auto telephonyTxModule =
|
|
@@ -697,9 +708,20 @@ status_t AudioPolicyManager::updateCallRoutingInternal(
|
|
ALOGE("%s() no telephony Tx and/or RX device", __func__);
|
|
return INVALID_OPERATION;
|
|
}
|
|
- // createAudioPatchInternal now supports both HW / SW bridging
|
|
- createRxPatch = true;
|
|
- createTxPatch = true;
|
|
+ if (property_get_int32("ro.vndk.version", 31) >= 30) {
|
|
+ // createAudioPatchInternal now supports both HW / SW bridging
|
|
+ createRxPatch = true;
|
|
+ createTxPatch = true;
|
|
+ } else {
|
|
+ // pre-R behavior: some devices before VNDK 30 do not support createAudioPatch correctly
|
|
+ // for HW bridging even though they declare support for it
|
|
+ // do not create a patch (aka Sw Bridging) if Primary HW module has declared supporting a
|
|
+ // route between telephony RX to Sink device and Source device to telephony TX
|
|
+ ALOGI("%s() Using pre-R behavior for createRxPatch and createTxPatch", __func__);
|
|
+ const auto &primaryModule = telephonyRxModule;
|
|
+ createRxPatch = !primaryModule->supportsPatch(rxSourceDevice, rxDevices.itemAt(0));
|
|
+ createTxPatch = !primaryModule->supportsPatch(txSourceDevice, txSinkDevice);
|
|
+ }
|
|
} else {
|
|
// If the RX device is on the primary HW module, then use legacy routing method for
|
|
// voice calls via setOutputDevice() on primary output.
|
|
@@ -716,7 +738,14 @@ status_t AudioPolicyManager::updateCallRoutingInternal(
|
|
if (!createRxPatch) {
|
|
muteWaitMs = setOutputDevices(mPrimaryOutput, rxDevices, true, delayMs);
|
|
} else { // create RX path audio patch
|
|
- connectTelephonyRxAudioSource();
|
|
+ if (property_get_int32("ro.vndk.version", 31) >= 31) {
|
|
+ connectTelephonyRxAudioSource();
|
|
+ } else {
|
|
+ // pre-S behavior: some devices do not support SW bridging correctly when HW bridge is
|
|
+ // available through createAudioPatch(); startAudioSource() forces SW bridging.
|
|
+ ALOGI("%s() Using pre-S behavior to create HW Rx patch", __func__);
|
|
+ mCallRxPatch = createTelephonyPatch(true /*isRx*/, rxDevices.itemAt(0), delayMs);
|
|
+ }
|
|
// If the TX device is on the primary HW module but RX device is
|
|
// on other HW module, SinkMetaData of telephony input should handle it
|
|
// assuming the device uses audio HAL V5.0 and above
|
|
@@ -731,7 +760,12 @@ status_t AudioPolicyManager::updateCallRoutingInternal(
|
|
closeActiveClients(activeDesc);
|
|
}
|
|
}
|
|
- connectTelephonyTxAudioSource(txSourceDevice, txSinkDevice, delayMs);
|
|
+ if (property_get_int32("ro.vndk.version", 33) >= 33) {
|
|
+ connectTelephonyTxAudioSource(txSourceDevice, txSinkDevice, delayMs);
|
|
+ } else {
|
|
+ // pre-T behavior: hw bridging for tx too; skip the SwOutput
|
|
+ mCallTxPatch = createTelephonyPatch(false /*isRx*/, txSourceDevice, delayMs);
|
|
+ }
|
|
}
|
|
if (waitMs != nullptr) {
|
|
*waitMs = muteWaitMs;
|
|
@@ -739,6 +773,36 @@ status_t AudioPolicyManager::updateCallRoutingInternal(
|
|
return NO_ERROR;
|
|
}
|
|
|
|
+sp<AudioPatch> AudioPolicyManager::createTelephonyPatch(
|
|
+ bool isRx, const sp<DeviceDescriptor> &device, uint32_t delayMs) {
|
|
+ PatchBuilder patchBuilder;
|
|
+
|
|
+ if (device == nullptr) {
|
|
+ return nullptr;
|
|
+ }
|
|
+
|
|
+ // @TODO: still ignoring the address, or not dealing platform with multiple telephony devices
|
|
+ if (isRx) {
|
|
+ patchBuilder.addSink(device).
|
|
+ addSource(mAvailableInputDevices.getDevice(
|
|
+ AUDIO_DEVICE_IN_TELEPHONY_RX, String8(), AUDIO_FORMAT_DEFAULT));
|
|
+ } else {
|
|
+ patchBuilder.addSource(device).
|
|
+ addSink(mAvailableOutputDevices.getDevice(
|
|
+ AUDIO_DEVICE_OUT_TELEPHONY_TX, String8(), AUDIO_FORMAT_DEFAULT));
|
|
+ }
|
|
+
|
|
+ audio_patch_handle_t patchHandle = AUDIO_PATCH_HANDLE_NONE;
|
|
+ status_t status =
|
|
+ createAudioPatchInternal(patchBuilder.patch(), &patchHandle, mUidCached, delayMs, nullptr);
|
|
+ ssize_t index = mAudioPatches.indexOfKey(patchHandle);
|
|
+ if (status != NO_ERROR || index < 0) {
|
|
+ ALOGW("%s() error %d creating %s audio patch", __func__, status, isRx ? "RX" : "TX");
|
|
+ return nullptr;
|
|
+ }
|
|
+ return mAudioPatches.valueAt(index);
|
|
+}
|
|
+
|
|
bool AudioPolicyManager::isDeviceOfModule(
|
|
const sp<DeviceDescriptor>& devDesc, const char *moduleId) const {
|
|
sp<HwModule> module = mHwModules.getModuleFromName(moduleId);
|
|
@@ -4541,6 +4605,7 @@ status_t AudioPolicyManager::createAudioPatchInternal(const struct audio_patch *
|
|
// in config XML to reach the sink so that is can be declared as available.
|
|
audio_io_handle_t output = AUDIO_IO_HANDLE_NONE;
|
|
sp<SwAudioOutputDescriptor> outputDesc;
|
|
+ if (sourceDesc != nullptr) { // Ignore indentation, we don't want to cuase huge conflicts...
|
|
if (!sourceDesc->isInternal()) {
|
|
// take care of dynamic routing for SwOutput selection,
|
|
audio_attributes_t attributes = sourceDesc->attributes();
|
|
@@ -4586,33 +4651,51 @@ status_t AudioPolicyManager::createAudioPatchInternal(const struct audio_patch *
|
|
outputDesc = mOutputs.valueFor(output);
|
|
if (outputDesc->isDuplicated()) {
|
|
ALOGV("%s output for device %s is duplicated",
|
|
- __func__, sinkDevice->toString().c_str());
|
|
+ __func__, sinkDevice->toString().c_str());
|
|
return INVALID_OPERATION;
|
|
}
|
|
sourceDesc->setSwOutput(outputDesc, /* closeOutput= */ false);
|
|
}
|
|
+ }
|
|
// create a software bridge in PatchPanel if:
|
|
// - source and sink devices are on different HW modules OR
|
|
// - audio HAL version is < 3.0
|
|
// - audio HAL version is >= 3.0 but no route has been declared between devices
|
|
- // - called from startAudioSource (aka sourceDesc is not internal) and source device
|
|
+ // - called from startAudioSource (aka sourceDesc is neither null nor internal) and source device
|
|
// does not have a gain controller
|
|
if (!srcDevice->hasSameHwModuleAs(sinkDevice) ||
|
|
(srcDevice->getModuleVersionMajor() < 3) ||
|
|
!srcDevice->getModule()->supportsPatch(srcDevice, sinkDevice) ||
|
|
- (!sourceDesc->isInternal() &&
|
|
+ ((sourceDesc != nullptr && !sourceDesc->isInternal()) &&
|
|
srcDevice->getAudioPort()->getGains().size() == 0)) {
|
|
// support only one sink device for now to simplify output selection logic
|
|
if (patch->num_sinks > 1) {
|
|
return INVALID_OPERATION;
|
|
}
|
|
- sourceDesc->setUseSwBridge();
|
|
+ if (sourceDesc == nullptr) {
|
|
+ SortedVector<audio_io_handle_t> outputs =
|
|
+ getOutputsForDevices(DeviceVector(sinkDevice), mOutputs);
|
|
+ // if the sink device is reachable via an opened output stream, request to
|
|
+ // go via this output stream by adding a second source to the patch
|
|
+ // description
|
|
+ output = selectOutput(outputs);
|
|
+ if (output != AUDIO_IO_HANDLE_NONE) {
|
|
+ outputDesc = mOutputs.valueFor(output);
|
|
+ if (outputDesc->isDuplicated()) {
|
|
+ ALOGV("%s output for device %s is duplicated",
|
|
+ __FUNCTION__, sinkDevice->toString().c_str());
|
|
+ return INVALID_OPERATION;
|
|
+ }
|
|
+ }
|
|
+ } else {
|
|
+ sourceDesc->setUseSwBridge();
|
|
+ }
|
|
if (outputDesc != nullptr) {
|
|
audio_port_config srcMixPortConfig = {};
|
|
outputDesc->toAudioPortConfig(&srcMixPortConfig, nullptr);
|
|
// for volume control, we may need a valid stream
|
|
srcMixPortConfig.ext.mix.usecase.stream =
|
|
- (!sourceDesc->isInternal() || isCallTxAudioSource(sourceDesc)) ?
|
|
+ ((sourceDesc != nullptr && !sourceDesc->isInternal()) || isCallTxAudioSource(sourceDesc)) ?
|
|
mEngine->getStreamTypeForAttributes(sourceDesc->attributes()) :
|
|
AUDIO_STREAM_PATCH;
|
|
patchBuilder.addSource(srcMixPortConfig);
|
|
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.h b/services/audiopolicy/managerdefault/AudioPolicyManager.h
|
|
index a69e08871b..f8762016db 100644
|
|
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.h
|
|
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.h
|
|
@@ -944,6 +944,9 @@ protected:
|
|
|
|
SoundTriggerSessionCollection mSoundTriggerSessions;
|
|
|
|
+ sp<AudioPatch> mCallTxPatch;
|
|
+ sp<AudioPatch> mCallRxPatch;
|
|
+
|
|
HwAudioOutputCollection mHwOutputs;
|
|
SourceClientCollection mAudioSources;
|
|
|
|
--
|
|
2.39.2
|
|
|