Initial unified commit for Android 14, with "light" GSI target

This commit is contained in:
Andy CrossGate Yan
2024-02-17 16:48:27 +08:00
commit ea765d3ff5
117 changed files with 15033 additions and 0 deletions

View File

@@ -0,0 +1,326 @@
From b5b0fd54c77d0c5feb3eb20395fa6e2400c41172 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/3] 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.34.1

View File

@@ -0,0 +1,61 @@
From cf178b74640512639620ed5f99122407225053f8 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/3] 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 3d5c1d2e42..881c188e4c 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>
@@ -885,6 +886,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.34.1

View File

@@ -0,0 +1,79 @@
From f792286920c7c2c43758a8e1053bab89948bf305 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/3] 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 881c188e4c..8519cfdc04 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.34.1