frameworks/av: Include more forward-ports from TD
This commit is contained in:
parent
4b704639a2
commit
4435ddab0a
|
@ -1,7 +1,7 @@
|
|||
From f8b9cb1d3cdf0274414bb7d100844d2707999558 Mon Sep 17 00:00:00 2001
|
||||
From: Peter Cai <peter@typeblog.net>
|
||||
Date: Wed, 24 Aug 2022 15:42:39 -0400
|
||||
Subject: [PATCH 1/3] APM: Optionally force-load audio policy for system-side
|
||||
Subject: [PATCH 1/5] APM: Optionally force-load audio policy for system-side
|
||||
bt audio HAL
|
||||
|
||||
Required to support our system-side bt audio implementation, i.e.
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
From d60a1b5fc58a7cc84b48c554cb2cffaeff14d86e Mon Sep 17 00:00:00 2001
|
||||
From: Peter Cai <peter@typeblog.net>
|
||||
Date: Thu, 25 Aug 2022 13:30:29 -0400
|
||||
Subject: [PATCH 2/3] APM: Remove A2DP audio ports from the primary HAL
|
||||
Subject: [PATCH 2/5] APM: Remove A2DP audio ports from the primary HAL
|
||||
|
||||
These ports defined in the primary HAL are intended for A2DP offloading,
|
||||
however they do not work in general on GSIs, and will interfere with
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
From aa1f3595b06e6d3d7027a5dd40ae183d71d032f0 Mon Sep 17 00:00:00 2001
|
||||
From: ponces <ponces26@gmail.com>
|
||||
Date: Mon, 24 Oct 2022 09:38:34 +0100
|
||||
Subject: [PATCH 3/3] voip: Fix high pitched voice on Qualcomm devices
|
||||
Subject: [PATCH 3/5] voip: Fix high pitched voice on Qualcomm devices
|
||||
|
||||
Change-Id: I6d314912169776b76d07d8c0301ec5249c1870a2
|
||||
---
|
||||
|
|
|
@ -0,0 +1,326 @@
|
|||
From 1a9a9faca4d5c28747a3b7d9843b67c641ed91c9 Mon Sep 17 00:00:00 2001
|
||||
From: Peter Cai <peter@typeblog.net>
|
||||
Date: Thu, 18 Aug 2022 15:44:46 -0400
|
||||
Subject: [PATCH 4/5] 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 | 206 ++++++++++++------
|
||||
.../managerdefault/AudioPolicyManager.h | 3 +
|
||||
2 files changed, 147 insertions(+), 62 deletions(-)
|
||||
|
||||
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
|
||||
index f093e685ba..9a90009f9e 100644
|
||||
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
|
||||
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
|
||||
@@ -689,6 +689,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 =
|
||||
@@ -711,9 +722,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.
|
||||
@@ -730,7 +752,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
|
||||
@@ -745,7 +774,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;
|
||||
@@ -753,6 +787,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);
|
||||
@@ -4958,83 +5022,101 @@ 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->isInternal()) {
|
||||
- // take care of dynamic routing for SwOutput selection,
|
||||
- audio_attributes_t attributes = sourceDesc->attributes();
|
||||
- audio_stream_type_t stream = sourceDesc->stream();
|
||||
- audio_attributes_t resultAttr;
|
||||
- audio_config_t config = AUDIO_CONFIG_INITIALIZER;
|
||||
- config.sample_rate = sourceDesc->config().sample_rate;
|
||||
- audio_channel_mask_t sourceMask = sourceDesc->config().channel_mask;
|
||||
- config.channel_mask =
|
||||
- (audio_channel_mask_get_representation(sourceMask)
|
||||
- == AUDIO_CHANNEL_REPRESENTATION_INDEX) ? sourceMask
|
||||
- : audio_channel_mask_in_to_out(sourceMask);
|
||||
- config.format = sourceDesc->config().format;
|
||||
- audio_output_flags_t flags = AUDIO_OUTPUT_FLAG_NONE;
|
||||
- audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE;
|
||||
- bool isRequestedDeviceForExclusiveUse = false;
|
||||
- output_type_t outputType;
|
||||
- bool isSpatialized;
|
||||
- bool isBitPerfect;
|
||||
- getOutputForAttrInt(&resultAttr, &output, AUDIO_SESSION_NONE, &attributes,
|
||||
- &stream, sourceDesc->uid(), &config, &flags,
|
||||
- &selectedDeviceId, &isRequestedDeviceForExclusiveUse,
|
||||
- nullptr, &outputType, &isSpatialized, &isBitPerfect);
|
||||
- if (output == AUDIO_IO_HANDLE_NONE) {
|
||||
- ALOGV("%s no output for device %s",
|
||||
- __FUNCTION__, sinkDevice->toString().c_str());
|
||||
- return INVALID_OPERATION;
|
||||
- }
|
||||
- outputDesc = mOutputs.valueFor(output);
|
||||
- if (outputDesc->isDuplicated()) {
|
||||
- ALOGE("%s output is duplicated", __func__);
|
||||
- return INVALID_OPERATION;
|
||||
- }
|
||||
- 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 =
|
||||
- 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) {
|
||||
- ALOGE("%s no output available for internal patch sink", __func__);
|
||||
- return INVALID_OPERATION;
|
||||
- }
|
||||
- outputDesc = mOutputs.valueFor(output);
|
||||
- if (outputDesc->isDuplicated()) {
|
||||
- ALOGV("%s output for device %s is duplicated",
|
||||
- __func__, sinkDevice->toString().c_str());
|
||||
- return INVALID_OPERATION;
|
||||
+ if (sourceDesc != nullptr) {
|
||||
+ if (!sourceDesc->isInternal()) {
|
||||
+ // take care of dynamic routing for SwOutput selection,
|
||||
+ audio_attributes_t attributes = sourceDesc->attributes();
|
||||
+ audio_stream_type_t stream = sourceDesc->stream();
|
||||
+ audio_attributes_t resultAttr;
|
||||
+ audio_config_t config = AUDIO_CONFIG_INITIALIZER;
|
||||
+ config.sample_rate = sourceDesc->config().sample_rate;
|
||||
+ audio_channel_mask_t sourceMask = sourceDesc->config().channel_mask;
|
||||
+ config.channel_mask =
|
||||
+ (audio_channel_mask_get_representation(sourceMask)
|
||||
+ == AUDIO_CHANNEL_REPRESENTATION_INDEX) ? sourceMask
|
||||
+ : audio_channel_mask_in_to_out(sourceMask);
|
||||
+ config.format = sourceDesc->config().format;
|
||||
+ audio_output_flags_t flags = AUDIO_OUTPUT_FLAG_NONE;
|
||||
+ audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE;
|
||||
+ bool isRequestedDeviceForExclusiveUse = false;
|
||||
+ output_type_t outputType;
|
||||
+ bool isSpatialized;
|
||||
+ bool isBitPerfect;
|
||||
+ getOutputForAttrInt(&resultAttr, &output, AUDIO_SESSION_NONE, &attributes,
|
||||
+ &stream, sourceDesc->uid(), &config, &flags,
|
||||
+ &selectedDeviceId, &isRequestedDeviceForExclusiveUse,
|
||||
+ nullptr, &outputType, &isSpatialized, &isBitPerfect);
|
||||
+ if (output == AUDIO_IO_HANDLE_NONE) {
|
||||
+ ALOGV("%s no output for device %s",
|
||||
+ __FUNCTION__, sinkDevice->toString().c_str());
|
||||
+ return INVALID_OPERATION;
|
||||
+ }
|
||||
+ outputDesc = mOutputs.valueFor(output);
|
||||
+ if (outputDesc->isDuplicated()) {
|
||||
+ ALOGE("%s output is duplicated", __func__);
|
||||
+ return INVALID_OPERATION;
|
||||
+ }
|
||||
+ 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 =
|
||||
+ 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) {
|
||||
+ ALOGE("%s no output available for internal patch sink", __func__);
|
||||
+ return INVALID_OPERATION;
|
||||
+ }
|
||||
+ outputDesc = mOutputs.valueFor(output);
|
||||
+ if (outputDesc->isDuplicated()) {
|
||||
+ ALOGV("%s output for device %s is duplicated",
|
||||
+ __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 88bafefdb1..188b5732b3 100644
|
||||
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.h
|
||||
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.h
|
||||
@@ -953,6 +953,9 @@ protected:
|
||||
|
||||
SoundTriggerSessionCollection mSoundTriggerSessions;
|
||||
|
||||
+ sp<AudioPatch> mCallTxPatch;
|
||||
+ sp<AudioPatch> mCallRxPatch;
|
||||
+
|
||||
HwAudioOutputCollection mHwOutputs;
|
||||
SourceClientCollection mAudioSources;
|
||||
|
||||
--
|
||||
2.41.0
|
||||
|
131
frameworks/av/0005-Fix-BT-in-call-on-CAF-devices.patch
Normal file
131
frameworks/av/0005-Fix-BT-in-call-on-CAF-devices.patch
Normal file
|
@ -0,0 +1,131 @@
|
|||
From 97421e35dd716c9b07ec44ec05265944efc96294 Mon Sep 17 00:00:00 2001
|
||||
From: Pierre-Hugues Husson <phh@phh.me>
|
||||
Date: Mon, 5 Aug 2019 18:09:50 +0200
|
||||
Subject: [PATCH 5/5] Fix BT in-call on CAF devices
|
||||
|
||||
See https://github.com/phhusson/treble_experimentations/issues/374
|
||||
|
||||
In Qualcomm's BSP audio_policy_configuration.xml, one route is missing,
|
||||
from primary output and telephony to BT SCO.
|
||||
|
||||
Add it if we detect telephony and bt sco, but no such route.
|
||||
|
||||
Change-Id: Ifea0f88276ec9a0811f3cb1973c4b06f2c82077b
|
||||
---
|
||||
.../managerdefinitions/src/Serializer.cpp | 93 +++++++++++++++++++
|
||||
1 file changed, 93 insertions(+)
|
||||
|
||||
diff --git a/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp b/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp
|
||||
index d23d55677d..4f896111cb 100644
|
||||
--- a/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp
|
||||
+++ b/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp
|
||||
@@ -672,6 +672,98 @@ std::variant<status_t, RouteTraits::Element> PolicySerializer::deserialize<Route
|
||||
return route;
|
||||
}
|
||||
|
||||
+static void fixupQualcommBtScoRoute(RouteTraits::Collection& routes, DevicePortTraits::Collection& devicePorts, HwModule* ctx) {
|
||||
+ // On many Qualcomm devices, there is a BT SCO Headset Mic => primary input mix
|
||||
+ // But Telephony Rx => BT SCO Headset route is missing
|
||||
+ // When we detect such case, add the missing route
|
||||
+
|
||||
+ // If we have:
|
||||
+ // <route type="mix" sink="Telephony Tx" sources="voice_tx"/>
|
||||
+ // <route type="mix" sink="primary input" sources="Built-In Mic,Built-In Back Mic,Wired Headset Mic,BT SCO Headset Mic"/>
|
||||
+ // <devicePort tagName="BT SCO Headset" type="AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET" role="sink" />
|
||||
+ // And no <route type="mix" sink="BT SCO Headset" />
|
||||
+
|
||||
+ // Add:
|
||||
+ // <route type="mix" sink="BT SCO Headset" sources="primary output,deep_buffer,compressed_offload,Telephony Rx"/>
|
||||
+ bool foundBtScoHeadsetDevice = false;
|
||||
+ for(const auto& device: devicePorts) {
|
||||
+ if(device->getTagName() == "BT SCO Headset") {
|
||||
+ foundBtScoHeadsetDevice = true;
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+ if(!foundBtScoHeadsetDevice) {
|
||||
+ ALOGE("No BT SCO Headset device found, don't patch policy");
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ bool foundTelephony = false;
|
||||
+ bool foundBtScoInput = false;
|
||||
+ bool foundScoHeadsetRoute = false;
|
||||
+ for(const auto& route: routes) {
|
||||
+ ALOGE("Looking at route %d\n", route->getType());
|
||||
+ if(route->getType() != AUDIO_ROUTE_MIX)
|
||||
+ continue;
|
||||
+ auto sink = route->getSink();
|
||||
+ ALOGE("... With sink %s\n", sink->getTagName().c_str());
|
||||
+ if(sink->getTagName() == "Telephony Tx") {
|
||||
+ foundTelephony = true;
|
||||
+ continue;
|
||||
+ }
|
||||
+ if(sink->getTagName() == "BT SCO Headset") {
|
||||
+ foundScoHeadsetRoute = true;
|
||||
+ break;
|
||||
+ }
|
||||
+ for(const auto& source: route->getSources()) {
|
||||
+ ALOGE("... With source %s\n", source->getTagName().c_str());
|
||||
+ if(source->getTagName() == "BT SCO Headset Mic") {
|
||||
+ foundBtScoInput = true;
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ //The route we want to add is already there
|
||||
+ ALOGE("Done looking for existing routes");
|
||||
+ if(foundScoHeadsetRoute)
|
||||
+ return;
|
||||
+
|
||||
+ ALOGE("No existing route found... %d %d", foundTelephony ? 1 : 0, foundBtScoInput ? 1 : 0);
|
||||
+ //We couldn't find the routes we assume are required for the function we want to add
|
||||
+ if(!foundTelephony || !foundBtScoInput)
|
||||
+ return;
|
||||
+ ALOGE("Adding our own.");
|
||||
+
|
||||
+ // Add:
|
||||
+ // <route type="mix" sink="BT SCO Headset" sources="primary output,deep_buffer,compressed_offload,Telephony Rx"/>
|
||||
+ AudioRoute *newRoute = new AudioRoute(AUDIO_ROUTE_MIX);
|
||||
+
|
||||
+ auto sink = ctx->findPortByTagName("BT SCO Headset");
|
||||
+ ALOGE("Got sink %p\n", sink.get());
|
||||
+ newRoute->setSink(sink);
|
||||
+
|
||||
+ Vector<sp<PolicyAudioPort>> sources;
|
||||
+ for(const auto& sourceName: {
|
||||
+ "primary output",
|
||||
+ "deep_buffer",
|
||||
+ "compressed_offload",
|
||||
+ "Telephony Rx"
|
||||
+ }) {
|
||||
+ auto source = ctx->findPortByTagName(sourceName);
|
||||
+ ALOGE("Got source %p\n", source.get());
|
||||
+ if (source.get() != nullptr) {
|
||||
+ sources.add(source);
|
||||
+ source->addRoute(newRoute);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ newRoute->setSources(sources);
|
||||
+
|
||||
+ sink->addRoute(newRoute);
|
||||
+
|
||||
+ auto ret = routes.add(newRoute);
|
||||
+ ALOGE("route add returned %zd", ret);
|
||||
+}
|
||||
+
|
||||
template<>
|
||||
std::variant<status_t, ModuleTraits::Element> PolicySerializer::deserialize<ModuleTraits>(
|
||||
const xmlNode *cur, ModuleTraits::PtrSerializingCtx ctx)
|
||||
@@ -739,6 +831,7 @@ std::variant<status_t, ModuleTraits::Element> PolicySerializer::deserialize<Modu
|
||||
if (status != NO_ERROR) {
|
||||
return status;
|
||||
}
|
||||
+ fixupQualcommBtScoRoute(routes, devicePorts, module.get());
|
||||
module->setRoutes(routes);
|
||||
|
||||
for (const xmlNode *children = cur->xmlChildrenNode; children != NULL;
|
||||
--
|
||||
2.41.0
|
||||
|
Loading…
Reference in a new issue