Loading services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h +1 −1 Original line number Diff line number Diff line Loading @@ -61,7 +61,7 @@ public: 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 Loading services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp +24 −10 Original line number Diff line number Diff line Loading @@ -272,12 +272,33 @@ status_t AudioPolicyMixCollection::getAudioPolicyMix(audio_devices_t deviceType, 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) { 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; } } } } Loading Loading @@ -335,13 +356,6 @@ status_t AudioPolicyMixCollection::getOutputForAttr( "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)) { Loading services/audiopolicy/managerdefault/AudioPolicyManager.cpp +20 −6 Original line number Diff line number Diff line Loading @@ -1217,13 +1217,14 @@ status_t AudioPolicyManager::getOutputForAttrInt( 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 Loading @@ -1231,23 +1232,29 @@ status_t AudioPolicyManager::getOutputForAttrInt( 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) { Loading @@ -1256,6 +1263,13 @@ status_t AudioPolicyManager::getOutputForAttrInt( *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 Loading Loading @@ -6689,7 +6703,7 @@ void AudioPolicyManager::closeOutput(audio_io_handle_t output) 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++) { Loading services/audiopolicy/tests/audiopolicymanager_tests.cpp +150 −56 Original line number Diff line number Diff line Loading @@ -211,7 +211,7 @@ class AudioPolicyManagerTest : public testing::Test { 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() { Loading Loading @@ -1274,13 +1274,30 @@ protected: 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(); } Loading @@ -1302,11 +1319,45 @@ status_t AudioPolicyManagerTestDynamicPolicy::addPolicyMix(int mixType, int mixF 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 } Loading Loading @@ -1684,11 +1735,6 @@ class AudioPolicyManagerTestDPPlaybackReRouting : public AudioPolicyManagerTestD 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() { Loading @@ -1702,34 +1748,10 @@ void AudioPolicyManagerTestDPPlaybackReRouting::SetUp() { 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) { Loading Loading @@ -1924,12 +1946,14 @@ TEST_P(AudioPolicyManagerTestMMapPlaybackRerouting, MmapPlaybackStreamMatchingLo // 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, Loading @@ -1942,11 +1966,12 @@ TEST_P(AudioPolicyManagerTestMMapPlaybackRerouting, // 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, Loading @@ -1957,23 +1982,57 @@ TEST_P(AudioPolicyManagerTestMMapPlaybackRerouting, 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, ASSERT_EQ(NO_ERROR, addPolicyMix(MIX_TYPE_PLAYERS, MIX_ROUTE_FLAG_RENDER, AUDIO_DEVICE_OUT_USB_DEVICE, /*mixAddress=*/"", audioConfig, {createUidCriterion(testUid)}); ASSERT_EQ(NO_ERROR, ret); 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, Loading @@ -1981,14 +2040,15 @@ TEST_F(AudioPolicyManagerTestMMapPlaybackRerouting, // 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, ASSERT_EQ(NO_ERROR, addPolicyMix(MIX_TYPE_PLAYERS, MIX_ROUTE_FLAG_RENDER, AUDIO_DEVICE_OUT_SPEAKER, /*mixAddress=*/"", audioConfig, {createUidCriterion(testUid)}); ASSERT_EQ(NO_ERROR, ret); {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, Loading Loading @@ -2322,6 +2382,7 @@ protected: 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 = Loading @@ -2335,6 +2396,8 @@ const std::string AudioPolicyManagerCarTest::sCarRearZoneOneOutput = "bus100_aud 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. } Loading Loading @@ -2784,6 +2847,37 @@ TEST_F(AudioPolicyManagerCarTest, GetOutputForAttrWithNoMatchingMix) { 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; } Loading services/audiopolicy/tests/resources/test_audio_policy_configuration.xml +1 −1 Original line number Diff line number Diff line Loading @@ -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> Loading Loading
services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h +1 −1 Original line number Diff line number Diff line Loading @@ -61,7 +61,7 @@ public: 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 Loading
services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp +24 −10 Original line number Diff line number Diff line Loading @@ -272,12 +272,33 @@ status_t AudioPolicyMixCollection::getAudioPolicyMix(audio_devices_t deviceType, 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) { 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; } } } } Loading Loading @@ -335,13 +356,6 @@ status_t AudioPolicyMixCollection::getOutputForAttr( "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)) { Loading
services/audiopolicy/managerdefault/AudioPolicyManager.cpp +20 −6 Original line number Diff line number Diff line Loading @@ -1217,13 +1217,14 @@ status_t AudioPolicyManager::getOutputForAttrInt( 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 Loading @@ -1231,23 +1232,29 @@ status_t AudioPolicyManager::getOutputForAttrInt( 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) { Loading @@ -1256,6 +1263,13 @@ status_t AudioPolicyManager::getOutputForAttrInt( *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 Loading Loading @@ -6689,7 +6703,7 @@ void AudioPolicyManager::closeOutput(audio_io_handle_t output) 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++) { Loading
services/audiopolicy/tests/audiopolicymanager_tests.cpp +150 −56 Original line number Diff line number Diff line Loading @@ -211,7 +211,7 @@ class AudioPolicyManagerTest : public testing::Test { 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() { Loading Loading @@ -1274,13 +1274,30 @@ protected: 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(); } Loading @@ -1302,11 +1319,45 @@ status_t AudioPolicyManagerTestDynamicPolicy::addPolicyMix(int mixType, int mixF 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 } Loading Loading @@ -1684,11 +1735,6 @@ class AudioPolicyManagerTestDPPlaybackReRouting : public AudioPolicyManagerTestD 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() { Loading @@ -1702,34 +1748,10 @@ void AudioPolicyManagerTestDPPlaybackReRouting::SetUp() { 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) { Loading Loading @@ -1924,12 +1946,14 @@ TEST_P(AudioPolicyManagerTestMMapPlaybackRerouting, MmapPlaybackStreamMatchingLo // 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, Loading @@ -1942,11 +1966,12 @@ TEST_P(AudioPolicyManagerTestMMapPlaybackRerouting, // 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, Loading @@ -1957,23 +1982,57 @@ TEST_P(AudioPolicyManagerTestMMapPlaybackRerouting, 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, ASSERT_EQ(NO_ERROR, addPolicyMix(MIX_TYPE_PLAYERS, MIX_ROUTE_FLAG_RENDER, AUDIO_DEVICE_OUT_USB_DEVICE, /*mixAddress=*/"", audioConfig, {createUidCriterion(testUid)}); ASSERT_EQ(NO_ERROR, ret); 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, Loading @@ -1981,14 +2040,15 @@ TEST_F(AudioPolicyManagerTestMMapPlaybackRerouting, // 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, ASSERT_EQ(NO_ERROR, addPolicyMix(MIX_TYPE_PLAYERS, MIX_ROUTE_FLAG_RENDER, AUDIO_DEVICE_OUT_SPEAKER, /*mixAddress=*/"", audioConfig, {createUidCriterion(testUid)}); ASSERT_EQ(NO_ERROR, ret); {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, Loading Loading @@ -2322,6 +2382,7 @@ protected: 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 = Loading @@ -2335,6 +2396,8 @@ const std::string AudioPolicyManagerCarTest::sCarRearZoneOneOutput = "bus100_aud 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. } Loading Loading @@ -2784,6 +2847,37 @@ TEST_F(AudioPolicyManagerCarTest, GetOutputForAttrWithNoMatchingMix) { 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; } Loading
services/audiopolicy/tests/resources/test_audio_policy_configuration.xml +1 −1 Original line number Diff line number Diff line Loading @@ -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> Loading