Loading services/audiopolicy/managerdefault/AudioPolicyManager.cpp +94 −33 Original line number Diff line number Diff line Loading @@ -935,6 +935,32 @@ void AudioPolicyManager::setSystemProperty(const char* property, const char* val ALOGV("setSystemProperty() property %s, value %s", property, value); } // Find an MSD output profile compatible with the parameters passed. // When "directOnly" is set, restrict search to profiles for direct outputs. sp<IOProfile> AudioPolicyManager::getMsdProfileForOutput( const DeviceVector& devices, uint32_t samplingRate, audio_format_t format, audio_channel_mask_t channelMask, audio_output_flags_t flags, bool directOnly) { flags = getRelevantFlags(flags, directOnly); sp<HwModule> msdModule = mHwModules.getModuleFromName(AUDIO_HARDWARE_MODULE_ID_MSD); if (msdModule != nullptr) { // for the msd module check if there are patches to the output devices if (msdHasPatchesToAllDevices(devices.toTypeAddrVector())) { HwModuleCollection modules; modules.add(msdModule); return searchCompatibleProfileHwModules( modules, getMsdAudioOutDevices(), samplingRate, format, channelMask, flags, directOnly); } } return nullptr; } // Find an output profile compatible with the parameters passed. When "directOnly" is set, restrict // search to profiles for direct outputs. sp<IOProfile> AudioPolicyManager::getProfileForOutput( Loading @@ -945,19 +971,35 @@ sp<IOProfile> AudioPolicyManager::getProfileForOutput( audio_output_flags_t flags, bool directOnly) { flags = getRelevantFlags(flags, directOnly); return searchCompatibleProfileHwModules( mHwModules, devices, samplingRate, format, channelMask, flags, directOnly); } audio_output_flags_t AudioPolicyManager::getRelevantFlags ( audio_output_flags_t flags, bool directOnly) { if (directOnly) { // only retain flags that will drive the direct output profile selection // if explicitly requested static const uint32_t kRelevantFlags = (AUDIO_OUTPUT_FLAG_HW_AV_SYNC | AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD | AUDIO_OUTPUT_FLAG_VOIP_RX | AUDIO_OUTPUT_FLAG_MMAP_NOIRQ); flags = (audio_output_flags_t)((flags & kRelevantFlags) | AUDIO_OUTPUT_FLAG_DIRECT); flags = (audio_output_flags_t)((flags & kRelevantFlags) | AUDIO_OUTPUT_FLAG_DIRECT); } return flags; } sp<IOProfile> AudioPolicyManager::searchCompatibleProfileHwModules ( const HwModuleCollection& hwModules, const DeviceVector& devices, uint32_t samplingRate, audio_format_t format, audio_channel_mask_t channelMask, audio_output_flags_t flags, bool directOnly) { sp<IOProfile> profile; for (const auto& hwModule : mHwModules) { for (const auto& hwModule : hwModules) { for (const auto& curProfile : hwModule->getOutputProfiles()) { if (!curProfile->isCompatibleProfile(devices, samplingRate, NULL /*updatedSamplingRate*/, Loading @@ -974,10 +1016,14 @@ sp<IOProfile> AudioPolicyManager::getProfileForOutput( if (!curProfile->devicesSupportEncodedFormats(devices.types())) { continue; } if (!directOnly) return curProfile; if (!directOnly) { return curProfile; } // when searching for direct outputs, if several profiles are compatible, give priority // to one with offload capability if (profile != 0 && ((curProfile->getFlags() & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) == 0)) { if (profile != 0 && ((curProfile->getFlags() & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) == 0)) { continue; } profile = curProfile; Loading Loading @@ -3820,7 +3866,22 @@ bool AudioPolicyManager::isDirectOutputSupported(const audio_config_base_t& conf __FUNCTION__, profile != 0 ? "" : "NOT ", (profile != 0 ? profile->getTagName().c_str() : "null"), config.sample_rate, config.format, config.channel_mask, output_flags); return (profile != 0); // also try the MSD module if compatible profile not found if (profile == nullptr) { profile = getMsdProfileForOutput(outputDevices, config.sample_rate, config.format, config.channel_mask, output_flags, true /* directOnly */); ALOGV("%s() MSD profile %sfound with name: %s, " "sample rate: %u, format: 0x%x, channel_mask: 0x%x, output flags: 0x%x", __FUNCTION__, profile != 0 ? "" : "NOT ", (profile != 0 ? profile->getTagName().c_str() : "null"), config.sample_rate, config.format, config.channel_mask, output_flags); } return (profile != nullptr); } bool AudioPolicyManager::isOffloadPossible(const audio_offload_info_t &offloadInfo, Loading services/audiopolicy/managerdefault/AudioPolicyManager.h +24 −0 Original line number Diff line number Diff line Loading @@ -768,6 +768,15 @@ protected: audio_channel_mask_t channelMask, audio_output_flags_t flags, bool directOnly); /** * Same as getProfileForOutput, but it looks for an MSD profile */ sp<IOProfile> getMsdProfileForOutput(const DeviceVector &devices, uint32_t samplingRate, audio_format_t format, audio_channel_mask_t channelMask, audio_output_flags_t flags, bool directOnly); audio_io_handle_t selectOutputForMusicEffects(); Loading Loading @@ -1201,6 +1210,21 @@ private: // without duplicating them if already present void addPortProfilesToVector(sp<IOProfile> outputProfile, AudioProfileVector& audioProfilesVector); // Searches for a compatible profile with the sample rate, audio format and channel mask // in the list of passed HwModule(s). // returns a compatible profile if found, nullptr otherwise sp<IOProfile> searchCompatibleProfileHwModules ( const HwModuleCollection& hwModules, const DeviceVector& devices, uint32_t samplingRate, audio_format_t format, audio_channel_mask_t channelMask, audio_output_flags_t flags, bool directOnly); // Filters only the relevant flags for getProfileForOutput audio_output_flags_t getRelevantFlags (audio_output_flags_t flags, bool directOnly); }; }; services/audiopolicy/tests/audiopolicymanager_tests.cpp +67 −0 Original line number Diff line number Diff line Loading @@ -699,6 +699,73 @@ TEST_P(AudioPolicyManagerTestMsd, GetDirectProfilesForAttributesWithMsd) { ASSERT_EQ(countDirectProfilesPrimary, getDirectProfilesForAttributes(attr).size()); } TEST_P(AudioPolicyManagerTestMsd, IsDirectPlaybackSupportedWithMsd) { const audio_attributes_t attr = { AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_UNKNOWN, AUDIO_SOURCE_DEFAULT, AUDIO_FLAG_NONE, ""}; audio_config_base_t directConfig = AUDIO_CONFIG_BASE_INITIALIZER; directConfig.format = AUDIO_FORMAT_DTS; directConfig.sample_rate = 48000; directConfig.channel_mask = AUDIO_CHANNEL_OUT_5POINT1; audio_config_base_t nonDirectConfig = AUDIO_CONFIG_BASE_INITIALIZER; nonDirectConfig.format = AUDIO_FORMAT_PCM_16_BIT; nonDirectConfig.sample_rate = 48000; nonDirectConfig.channel_mask = AUDIO_CHANNEL_OUT_STEREO; audio_config_base_t nonExistentConfig = AUDIO_CONFIG_BASE_INITIALIZER; nonExistentConfig.format = AUDIO_FORMAT_E_AC3; nonExistentConfig.sample_rate = 48000; nonExistentConfig.channel_mask = AUDIO_CHANNEL_OUT_STEREO; audio_config_base_t msdDirectConfig1 = AUDIO_CONFIG_BASE_INITIALIZER; msdDirectConfig1.format = AUDIO_FORMAT_AC3; msdDirectConfig1.sample_rate = 48000; msdDirectConfig1.channel_mask = AUDIO_CHANNEL_OUT_5POINT1; audio_config_base_t msdDirectConfig2 = AUDIO_CONFIG_BASE_INITIALIZER; msdDirectConfig2.format = AUDIO_FORMAT_IEC60958; msdDirectConfig2.sample_rate = 48000; msdDirectConfig2.channel_mask = AUDIO_CHANNEL_OUT_STEREO; audio_config_base_t msdNonDirectConfig = AUDIO_CONFIG_BASE_INITIALIZER; msdNonDirectConfig.format = AUDIO_FORMAT_PCM_16_BIT; msdNonDirectConfig.sample_rate = 96000; msdNonDirectConfig.channel_mask = AUDIO_CHANNEL_OUT_STEREO; ASSERT_TRUE(mManager->isDirectOutputSupported(directConfig, attr)); ASSERT_FALSE(mManager->isDirectOutputSupported(nonDirectConfig, attr)); ASSERT_FALSE(mManager->isDirectOutputSupported(nonExistentConfig, attr)); // before setting MSD patches the direct MSD configs return false ASSERT_FALSE(mManager->isDirectOutputSupported(msdDirectConfig1, attr)); ASSERT_FALSE(mManager->isDirectOutputSupported(msdDirectConfig2, attr)); ASSERT_FALSE(mManager->isDirectOutputSupported(msdNonDirectConfig, attr)); DeviceVector outputDevices = mManager->getAvailableOutputDevices(); // Remove MSD output device to avoid patching to itself outputDevices.remove(mMsdOutputDevice); mManager->setMsdOutputPatches(&outputDevices); ASSERT_TRUE(mManager->isDirectOutputSupported(directConfig, attr)); ASSERT_FALSE(mManager->isDirectOutputSupported(nonDirectConfig, attr)); ASSERT_FALSE(mManager->isDirectOutputSupported(nonExistentConfig, attr)); // after setting MSD patches the direct MSD configs return true ASSERT_TRUE(mManager->isDirectOutputSupported(msdDirectConfig1, attr)); ASSERT_TRUE(mManager->isDirectOutputSupported(msdDirectConfig2, attr)); ASSERT_FALSE(mManager->isDirectOutputSupported(msdNonDirectConfig, attr)); mManager->releaseMsdOutputPatches(outputDevices); ASSERT_TRUE(mManager->isDirectOutputSupported(directConfig, attr)); ASSERT_FALSE(mManager->isDirectOutputSupported(nonDirectConfig, attr)); ASSERT_FALSE(mManager->isDirectOutputSupported(nonExistentConfig, attr)); // AFTER releasing MSD patches the direct MSD configs return false ASSERT_FALSE(mManager->isDirectOutputSupported(msdDirectConfig1, attr)); ASSERT_FALSE(mManager->isDirectOutputSupported(msdDirectConfig2, attr)); ASSERT_FALSE(mManager->isDirectOutputSupported(msdNonDirectConfig, attr)); } class AudioPolicyManagerTestWithConfigurationFile : public AudioPolicyManagerTest { protected: void SetUpManagerConfig() override; Loading Loading
services/audiopolicy/managerdefault/AudioPolicyManager.cpp +94 −33 Original line number Diff line number Diff line Loading @@ -935,6 +935,32 @@ void AudioPolicyManager::setSystemProperty(const char* property, const char* val ALOGV("setSystemProperty() property %s, value %s", property, value); } // Find an MSD output profile compatible with the parameters passed. // When "directOnly" is set, restrict search to profiles for direct outputs. sp<IOProfile> AudioPolicyManager::getMsdProfileForOutput( const DeviceVector& devices, uint32_t samplingRate, audio_format_t format, audio_channel_mask_t channelMask, audio_output_flags_t flags, bool directOnly) { flags = getRelevantFlags(flags, directOnly); sp<HwModule> msdModule = mHwModules.getModuleFromName(AUDIO_HARDWARE_MODULE_ID_MSD); if (msdModule != nullptr) { // for the msd module check if there are patches to the output devices if (msdHasPatchesToAllDevices(devices.toTypeAddrVector())) { HwModuleCollection modules; modules.add(msdModule); return searchCompatibleProfileHwModules( modules, getMsdAudioOutDevices(), samplingRate, format, channelMask, flags, directOnly); } } return nullptr; } // Find an output profile compatible with the parameters passed. When "directOnly" is set, restrict // search to profiles for direct outputs. sp<IOProfile> AudioPolicyManager::getProfileForOutput( Loading @@ -945,19 +971,35 @@ sp<IOProfile> AudioPolicyManager::getProfileForOutput( audio_output_flags_t flags, bool directOnly) { flags = getRelevantFlags(flags, directOnly); return searchCompatibleProfileHwModules( mHwModules, devices, samplingRate, format, channelMask, flags, directOnly); } audio_output_flags_t AudioPolicyManager::getRelevantFlags ( audio_output_flags_t flags, bool directOnly) { if (directOnly) { // only retain flags that will drive the direct output profile selection // if explicitly requested static const uint32_t kRelevantFlags = (AUDIO_OUTPUT_FLAG_HW_AV_SYNC | AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD | AUDIO_OUTPUT_FLAG_VOIP_RX | AUDIO_OUTPUT_FLAG_MMAP_NOIRQ); flags = (audio_output_flags_t)((flags & kRelevantFlags) | AUDIO_OUTPUT_FLAG_DIRECT); flags = (audio_output_flags_t)((flags & kRelevantFlags) | AUDIO_OUTPUT_FLAG_DIRECT); } return flags; } sp<IOProfile> AudioPolicyManager::searchCompatibleProfileHwModules ( const HwModuleCollection& hwModules, const DeviceVector& devices, uint32_t samplingRate, audio_format_t format, audio_channel_mask_t channelMask, audio_output_flags_t flags, bool directOnly) { sp<IOProfile> profile; for (const auto& hwModule : mHwModules) { for (const auto& hwModule : hwModules) { for (const auto& curProfile : hwModule->getOutputProfiles()) { if (!curProfile->isCompatibleProfile(devices, samplingRate, NULL /*updatedSamplingRate*/, Loading @@ -974,10 +1016,14 @@ sp<IOProfile> AudioPolicyManager::getProfileForOutput( if (!curProfile->devicesSupportEncodedFormats(devices.types())) { continue; } if (!directOnly) return curProfile; if (!directOnly) { return curProfile; } // when searching for direct outputs, if several profiles are compatible, give priority // to one with offload capability if (profile != 0 && ((curProfile->getFlags() & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) == 0)) { if (profile != 0 && ((curProfile->getFlags() & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) == 0)) { continue; } profile = curProfile; Loading Loading @@ -3820,7 +3866,22 @@ bool AudioPolicyManager::isDirectOutputSupported(const audio_config_base_t& conf __FUNCTION__, profile != 0 ? "" : "NOT ", (profile != 0 ? profile->getTagName().c_str() : "null"), config.sample_rate, config.format, config.channel_mask, output_flags); return (profile != 0); // also try the MSD module if compatible profile not found if (profile == nullptr) { profile = getMsdProfileForOutput(outputDevices, config.sample_rate, config.format, config.channel_mask, output_flags, true /* directOnly */); ALOGV("%s() MSD profile %sfound with name: %s, " "sample rate: %u, format: 0x%x, channel_mask: 0x%x, output flags: 0x%x", __FUNCTION__, profile != 0 ? "" : "NOT ", (profile != 0 ? profile->getTagName().c_str() : "null"), config.sample_rate, config.format, config.channel_mask, output_flags); } return (profile != nullptr); } bool AudioPolicyManager::isOffloadPossible(const audio_offload_info_t &offloadInfo, Loading
services/audiopolicy/managerdefault/AudioPolicyManager.h +24 −0 Original line number Diff line number Diff line Loading @@ -768,6 +768,15 @@ protected: audio_channel_mask_t channelMask, audio_output_flags_t flags, bool directOnly); /** * Same as getProfileForOutput, but it looks for an MSD profile */ sp<IOProfile> getMsdProfileForOutput(const DeviceVector &devices, uint32_t samplingRate, audio_format_t format, audio_channel_mask_t channelMask, audio_output_flags_t flags, bool directOnly); audio_io_handle_t selectOutputForMusicEffects(); Loading Loading @@ -1201,6 +1210,21 @@ private: // without duplicating them if already present void addPortProfilesToVector(sp<IOProfile> outputProfile, AudioProfileVector& audioProfilesVector); // Searches for a compatible profile with the sample rate, audio format and channel mask // in the list of passed HwModule(s). // returns a compatible profile if found, nullptr otherwise sp<IOProfile> searchCompatibleProfileHwModules ( const HwModuleCollection& hwModules, const DeviceVector& devices, uint32_t samplingRate, audio_format_t format, audio_channel_mask_t channelMask, audio_output_flags_t flags, bool directOnly); // Filters only the relevant flags for getProfileForOutput audio_output_flags_t getRelevantFlags (audio_output_flags_t flags, bool directOnly); }; };
services/audiopolicy/tests/audiopolicymanager_tests.cpp +67 −0 Original line number Diff line number Diff line Loading @@ -699,6 +699,73 @@ TEST_P(AudioPolicyManagerTestMsd, GetDirectProfilesForAttributesWithMsd) { ASSERT_EQ(countDirectProfilesPrimary, getDirectProfilesForAttributes(attr).size()); } TEST_P(AudioPolicyManagerTestMsd, IsDirectPlaybackSupportedWithMsd) { const audio_attributes_t attr = { AUDIO_CONTENT_TYPE_UNKNOWN, AUDIO_USAGE_UNKNOWN, AUDIO_SOURCE_DEFAULT, AUDIO_FLAG_NONE, ""}; audio_config_base_t directConfig = AUDIO_CONFIG_BASE_INITIALIZER; directConfig.format = AUDIO_FORMAT_DTS; directConfig.sample_rate = 48000; directConfig.channel_mask = AUDIO_CHANNEL_OUT_5POINT1; audio_config_base_t nonDirectConfig = AUDIO_CONFIG_BASE_INITIALIZER; nonDirectConfig.format = AUDIO_FORMAT_PCM_16_BIT; nonDirectConfig.sample_rate = 48000; nonDirectConfig.channel_mask = AUDIO_CHANNEL_OUT_STEREO; audio_config_base_t nonExistentConfig = AUDIO_CONFIG_BASE_INITIALIZER; nonExistentConfig.format = AUDIO_FORMAT_E_AC3; nonExistentConfig.sample_rate = 48000; nonExistentConfig.channel_mask = AUDIO_CHANNEL_OUT_STEREO; audio_config_base_t msdDirectConfig1 = AUDIO_CONFIG_BASE_INITIALIZER; msdDirectConfig1.format = AUDIO_FORMAT_AC3; msdDirectConfig1.sample_rate = 48000; msdDirectConfig1.channel_mask = AUDIO_CHANNEL_OUT_5POINT1; audio_config_base_t msdDirectConfig2 = AUDIO_CONFIG_BASE_INITIALIZER; msdDirectConfig2.format = AUDIO_FORMAT_IEC60958; msdDirectConfig2.sample_rate = 48000; msdDirectConfig2.channel_mask = AUDIO_CHANNEL_OUT_STEREO; audio_config_base_t msdNonDirectConfig = AUDIO_CONFIG_BASE_INITIALIZER; msdNonDirectConfig.format = AUDIO_FORMAT_PCM_16_BIT; msdNonDirectConfig.sample_rate = 96000; msdNonDirectConfig.channel_mask = AUDIO_CHANNEL_OUT_STEREO; ASSERT_TRUE(mManager->isDirectOutputSupported(directConfig, attr)); ASSERT_FALSE(mManager->isDirectOutputSupported(nonDirectConfig, attr)); ASSERT_FALSE(mManager->isDirectOutputSupported(nonExistentConfig, attr)); // before setting MSD patches the direct MSD configs return false ASSERT_FALSE(mManager->isDirectOutputSupported(msdDirectConfig1, attr)); ASSERT_FALSE(mManager->isDirectOutputSupported(msdDirectConfig2, attr)); ASSERT_FALSE(mManager->isDirectOutputSupported(msdNonDirectConfig, attr)); DeviceVector outputDevices = mManager->getAvailableOutputDevices(); // Remove MSD output device to avoid patching to itself outputDevices.remove(mMsdOutputDevice); mManager->setMsdOutputPatches(&outputDevices); ASSERT_TRUE(mManager->isDirectOutputSupported(directConfig, attr)); ASSERT_FALSE(mManager->isDirectOutputSupported(nonDirectConfig, attr)); ASSERT_FALSE(mManager->isDirectOutputSupported(nonExistentConfig, attr)); // after setting MSD patches the direct MSD configs return true ASSERT_TRUE(mManager->isDirectOutputSupported(msdDirectConfig1, attr)); ASSERT_TRUE(mManager->isDirectOutputSupported(msdDirectConfig2, attr)); ASSERT_FALSE(mManager->isDirectOutputSupported(msdNonDirectConfig, attr)); mManager->releaseMsdOutputPatches(outputDevices); ASSERT_TRUE(mManager->isDirectOutputSupported(directConfig, attr)); ASSERT_FALSE(mManager->isDirectOutputSupported(nonDirectConfig, attr)); ASSERT_FALSE(mManager->isDirectOutputSupported(nonExistentConfig, attr)); // AFTER releasing MSD patches the direct MSD configs return false ASSERT_FALSE(mManager->isDirectOutputSupported(msdDirectConfig1, attr)); ASSERT_FALSE(mManager->isDirectOutputSupported(msdDirectConfig2, attr)); ASSERT_FALSE(mManager->isDirectOutputSupported(msdNonDirectConfig, attr)); } class AudioPolicyManagerTestWithConfigurationFile : public AudioPolicyManagerTest { protected: void SetUpManagerConfig() override; Loading