APM: Provide mix port flags via 'listAudioPorts'
Flags are now provided for mix ports via the 'active_config.flags'
field of 'audio_port_v7'.
To enable this, the following changes were made:
1. Use 'AUDIO_PORT_CONFIG_ALL' config for the export in
Audio{Input|Output}Descriptor::toAudioPortConfig.
2. Fix duplication of 'mFlags' field between AudioOutputDescriptor
and its base class AudioPortConfig.
3. Add 'mFlags' field to AudioInputDescriptor which is a reference
to the relevant part of AudioPortConfig.mFlags (same mechanism
as in 2.)
4. Verify behavior in
AudioPolicyManagerTestWithConfigurationFile#ListAudioPortsHasFlags
Also, 'test_audio_policy_configuration.xml' was updated to V7 syntax
to exercise more paths in APM.
Bug: 218507839
Test: atest audiopolicy_tests
Change-Id: I78fbd53dde15a90eca104aa17c68282563f8633a
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioInputDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/AudioInputDescriptor.h
index 856ae66..c26ea10 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioInputDescriptor.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioInputDescriptor.h
@@ -144,6 +144,7 @@
AudioPolicyClientInterface * const mClientInterface;
int32_t mGlobalActiveCount = 0; // non-client-specific activity ref count
EffectDescriptorCollection mEnabledEffects;
+ audio_input_flags_t& mFlags = AudioPortConfig::mFlags.input;
};
class AudioInputCollection :
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h
index 69082ac..b5373cb 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h
@@ -316,6 +316,7 @@
AudioPolicyClientInterface * const mClientInterface;
uint32_t mGlobalActiveCount = 0; // non-client-specific active count
audio_patch_handle_t mPatchHandle = AUDIO_PATCH_HANDLE_NONE;
+ audio_output_flags_t& mFlags = AudioPortConfig::mFlags.output;
// The ActiveClients shows the clients that contribute to the @VolumeSource counts
// and may include upstream clients from a duplicating thread.
@@ -424,7 +425,7 @@
const sp<IOProfile> mProfile; // I/O profile this output derives from
audio_io_handle_t mIoHandle; // output handle
uint32_t mLatency; //
- audio_output_flags_t mFlags; //
+ using AudioOutputDescriptor::mFlags;
sp<SwAudioOutputDescriptor> mOutput1; // used by duplicated outputs: first output
sp<SwAudioOutputDescriptor> mOutput2; // used by duplicated outputs: second output
uint32_t mDirectOpenCount; // number of clients using this output (direct outputs only)
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioInputDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioInputDescriptor.cpp
index 966b8cb..6f71ac5 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioInputDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioInputDescriptor.cpp
@@ -39,6 +39,7 @@
if (profile->getGains().size() > 0) {
profile->getGains()[0]->getDefaultConfig(&mGain);
}
+ mFlags = (audio_input_flags_t)profile->getFlags();
}
}
@@ -77,8 +78,7 @@
{
ALOG_ASSERT(mProfile != 0,
"toAudioPortConfig() called on input with null profile %d", mIoHandle);
- dstConfig->config_mask = AUDIO_PORT_CONFIG_SAMPLE_RATE|AUDIO_PORT_CONFIG_CHANNEL_MASK|
- AUDIO_PORT_CONFIG_FORMAT|AUDIO_PORT_CONFIG_GAIN;
+ dstConfig->config_mask = AUDIO_PORT_CONFIG_ALL;
if (srcConfig != NULL) {
dstConfig->config_mask |= srcConfig->config_mask;
}
@@ -512,8 +512,13 @@
void AudioInputDescriptor::dump(String8 *dst, int spaces, const char* extraInfo) const
{
- dst->appendFormat("Port ID: %d%s%s\n",
- getId(), extraInfo != nullptr ? "; " : "", extraInfo != nullptr ? extraInfo : "");
+ std::string flagsLiteral = toString(mFlags);
+ if (!flagsLiteral.empty()) {
+ flagsLiteral = " (" + flagsLiteral + ")";
+ }
+ dst->appendFormat("Port ID: %d; 0x%04x%s%s%s\n",
+ getId(), mFlags, flagsLiteral.c_str(),
+ extraInfo != nullptr ? "; " : "", extraInfo != nullptr ? extraInfo : "");
dst->appendFormat("%*s%s; %d; Channel mask: 0x%x\n", spaces, "",
audio_format_to_string(mFormat), mSamplingRate, mChannelMask);
dst->appendFormat("%*sDevices: %s\n", spaces, "",
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
index 663c80a..9979392 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
@@ -202,8 +202,7 @@
void AudioOutputDescriptor::toAudioPortConfig(struct audio_port_config *dstConfig,
const struct audio_port_config *srcConfig) const
{
- dstConfig->config_mask = AUDIO_PORT_CONFIG_SAMPLE_RATE|AUDIO_PORT_CONFIG_CHANNEL_MASK|
- AUDIO_PORT_CONFIG_FORMAT|AUDIO_PORT_CONFIG_GAIN;
+ dstConfig->config_mask = AUDIO_PORT_CONFIG_ALL;
if (srcConfig != NULL) {
dstConfig->config_mask |= srcConfig->config_mask;
}
@@ -298,7 +297,6 @@
AudioPolicyClientInterface *clientInterface)
: AudioOutputDescriptor(profile, clientInterface),
mProfile(profile), mIoHandle(AUDIO_IO_HANDLE_NONE), mLatency(0),
- mFlags((audio_output_flags_t)0),
mOutput1(0), mOutput2(0), mDirectOpenCount(0),
mDirectClientSession(AUDIO_SESSION_NONE)
{
diff --git a/services/audiopolicy/tests/audiopolicymanager_tests.cpp b/services/audiopolicy/tests/audiopolicymanager_tests.cpp
index 9c1adc6..7bf7023 100644
--- a/services/audiopolicy/tests/audiopolicymanager_tests.cpp
+++ b/services/audiopolicy/tests/audiopolicymanager_tests.cpp
@@ -137,6 +137,8 @@
audio_port_handle_t *portId = nullptr);
PatchCountCheck snapshotPatchCount() { return PatchCountCheck(mClient.get()); }
+ void getAudioPorts(audio_port_type_t type, audio_port_role_t role,
+ std::vector<audio_port_v7>* ports);
// Tries to find a device port. If 'foundPort' isn't nullptr,
// will generate a failure if the port hasn't been found.
bool findDevicePort(audio_port_role_t role, audio_devices_t deviceType,
@@ -255,21 +257,26 @@
ASSERT_NE(AUDIO_PORT_HANDLE_NONE, *portId);
}
-bool AudioPolicyManagerTest::findDevicePort(audio_port_role_t role,
- audio_devices_t deviceType, const std::string &address, audio_port_v7 *foundPort) {
+void AudioPolicyManagerTest::getAudioPorts(audio_port_type_t type, audio_port_role_t role,
+ std::vector<audio_port_v7>* ports) {
uint32_t numPorts = 0;
uint32_t generation1;
status_t ret;
- ret = mManager->listAudioPorts(role, AUDIO_PORT_TYPE_DEVICE, &numPorts, nullptr, &generation1);
- EXPECT_EQ(NO_ERROR, ret) << "mManager->listAudioPorts returned error";
- if (HasFailure()) return false;
+ ret = mManager->listAudioPorts(role, type, &numPorts, nullptr, &generation1);
+ ASSERT_EQ(NO_ERROR, ret) << "mManager->listAudioPorts returned error";
uint32_t generation2;
- struct audio_port_v7 ports[numPorts];
- ret = mManager->listAudioPorts(role, AUDIO_PORT_TYPE_DEVICE, &numPorts, ports, &generation2);
- EXPECT_EQ(NO_ERROR, ret) << "mManager->listAudioPorts returned error";
- EXPECT_EQ(generation1, generation2) << "Generations changed during ports retrieval";
+ ports->resize(numPorts);
+ ret = mManager->listAudioPorts(role, type, &numPorts, ports->data(), &generation2);
+ ASSERT_EQ(NO_ERROR, ret) << "mManager->listAudioPorts returned error";
+ ASSERT_EQ(generation1, generation2) << "Generations changed during ports retrieval";
+}
+
+bool AudioPolicyManagerTest::findDevicePort(audio_port_role_t role,
+ audio_devices_t deviceType, const std::string &address, audio_port_v7 *foundPort) {
+ std::vector<audio_port_v7> ports;
+ getAudioPorts(AUDIO_PORT_TYPE_DEVICE, role, &ports);
if (HasFailure()) return false;
for (const auto &port : ports) {
@@ -671,6 +678,44 @@
dumpToLog();
}
+TEST_F(AudioPolicyManagerTestWithConfigurationFile, ListAudioPortsHasFlags) {
+ // Create an input for VOIP TX because it's not opened automatically like outputs are.
+ audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE;
+ audio_port_handle_t mixPortId = AUDIO_PORT_HANDLE_NONE;
+ audio_source_t source = AUDIO_SOURCE_VOICE_COMMUNICATION;
+ audio_attributes_t attr = {
+ AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_UNKNOWN, source, AUDIO_FLAG_NONE, ""};
+ ASSERT_NO_FATAL_FAILURE(getInputForAttr(attr, 1, &selectedDeviceId, AUDIO_FORMAT_PCM_16_BIT,
+ AUDIO_CHANNEL_IN_MONO, 8000, AUDIO_INPUT_FLAG_VOIP_TX, &mixPortId));
+
+ std::vector<audio_port_v7> ports;
+ ASSERT_NO_FATAL_FAILURE(
+ getAudioPorts(AUDIO_PORT_TYPE_MIX, AUDIO_PORT_ROLE_NONE, &ports));
+ EXPECT_NE(0, ports.size());
+ bool hasFlags = false, foundPrimary = false, foundVoipRx = false, foundVoipTx = false;
+ for (const auto& port : ports) {
+ if ((port.active_config.config_mask & AUDIO_PORT_CONFIG_FLAGS) != 0) {
+ hasFlags = true;
+ if (port.role == AUDIO_PORT_ROLE_SOURCE) {
+ if ((port.active_config.flags.output & AUDIO_OUTPUT_FLAG_PRIMARY) != 0) {
+ foundPrimary = true;
+ }
+ if ((port.active_config.flags.output & AUDIO_OUTPUT_FLAG_VOIP_RX) != 0) {
+ foundVoipRx = true;
+ }
+ } else if (port.role == AUDIO_PORT_ROLE_SINK) {
+ if ((port.active_config.flags.input & AUDIO_INPUT_FLAG_VOIP_TX) != 0) {
+ foundVoipTx = true;
+ }
+ }
+ }
+ }
+ EXPECT_TRUE(hasFlags);
+ EXPECT_TRUE(foundPrimary);
+ EXPECT_TRUE(foundVoipRx);
+ EXPECT_TRUE(foundVoipTx);
+}
+
using PolicyMixTuple = std::tuple<audio_usage_t, audio_source_t, uint32_t>;
class AudioPolicyManagerTestDynamicPolicy : public AudioPolicyManagerTestWithConfigurationFile {
diff --git a/services/audiopolicy/tests/resources/test_audio_policy_configuration.xml b/services/audiopolicy/tests/resources/test_audio_policy_configuration.xml
index 41ed70c..5e1822a 100644
--- a/services/audiopolicy/tests/resources/test_audio_policy_configuration.xml
+++ b/services/audiopolicy/tests/resources/test_audio_policy_configuration.xml
@@ -14,7 +14,7 @@
limitations under the License.
-->
-<audioPolicyConfiguration version="1.0" xmlns:xi="http://www.w3.org/2001/XInclude">
+<audioPolicyConfiguration version="7.0" xmlns:xi="http://www.w3.org/2001/XInclude">
<globalConfiguration speaker_drc_enabled="true"/>
<modules>
@@ -41,8 +41,18 @@
</mixPort>
<mixPort name="mixport_bt_hfp_input" role="sink">
<profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
- samplingRates="8000,11025,16000,44100,48000"
- channelMasks="AUDIO_CHANNEL_IN_STEREO,AUDIO_CHANNEL_IN_MONO"/>
+ samplingRates="8000 11025 16000 44100 48000"
+ channelMasks="AUDIO_CHANNEL_IN_STEREO AUDIO_CHANNEL_IN_MONO"/>
+ </mixPort>
+ <mixPort name="voip_tx" role="sink"
+ flags="AUDIO_INPUT_FLAG_VOIP_TX">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="8000 16000 32000 48000" channelMasks="AUDIO_CHANNEL_IN_MONO"/>
+ </mixPort>
+ <mixPort name="voip_rx" role="source"
+ flags="AUDIO_OUTPUT_FLAG_VOIP_RX">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="8000 16000 32000 48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
</mixPort>
</mixPorts>
<devicePorts>
@@ -64,13 +74,15 @@
</devicePorts>
<routes>
<route type="mix" sink="Speaker"
- sources="primary output"/>
+ sources="primary output,voip_rx"/>
<route type="mix" sink="primary input"
sources="Built-In Mic,Hdmi-In Mic"/>
+ <route type="mix" sink="voip_tx"
+ sources="Built-In Mic"/>
<route type="mix" sink="Hdmi"
sources="primary output"/>
<route type="mix" sink="BT SCO"
- sources="mixport_bt_hfp_output"/>
+ sources="mixport_bt_hfp_output,voip_rx"/>
<route type="mix" sink="mixport_bt_hfp_input"
sources="BT SCO Headset Mic"/>
</routes>