Reject mmap if the selected device for policy mix doesn't support mmap.
When there is any policy mix that selects output device, mmap request
should be rejected if the selected output device doesn't support mmap
and the mix matches request.
Bug: 301619865
Test: atest audiopolicy_tests
Test: atest AudioPlaybackCaptureTest
Change-Id: I9c6d188a4d61fb9ac7d8424b35d165033a65247c
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h b/services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h
index b560bc4..f066c09 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h
@@ -61,7 +61,7 @@
status_t updateMix(const AudioMix& mix, const std::vector<AudioMixMatchCriterion>& newCriteria);
- void closeOutput(sp<SwAudioOutputDescriptor> &desc);
+ void closeOutput(sp<SwAudioOutputDescriptor> &desc, const SwAudioOutputCollection& allOutputs);
/**
* Tries to find the best matching audio policy mix
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp
index 7ee75c7..dc0f466 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp
@@ -272,12 +272,33 @@
return BAD_VALUE;
}
-void AudioPolicyMixCollection::closeOutput(sp<SwAudioOutputDescriptor> &desc)
+void AudioPolicyMixCollection::closeOutput(sp<SwAudioOutputDescriptor> &desc,
+ const SwAudioOutputCollection& allOutputs)
{
for (size_t i = 0; i < size(); i++) {
sp<AudioPolicyMix> policyMix = itemAt(i);
- if (policyMix->getOutput() == desc) {
- policyMix->clearOutput();
+ if (policyMix->getOutput() != desc) {
+ continue;
+ }
+ policyMix->clearOutput();
+ if (policyMix->mRouteFlags != MIX_ROUTE_FLAG_RENDER) {
+ continue;
+ }
+ auto device = desc->supportedDevices().getDevice(
+ policyMix->mDeviceType, policyMix->mDeviceAddress, AUDIO_FORMAT_DEFAULT);
+ if (device == nullptr) {
+ // This must not happen
+ ALOGE("%s, the rerouted device is not found", __func__);
+ continue;
+ }
+ // Restore the policy mix mix output to the first opened output supporting a route to
+ // the mix device. This is because the current mix output can be changed to a direct output.
+ for (size_t j = 0; j < allOutputs.size(); ++j) {
+ if (allOutputs[i] != desc && !allOutputs[i]->isDuplicated() &&
+ allOutputs[i]->supportedDevices().contains(device)) {
+ policyMix->setOutput(allOutputs[i]);
+ break;
+ }
}
}
}
@@ -335,13 +356,6 @@
"audio policy mix.", __func__);
return INVALID_OPERATION;
}
- if (mixDevice != nullptr) {
- // TODO(b/301619865): Only disallow the device that doesn't support MMAP.
- ALOGD("%s: Rejecting MMAP_NOIRQ request matched to dynamic audio policy "
- "mix pointing to device %s which the mmap support is unknown at this moment",
- __func__, mixDevice->toString(false).c_str());
- return INVALID_OPERATION;
- }
}
if (mixDevice != nullptr && mixDevice->equals(requestedDevice)) {
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index e8066fb..ac15b49 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -1219,13 +1219,14 @@
return BAD_VALUE;
}
if (usePrimaryOutputFromPolicyMixes) {
- sp<DeviceDescriptor> deviceDesc =
+ sp<DeviceDescriptor> policyMixDevice =
mAvailableOutputDevices.getDevice(primaryMix->mDeviceType,
primaryMix->mDeviceAddress,
AUDIO_FORMAT_DEFAULT);
sp<SwAudioOutputDescriptor> policyDesc = primaryMix->getOutput();
bool tryDirectForFlags = policyDesc == nullptr ||
- (policyDesc->mFlags & AUDIO_OUTPUT_FLAG_DIRECT);
+ (policyDesc->mFlags & AUDIO_OUTPUT_FLAG_DIRECT) ||
+ (*flags & (AUDIO_OUTPUT_FLAG_HW_AV_SYNC | AUDIO_OUTPUT_FLAG_MMAP_NOIRQ));
// if a direct output can be opened to deliver the track's multi-channel content to the
// output rather than being downmixed by the primary output, then use this direct
// output by by-passing the primary mix if possible, otherwise fall-through to primary
@@ -1233,23 +1234,29 @@
bool tryDirectForChannelMask = policyDesc != nullptr
&& (audio_channel_count_from_out_mask(policyDesc->getConfig().channel_mask) <
audio_channel_count_from_out_mask(config->channel_mask));
- if (deviceDesc != nullptr && (tryDirectForFlags || tryDirectForChannelMask)) {
+ if (policyMixDevice != nullptr && (tryDirectForFlags || tryDirectForChannelMask)) {
audio_io_handle_t newOutput;
status = openDirectOutput(
*stream, session, config,
(audio_output_flags_t)(*flags | AUDIO_OUTPUT_FLAG_DIRECT),
- DeviceVector(deviceDesc), &newOutput);
+ DeviceVector(policyMixDevice), &newOutput);
if (status == NO_ERROR) {
policyDesc = mOutputs.valueFor(newOutput);
primaryMix->setOutput(policyDesc);
} else if (tryDirectForFlags) {
+ ALOGW("%s, failed open direct, status: %d", __func__, status);
policyDesc = nullptr;
} // otherwise use primary if available.
}
if (policyDesc != nullptr) {
policyDesc->mPolicyMix = primaryMix;
*output = policyDesc->mIoHandle;
- *selectedDeviceId = deviceDesc != 0 ? deviceDesc->getId() : AUDIO_PORT_HANDLE_NONE;
+ *selectedDeviceId = policyMixDevice != nullptr ? policyMixDevice->getId()
+ : AUDIO_PORT_HANDLE_NONE;
+ if ((policyDesc->mFlags & AUDIO_OUTPUT_FLAG_DIRECT) != AUDIO_OUTPUT_FLAG_DIRECT) {
+ // Remove direct flag as it is not on a direct output.
+ *flags = (audio_output_flags_t) (*flags & ~AUDIO_OUTPUT_FLAG_DIRECT);
+ }
ALOGV("getOutputForAttr() returns output %d", *output);
if (resultAttr->usage == AUDIO_USAGE_VIRTUAL_SOURCE) {
@@ -1258,6 +1265,13 @@
*outputType = API_OUTPUT_LEGACY;
}
return NO_ERROR;
+ } else {
+ if (policyMixDevice != nullptr) {
+ ALOGE("%s, try to use primary mix but no output found", __func__);
+ return INVALID_OPERATION;
+ }
+ // Fallback to default engine selection as the selected primary mix device is not
+ // available.
}
}
// Virtual sources must always be dynamicaly or explicitly routed
@@ -6691,7 +6705,7 @@
return;
}
const bool closingOutputWasActive = closingOutput->isActive();
- mPolicyMixes.closeOutput(closingOutput);
+ mPolicyMixes.closeOutput(closingOutput, mOutputs);
// look for duplicated outputs connected to the output being removed.
for (size_t i = 0; i < mOutputs.size(); i++) {
diff --git a/services/audiopolicy/tests/audiopolicymanager_tests.cpp b/services/audiopolicy/tests/audiopolicymanager_tests.cpp
index 8dbf471..74d3474 100644
--- a/services/audiopolicy/tests/audiopolicymanager_tests.cpp
+++ b/services/audiopolicy/tests/audiopolicymanager_tests.cpp
@@ -211,7 +211,7 @@
std::unique_ptr<AudioPolicyManagerTestClient> mClient;
std::unique_ptr<AudioPolicyTestManager> mManager;
- const uint32_t k48000SamplingRate = 48000;
+ constexpr static const uint32_t k48000SamplingRate = 48000;
};
void AudioPolicyManagerTest::SetUp() {
@@ -1274,13 +1274,30 @@
std::string mixAddress, const audio_config_t& audioConfig,
const std::vector<AudioMixMatchCriterion>& matchCriteria);
void clearPolicyMix();
+ void addPolicyMixAndStartInputForLoopback(
+ int mixType, int mixFlag, audio_devices_t deviceType, std::string mixAddress,
+ const audio_config_t& audioConfig,
+ const std::vector<AudioMixMatchCriterion>& matchCriteria,
+ audio_session_t session=AUDIO_SESSION_NONE,
+ audio_config_base_t config=DEFAULT_INPUT_CONFIG,
+ audio_input_flags_t inputFlags=AUDIO_INPUT_FLAG_NONE);
Vector<AudioMix> mAudioMixes;
const std::string mMixAddress = "remote_submix_media";
+
+ audio_port_handle_t mLoopbackInputPortId = AUDIO_PORT_HANDLE_NONE;
+ std::unique_ptr<RecordingActivityTracker> mTracker;
+ struct audio_port_v7 mInjectionPort;
+
+ constexpr static const audio_config_base_t DEFAULT_INPUT_CONFIG = {
+ .sample_rate = k48000SamplingRate,
+ .channel_mask = AUDIO_CHANNEL_IN_STEREO,
+ .format = AUDIO_FORMAT_PCM_16_BIT
+ };
};
void AudioPolicyManagerTestDynamicPolicy::TearDown() {
- mManager->unregisterPolicyMixes(mAudioMixes);
+ clearPolicyMix();
AudioPolicyManagerTestWithConfigurationFile::TearDown();
}
@@ -1302,11 +1319,45 @@
void AudioPolicyManagerTestDynamicPolicy::clearPolicyMix() {
if (mManager != nullptr) {
+ mManager->stopInput(mLoopbackInputPortId);
mManager->unregisterPolicyMixes(mAudioMixes);
}
mAudioMixes.clear();
}
+void AudioPolicyManagerTestDynamicPolicy::addPolicyMixAndStartInputForLoopback(
+ int mixType, int mixFlag, audio_devices_t deviceType, std::string mixAddress,
+ const audio_config_t& audioConfig,
+ const std::vector<AudioMixMatchCriterion>& matchCriteria, audio_session_t session,
+ audio_config_base_t config, audio_input_flags_t inputFlags) {
+ ASSERT_EQ(NO_ERROR,
+ addPolicyMix(mixType, mixFlag, deviceType, mixAddress, audioConfig, matchCriteria));
+ if ((mixFlag & MIX_ROUTE_FLAG_LOOP_BACK) != MIX_ROUTE_FLAG_LOOP_BACK) {
+ return;
+ }
+
+ mTracker.reset(new RecordingActivityTracker());
+ struct audio_port_v7 extractionPort;
+ ASSERT_TRUE(findDevicePort(AUDIO_PORT_ROLE_SOURCE, AUDIO_DEVICE_IN_REMOTE_SUBMIX,
+ mixAddress, &extractionPort));
+ audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE;
+ audio_source_t source = AUDIO_SOURCE_REMOTE_SUBMIX;
+ audio_attributes_t attr = {
+ AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_UNKNOWN, source, AUDIO_FLAG_NONE, ""};
+ std::string tags = "addr=" + mMixAddress;
+ audio_io_handle_t input = AUDIO_PORT_HANDLE_NONE;
+ strncpy(attr.tags, tags.c_str(), AUDIO_ATTRIBUTES_TAGS_MAX_SIZE - 1);
+ ASSERT_NO_FATAL_FAILURE(
+ getInputForAttr(attr, &input, session, mTracker->getRiid(),
+ &selectedDeviceId, config.format, config.channel_mask,
+ config.sample_rate, inputFlags, &mLoopbackInputPortId));
+ ASSERT_EQ(NO_ERROR, mManager->startInput(mLoopbackInputPortId));
+ ASSERT_EQ(extractionPort.id, selectedDeviceId);
+
+ ASSERT_TRUE(findDevicePort(AUDIO_PORT_ROLE_SINK, AUDIO_DEVICE_OUT_REMOTE_SUBMIX,
+ mMixAddress, &mInjectionPort));
+}
+
TEST_F(AudioPolicyManagerTestDynamicPolicy, InitSuccess) {
// SetUp must finish with no assertions
}
@@ -1684,11 +1735,6 @@
public testing::WithParamInterface<DPTestParam> {
protected:
void SetUp() override;
- void TearDown() override;
-
- std::unique_ptr<RecordingActivityTracker> mTracker;
- struct audio_port_v7 mInjectionPort;
- audio_port_handle_t mPortId = AUDIO_PORT_HANDLE_NONE;
};
void AudioPolicyManagerTestDPPlaybackReRouting::SetUp() {
@@ -1702,34 +1748,10 @@
audioConfig.sample_rate = k48000SamplingRate;
DPTestParam param = GetParam();
- status_t ret = addPolicyMix(MIX_TYPE_PLAYERS, MIX_ROUTE_FLAG_LOOP_BACK,
- AUDIO_DEVICE_OUT_REMOTE_SUBMIX, mMixAddress, audioConfig, param.mixCriteria);
- ASSERT_EQ(NO_ERROR, ret);
-
- struct audio_port_v7 extractionPort;
- ASSERT_TRUE(findDevicePort(AUDIO_PORT_ROLE_SOURCE, AUDIO_DEVICE_IN_REMOTE_SUBMIX,
- mMixAddress, &extractionPort));
-
- audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE;
- audio_source_t source = AUDIO_SOURCE_REMOTE_SUBMIX;
- audio_attributes_t attr = {
- AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_UNKNOWN, source, AUDIO_FLAG_NONE, ""};
- std::string tags = "addr=" + mMixAddress;
- audio_io_handle_t input = AUDIO_PORT_HANDLE_NONE;
- strncpy(attr.tags, tags.c_str(), AUDIO_ATTRIBUTES_TAGS_MAX_SIZE - 1);
- getInputForAttr(attr, &input, param.session, mTracker->getRiid(),
- &selectedDeviceId, AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_IN_STEREO,
- k48000SamplingRate, AUDIO_INPUT_FLAG_NONE, &mPortId);
- ASSERT_EQ(NO_ERROR, mManager->startInput(mPortId));
- ASSERT_EQ(extractionPort.id, selectedDeviceId);
-
- ASSERT_TRUE(findDevicePort(AUDIO_PORT_ROLE_SINK, AUDIO_DEVICE_OUT_REMOTE_SUBMIX,
- mMixAddress, &mInjectionPort));
-}
-
-void AudioPolicyManagerTestDPPlaybackReRouting::TearDown() {
- mManager->stopInput(mPortId);
- AudioPolicyManagerTestDynamicPolicy::TearDown();
+ ASSERT_NO_FATAL_FAILURE(
+ addPolicyMixAndStartInputForLoopback(MIX_TYPE_PLAYERS, MIX_ROUTE_FLAG_LOOP_BACK,
+ AUDIO_DEVICE_OUT_REMOTE_SUBMIX, mMixAddress, audioConfig, param.mixCriteria,
+ param.session));
}
TEST_P(AudioPolicyManagerTestDPPlaybackReRouting, PlaybackReRouting) {
@@ -1924,12 +1946,14 @@
// Add mix matching the test uid.
const int testUid = 12345;
const auto param = GetParam();
- status_t ret = addPolicyMix(MIX_TYPE_PLAYERS, param.mixRouteFlags, param.deviceType,
- param.deviceAddress, audioConfig, {createUidCriterion(testUid)});
- ASSERT_EQ(NO_ERROR, ret);
+ ASSERT_NO_FATAL_FAILURE(
+ addPolicyMixAndStartInputForLoopback(MIX_TYPE_PLAYERS, param.mixRouteFlags,
+ param.deviceType, param.deviceAddress, audioConfig,
+ {createUidCriterion(testUid)}));
- // Geting output for matching uid and mmap-ed stream should fail.
- audio_output_flags_t outputFlags = AUDIO_OUTPUT_FLAG_MMAP_NOIRQ;
+ // Getting output for matching uid and mmap-ed stream should fail.
+ audio_output_flags_t outputFlags =
+ (audio_output_flags_t) (AUDIO_OUTPUT_FLAG_MMAP_NOIRQ | AUDIO_OUTPUT_FLAG_DIRECT);
ASSERT_EQ(INVALID_OPERATION,
mManager->getOutputForAttr(&attr, &mOutput, AUDIO_SESSION_NONE, &mStream,
createAttributionSourceState(testUid), &audioConfig,
@@ -1942,11 +1966,12 @@
// Add mix matching the test uid.
const int testUid = 12345;
const auto param = GetParam();
- status_t ret = addPolicyMix(MIX_TYPE_PLAYERS, param.mixRouteFlags, param.deviceType,
- param.deviceAddress, audioConfig, {createUidCriterion(testUid)});
- ASSERT_EQ(NO_ERROR, ret);
+ ASSERT_NO_FATAL_FAILURE(
+ addPolicyMixAndStartInputForLoopback(MIX_TYPE_PLAYERS, param.mixRouteFlags,
+ param.deviceType,param.deviceAddress, audioConfig,
+ {createUidCriterion(testUid)}));
- // Geting output for matching uid should succeed for non-mmaped stream.
+ // Getting output for matching uid should succeed for non-mmaped stream.
audio_output_flags_t outputFlags = AUDIO_OUTPUT_FLAG_NONE;
ASSERT_EQ(NO_ERROR,
mManager->getOutputForAttr(&attr, &mOutput, AUDIO_SESSION_NONE, &mStream,
@@ -1957,23 +1982,57 @@
TEST_F(AudioPolicyManagerTestMMapPlaybackRerouting,
MmapPlaybackStreamMatchingRenderDapMixSupportingMmapSucceeds) {
+ const std::string usbAddress = "card=1;device=0";
+ ASSERT_EQ(NO_ERROR, mManager->setDeviceConnectionState(
+ AUDIO_DEVICE_OUT_USB_DEVICE, AUDIO_POLICY_DEVICE_STATE_AVAILABLE,
+ usbAddress.c_str(), "", AUDIO_FORMAT_DEFAULT));
+ audio_port_v7 usbDevicePort;
+ ASSERT_TRUE(findDevicePort(AUDIO_PORT_ROLE_SINK, AUDIO_DEVICE_OUT_USB_DEVICE,
+ usbAddress, &usbDevicePort));
+
// Add render-only mix matching the test uid.
const int testUid = 12345;
// test_audio_policy_configuration.xml declares mmap-capable mix port
// for AUDIO_DEVICE_OUT_USB_DEVICE.
- status_t ret = addPolicyMix(MIX_TYPE_PLAYERS, MIX_ROUTE_FLAG_RENDER,
- AUDIO_DEVICE_OUT_USB_DEVICE, /*mixAddress=*/"",
- audioConfig, {createUidCriterion(testUid)});
- ASSERT_EQ(NO_ERROR, ret);
+ ASSERT_EQ(NO_ERROR,
+ addPolicyMix(MIX_TYPE_PLAYERS, MIX_ROUTE_FLAG_RENDER,
+ AUDIO_DEVICE_OUT_USB_DEVICE, /*mixAddress=*/"",
+ audioConfig, {createUidCriterion(testUid)}));
- // Geting output for matching uid should succeed for mmaped stream, because matched mix
+ static const audio_output_flags_t mmapDirectFlags =
+ (audio_output_flags_t) (AUDIO_OUTPUT_FLAG_MMAP_NOIRQ | AUDIO_OUTPUT_FLAG_DIRECT);
+ // Getting output for matching uid should succeed for mmaped stream, because matched mix
// redirects to mmap capable device.
- audio_output_flags_t outputFlags = AUDIO_OUTPUT_FLAG_MMAP_NOIRQ;
+ audio_output_flags_t outputFlags = mmapDirectFlags;
ASSERT_EQ(NO_ERROR,
mManager->getOutputForAttr(&attr, &mOutput, AUDIO_SESSION_NONE, &mStream,
createAttributionSourceState(testUid), &audioConfig,
&outputFlags, &mSelectedDeviceId, &mPortId, {},
&mOutputType, &mIsSpatialized, &mIsBitPerfect));
+ ASSERT_EQ(usbDevicePort.id, mSelectedDeviceId);
+ auto outputDesc = mManager->getOutputs().valueFor(mOutput);
+ ASSERT_NE(nullptr, outputDesc);
+ ASSERT_EQ(mmapDirectFlags, outputDesc->getFlags().output);
+
+ // After releasing the client, the output is closed. APM should reselect output for the policy
+ // mix.
+ mManager->releaseOutput(mPortId);
+ ASSERT_EQ(nullptr, mManager->getOutputs().valueFor(mOutput));
+ outputFlags = AUDIO_OUTPUT_FLAG_NONE;
+ mPortId = AUDIO_PORT_HANDLE_NONE;
+ ASSERT_EQ(NO_ERROR,
+ mManager->getOutputForAttr(&attr, &mOutput, AUDIO_SESSION_NONE, &mStream,
+ createAttributionSourceState(testUid), &audioConfig,
+ &outputFlags, &mSelectedDeviceId, &mPortId, {},
+ &mOutputType, &mIsSpatialized, &mIsBitPerfect));
+ ASSERT_EQ(usbDevicePort.id, mSelectedDeviceId);
+ outputDesc = mManager->getOutputs().valueFor(mOutput);
+ ASSERT_NE(nullptr, outputDesc);
+ ASSERT_NE(mmapDirectFlags, outputDesc->getFlags().output);
+
+ ASSERT_EQ(NO_ERROR, mManager->setDeviceConnectionState(
+ AUDIO_DEVICE_OUT_USB_DEVICE, AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
+ usbAddress.c_str(), "", AUDIO_FORMAT_DEFAULT));
}
TEST_F(AudioPolicyManagerTestMMapPlaybackRerouting,
@@ -1981,14 +2040,15 @@
// Add render-only mix matching the test uid.
const int testUid = 12345;
// Per test_audio_policy_configuration.xml AUDIO_DEVICE_OUT_SPEAKER doesn't support mmap.
- status_t ret = addPolicyMix(MIX_TYPE_PLAYERS, MIX_ROUTE_FLAG_RENDER,
- AUDIO_DEVICE_OUT_SPEAKER, /*mixAddress=*/"", audioConfig,
- {createUidCriterion(testUid)});
- ASSERT_EQ(NO_ERROR, ret);
+ ASSERT_EQ(NO_ERROR,
+ addPolicyMix(MIX_TYPE_PLAYERS, MIX_ROUTE_FLAG_RENDER,
+ AUDIO_DEVICE_OUT_SPEAKER, /*mixAddress=*/"", audioConfig,
+ {createUidCriterion(testUid)}));
- // Geting output for matching uid should fail for mmaped stream, because
+ // Getting output for matching uid should fail for mmaped stream, because
// matched mix redirects to device which doesn't support mmap.
- audio_output_flags_t outputFlags = AUDIO_OUTPUT_FLAG_MMAP_NOIRQ;
+ audio_output_flags_t outputFlags =
+ (audio_output_flags_t) (AUDIO_OUTPUT_FLAG_MMAP_NOIRQ | AUDIO_OUTPUT_FLAG_DIRECT);
ASSERT_EQ(INVALID_OPERATION,
mManager->getOutputForAttr(&attr, &mOutput, AUDIO_SESSION_NONE, &mStream,
createAttributionSourceState(testUid), &audioConfig,
@@ -2322,6 +2382,7 @@
static const std::string sCarBusNavigationOutput;
static const std::string sCarRearZoneOneOutput;
static const std::string sCarRearZoneTwoOutput;
+ static const std::string sCarBusMmapOutput;
};
const std::string AudioPolicyManagerCarTest::sCarConfig =
@@ -2335,6 +2396,8 @@
const std::string AudioPolicyManagerCarTest::sCarRearZoneTwoOutput = "bus200_audio_zone_2";
+const std::string AudioPolicyManagerCarTest::sCarBusMmapOutput = "bus8_mmap_out";
+
TEST_F(AudioPolicyManagerCarTest, InitSuccess) {
// SetUp must finish with no assertions.
}
@@ -2784,6 +2847,37 @@
ASSERT_EQ(navDevicePort.id, selectedDeviceId);
}
+TEST_F(AudioPolicyManagerCarTest, GetOutputForAttrForMMapWithPolicyMatched) {
+ status_t ret;
+ audio_config_t audioConfig = AUDIO_CONFIG_INITIALIZER;
+ audioConfig.channel_mask = AUDIO_CHANNEL_OUT_STEREO;
+ audioConfig.format = AUDIO_FORMAT_PCM_16_BIT;
+ audioConfig.sample_rate = k48000SamplingRate;
+ std::vector<AudioMixMatchCriterion> mediaMatchCriteria = {
+ createUsageCriterion(AUDIO_USAGE_MEDIA, /*exclude=*/ false)};
+ ret = addPolicyMix(MIX_TYPE_PLAYERS, MIX_ROUTE_FLAG_RENDER,
+ AUDIO_DEVICE_OUT_BUS, sCarBusMmapOutput, audioConfig, mediaMatchCriteria);
+ ASSERT_EQ(NO_ERROR, ret);
+ ASSERT_EQ(NO_ERROR, ret);
+ audio_port_v7 mmapDevicePort;
+ ASSERT_TRUE(findDevicePort(AUDIO_PORT_ROLE_SINK, AUDIO_DEVICE_OUT_BUS,
+ sCarBusMmapOutput, &mmapDevicePort));
+ audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE;
+ audio_io_handle_t output;
+ audio_port_handle_t portId;
+ const audio_attributes_t mediaAttribute = {
+ AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_MEDIA,
+ AUDIO_SOURCE_DEFAULT, AUDIO_FLAG_NONE, ""};
+
+ getOutputForAttr(
+ &selectedDeviceId, AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_OUT_STEREO,
+ k48000SamplingRate,
+ (audio_output_flags_t)(AUDIO_OUTPUT_FLAG_MMAP_NOIRQ | AUDIO_OUTPUT_FLAG_DIRECT),
+ &output, &portId, mediaAttribute);
+
+ ASSERT_EQ(mmapDevicePort.id, selectedDeviceId);
+}
+
class AudioPolicyManagerTVTest : public AudioPolicyManagerTestWithConfigurationFile {
protected:
std::string getConfigFile() override { return sTvConfig; }
diff --git a/services/audiopolicy/tests/resources/test_audio_policy_configuration.xml b/services/audiopolicy/tests/resources/test_audio_policy_configuration.xml
index 9e092c6..4efdf8a 100644
--- a/services/audiopolicy/tests/resources/test_audio_policy_configuration.xml
+++ b/services/audiopolicy/tests/resources/test_audio_policy_configuration.xml
@@ -56,7 +56,7 @@
</mixPort>
<mixPort name="hifi_output" role="source" flags="AUDIO_OUTPUT_FLAG_BIT_PERFECT"/>
<mixPort name="mmap_no_irq_out" role="source"
- flags="AUDIO_OUTPUT_FLAG_DIRECT|AUDIO_OUTPUT_FLAG_MMAP_NOIRQ">
+ flags="AUDIO_OUTPUT_FLAG_DIRECT AUDIO_OUTPUT_FLAG_MMAP_NOIRQ">
<profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
</mixPort>
diff --git a/services/audiopolicy/tests/resources/test_car_ap_atmos_offload_configuration.xml b/services/audiopolicy/tests/resources/test_car_ap_atmos_offload_configuration.xml
index d131ed8..d40ebfc 100644
--- a/services/audiopolicy/tests/resources/test_car_ap_atmos_offload_configuration.xml
+++ b/services/audiopolicy/tests/resources/test_car_ap_atmos_offload_configuration.xml
@@ -30,6 +30,7 @@
<item>bus5_alarm_out</item>
<item>bus6_notification_out</item>
<item>bus7_system_sound_out</item>
+ <item>bus8_mmap_out</item>
<!-- names with _audio_zone_# are used for defined an emulator rear seat audio zone
where each number # is the zone id number -->
<item>bus100_audio_zone_1</item>
@@ -96,6 +97,11 @@
samplingRates="48000"
channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
</mixPort>
+ <mixPort name="mixport_bus8_mmap_out" role="source"
+ flags="AUDIO_OUTPUT_FLAG_DIRECT|AUDIO_OUTPUT_FLAG_MMAP_NOIRQ">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+ </mixPort>
<mixPort name="mixport_bus100_audio_zone_1" role="source">
<profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
samplingRates="48000"
@@ -213,6 +219,16 @@
stepValueMB="100"/>
</gains>
</devicePort>
+ <devicePort tagName="bus8_mmap_out" role="sink" type="AUDIO_DEVICE_OUT_BUS"
+ address="bus8_mmap_out">
+ <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
+ samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
+ <gains>
+ <gain name="" mode="AUDIO_GAIN_MODE_JOINT"
+ minValueMB="-3200" maxValueMB="600" defaultValueMB="0"
+ stepValueMB="100"/>
+ </gains>
+ </devicePort>
<devicePort tagName="bus100_audio_zone_1" role="sink" type="AUDIO_DEVICE_OUT_BUS"
address="bus100_audio_zone_1">
<profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
@@ -295,6 +311,8 @@
sources="mixport_bus6_notification_out"/>
<route type="mix" sink="bus7_system_sound_out"
sources="mixport_bus7_system_sound_out"/>
+ <route type="mix" sink="bus8_mmap_out"
+ sources="mixport_bus8_mmap_out"/>
<route type="mix" sink="bus100_audio_zone_1" sources="mixport_bus100_audio_zone_1"/>
<route type="mix" sink="bus200_audio_zone_2" sources="mixport_bus200_audio_zone_2"/>
<route type="mix" sink="primary input"