Initial unified commit for Android 13, with "light" GSI target
This commit is contained in:
+313
@@ -0,0 +1,313 @@
|
||||
From 51deb8e31ca57f19420277cc92b26375233e9050 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/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 | 193 +++++++++++++-----
|
||||
.../managerdefault/AudioPolicyManager.h | 3 +
|
||||
2 files changed, 141 insertions(+), 55 deletions(-)
|
||||
|
||||
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
|
||||
index 744609f27b..224dae3820 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);
|
||||
@@ -4520,76 +4584,95 @@ 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 = 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;
|
||||
- config.channel_mask = sourceDesc->config().channel_mask;
|
||||
- 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;
|
||||
- getOutputForAttrInt(&resultAttr, &output, AUDIO_SESSION_NONE, &attributes,
|
||||
- &stream, sourceDesc->uid(), &config, &flags,
|
||||
- &selectedDeviceId, &isRequestedDeviceForExclusiveUse,
|
||||
- nullptr, &outputType, &isSpatialized);
|
||||
- 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;
|
||||
- }
|
||||
- sourceDesc->setSwOutput(outputDesc);
|
||||
- } else {
|
||||
- // Same for "raw patches" aka created from createAudioPatch API
|
||||
- SortedVector<audio_io_handle_t> outputs =
|
||||
+ 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;
|
||||
+ config.channel_mask = sourceDesc->config().channel_mask;
|
||||
+ 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;
|
||||
+ getOutputForAttrInt(&resultAttr, &output, AUDIO_SESSION_NONE, &attributes,
|
||||
+ &stream, sourceDesc->uid(), &config, &flags,
|
||||
+ &selectedDeviceId, &isRequestedDeviceForExclusiveUse,
|
||||
+ nullptr, &outputType, &isSpatialized);
|
||||
+ 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;
|
||||
+ }
|
||||
+ sourceDesc->setSwOutput(outputDesc);
|
||||
+ } 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 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);
|
||||
}
|
||||
- sourceDesc->setSwOutput(outputDesc);
|
||||
}
|
||||
// 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() ?
|
||||
+ srcMixPortConfig.ext.mix.usecase.stream = (sourceDesc != nullptr && !sourceDesc->isInternal()) ?
|
||||
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 db0ee15de8..97fa6f6f81 100644
|
||||
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.h
|
||||
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.h
|
||||
@@ -938,6 +938,9 @@ protected:
|
||||
|
||||
SoundTriggerSessionCollection mSoundTriggerSessions;
|
||||
|
||||
+ sp<AudioPatch> mCallTxPatch;
|
||||
+ sp<AudioPatch> mCallRxPatch;
|
||||
+
|
||||
HwAudioOutputCollection mHwOutputs;
|
||||
SourceClientCollection mAudioSources;
|
||||
|
||||
--
|
||||
2.37.2
|
||||
|
||||
+61
@@ -0,0 +1,61 @@
|
||||
From 5def9ad1a26e28d517666e34301dc725c1660e36 Mon Sep 17 00:00:00 2001
|
||||
From: Peter Cai <peter@typeblog.net>
|
||||
Date: Wed, 24 Aug 2022 15:42:39 -0400
|
||||
Subject: [PATCH 2/5] APM: Optionally force-load audio policy for system-side
|
||||
bt audio HAL
|
||||
|
||||
Required to support our system-side bt audio implementation, i.e.
|
||||
`sysbta`.
|
||||
|
||||
Co-authored-by: Pierre-Hugues Husson <phh@phh.me>
|
||||
Change-Id: I279fff541a531f922f3fa55b8f14d00237db59ff
|
||||
---
|
||||
.../managerdefinitions/src/Serializer.cpp | 25 +++++++++++++++++++
|
||||
1 file changed, 25 insertions(+)
|
||||
|
||||
diff --git a/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp b/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp
|
||||
index d446e9667b..f5233f2a42 100644
|
||||
--- a/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp
|
||||
+++ b/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp
|
||||
@@ -25,6 +25,7 @@
|
||||
#include <libxml/parser.h>
|
||||
#include <libxml/xinclude.h>
|
||||
#include <media/convert.h>
|
||||
+#include <cutils/properties.h>
|
||||
#include <utils/Log.h>
|
||||
#include <utils/StrongPointer.h>
|
||||
#include <utils/Errors.h>
|
||||
@@ -890,6 +891,30 @@ status_t PolicySerializer::deserialize(const char *configFile, AudioPolicyConfig
|
||||
if (status != NO_ERROR) {
|
||||
return status;
|
||||
}
|
||||
+
|
||||
+ // Remove modules called bluetooth, bluetooth_qti or a2dp, and inject our own
|
||||
+ if (property_get_bool("persist.bluetooth.system_audio_hal.enabled", false)) {
|
||||
+ for (auto it = modules.begin(); it != modules.end(); it++) {
|
||||
+ const char *name = (*it)->getName();
|
||||
+ if (strcmp(name, "a2dp") == 0 ||
|
||||
+ strcmp(name, "a2dpsink") == 0 ||
|
||||
+ strcmp(name, "bluetooth") == 0 ||
|
||||
+ strcmp(name, "bluetooth_qti") == 0) {
|
||||
+
|
||||
+ ALOGE("Removed module %s\n", name);
|
||||
+ it = modules.erase(it);
|
||||
+ }
|
||||
+ if (it == modules.end()) break;
|
||||
+ }
|
||||
+ const char* a2dpFileName = "/system/etc/sysbta_audio_policy_configuration.xml";
|
||||
+ if (version == "7.0")
|
||||
+ a2dpFileName = "/system/etc/sysbta_audio_policy_configuration_7_0.xml";
|
||||
+ auto doc = make_xmlUnique(xmlParseFile(a2dpFileName));
|
||||
+ xmlNodePtr root = xmlDocGetRootElement(doc.get());
|
||||
+ auto maybeA2dpModule = deserialize<ModuleTraits>(root, config);
|
||||
+ modules.add(std::get<1>(maybeA2dpModule));
|
||||
+ }
|
||||
+
|
||||
config->setHwModules(modules);
|
||||
|
||||
// Global Configuration
|
||||
--
|
||||
2.37.2
|
||||
|
||||
+79
@@ -0,0 +1,79 @@
|
||||
From e31fc6f3f79848e6f7e7b1b4abe82aa26571cf7b Mon Sep 17 00:00:00 2001
|
||||
From: Peter Cai <peter@typeblog.net>
|
||||
Date: Thu, 25 Aug 2022 13:30:29 -0400
|
||||
Subject: [PATCH 3/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
|
||||
sysbta, the system-side generic bluetooth audio implementation.
|
||||
|
||||
Remove them as we parse the policy XML.
|
||||
|
||||
Co-authored-by: Pierre-Hugues Husson <phh@phh.me>
|
||||
Change-Id: I3305594a17285da113167b419543543f0ef71122
|
||||
---
|
||||
.../managerdefinitions/src/Serializer.cpp | 26 ++++++++++++++++---
|
||||
1 file changed, 22 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp b/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp
|
||||
index f5233f2a42..6630d06f6d 100644
|
||||
--- a/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp
|
||||
+++ b/services/audiopolicy/common/managerdefinitions/src/Serializer.cpp
|
||||
@@ -26,6 +26,7 @@
|
||||
#include <libxml/xinclude.h>
|
||||
#include <media/convert.h>
|
||||
#include <cutils/properties.h>
|
||||
+#include <system/audio.h>
|
||||
#include <utils/Log.h>
|
||||
#include <utils/StrongPointer.h>
|
||||
#include <utils/Errors.h>
|
||||
@@ -334,11 +335,8 @@ status_t PolicySerializer::deserializeCollection(const xmlNode *cur,
|
||||
Trait::collectionTag);
|
||||
return status;
|
||||
}
|
||||
- } else if (mIgnoreVendorExtensions && std::get<status_t>(maybeElement) == NO_INIT) {
|
||||
- // Skip a vendor extension element.
|
||||
- } else {
|
||||
- return BAD_VALUE;
|
||||
}
|
||||
+ // Ignore elements that failed to parse, e.g. routes with invalid sinks
|
||||
}
|
||||
}
|
||||
if (!xmlStrcmp(cur->name, reinterpret_cast<const xmlChar*>(Trait::tag))) {
|
||||
@@ -679,6 +677,7 @@ std::variant<status_t, ModuleTraits::Element> PolicySerializer::deserialize<Modu
|
||||
ALOGE("%s: No %s found", __func__, Attributes::name);
|
||||
return BAD_VALUE;
|
||||
}
|
||||
+
|
||||
uint32_t versionMajor = 0, versionMinor = 0;
|
||||
std::string versionLiteral = getXmlAttribute(cur, Attributes::version);
|
||||
if (!versionLiteral.empty()) {
|
||||
@@ -704,6 +703,25 @@ std::variant<status_t, ModuleTraits::Element> PolicySerializer::deserialize<Modu
|
||||
if (status != NO_ERROR) {
|
||||
return status;
|
||||
}
|
||||
+ bool shouldEraseA2DP = name == "primary" && property_get_bool("persist.bluetooth.system_audio_hal.enabled", false);
|
||||
+ if (shouldEraseA2DP) {
|
||||
+ // Having A2DP ports in the primary audio HAL module will interfere with sysbta
|
||||
+ // so remove them here. Note that we do not need to explicitly remove the
|
||||
+ // corresponding routes below, because routes with invalid sinks will be ignored
|
||||
+ auto iter = devicePorts.begin();
|
||||
+ while (iter != devicePorts.end()) {
|
||||
+ auto port = *iter;
|
||||
+ auto type = port->type();
|
||||
+ if (type == AUDIO_DEVICE_OUT_BLUETOOTH_A2DP
|
||||
+ || type == AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES
|
||||
+ || type == AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER) {
|
||||
+ ALOGE("Erasing A2DP device port %s", port->getTagName().c_str());
|
||||
+ iter = devicePorts.erase(iter);
|
||||
+ } else {
|
||||
+ iter++;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
module->setDeclaredDevices(devicePorts);
|
||||
|
||||
RouteTraits::Collection routes;
|
||||
--
|
||||
2.37.2
|
||||
|
||||
Reference in New Issue
Block a user