diff --git a/media/libaudioclient/AudioTrack.cpp b/media/libaudioclient/AudioTrack.cpp index 02324ac6ca..8f06ee7748 100644 --- a/media/libaudioclient/AudioTrack.cpp +++ b/media/libaudioclient/AudioTrack.cpp @@ -30,9 +30,11 @@ #include #include #include +#include #include #include #include +#include #include #include @@ -157,6 +159,15 @@ status_t AudioTrack::getMinFrameCount( return NO_ERROR; } +// static +bool AudioTrack::isDirectOutputSupported(const audio_config_base_t& config, + const audio_attributes_t& attributes) { + ALOGV("%s()", __FUNCTION__); + const sp& aps = AudioSystem::get_audio_policy_service(); + if (aps == 0) return false; + return aps->isDirectOutputSupported(config, attributes); +} + // --------------------------------------------------------------------------- static std::string audioContentTypeString(audio_content_type_t value) { @@ -465,16 +476,7 @@ status_t AudioTrack::set( __func__, mAttributes.usage, mAttributes.content_type, mAttributes.flags, mAttributes.tags); mStreamType = AUDIO_STREAM_DEFAULT; - if ((mAttributes.flags & AUDIO_FLAG_HW_AV_SYNC) != 0) { - flags = (audio_output_flags_t)(flags | AUDIO_OUTPUT_FLAG_HW_AV_SYNC); - } - if ((mAttributes.flags & AUDIO_FLAG_LOW_LATENCY) != 0) { - flags = (audio_output_flags_t) (flags | AUDIO_OUTPUT_FLAG_FAST); - } - // check deep buffer after flags have been modified above - if (flags == AUDIO_OUTPUT_FLAG_NONE && (mAttributes.flags & AUDIO_FLAG_DEEP_BUFFER) != 0) { - flags = AUDIO_OUTPUT_FLAG_DEEP_BUFFER; - } + audio_attributes_flags_to_audio_output_flags(mAttributes.flags, flags); } // these below should probably come from the audioFlinger too... diff --git a/media/libaudioclient/IAudioPolicyService.cpp b/media/libaudioclient/IAudioPolicyService.cpp index 7f2e5e5805..86e417a1a5 100644 --- a/media/libaudioclient/IAudioPolicyService.cpp +++ b/media/libaudioclient/IAudioPolicyService.cpp @@ -62,6 +62,7 @@ enum { SET_EFFECT_ENABLED, IS_STREAM_ACTIVE_REMOTELY, IS_OFFLOAD_SUPPORTED, + IS_DIRECT_OUTPUT_SUPPORTED, LIST_AUDIO_PORTS, GET_AUDIO_PORT, CREATE_AUDIO_PATCH, @@ -523,6 +524,16 @@ public: return reply.readInt32(); } + virtual bool isDirectOutputSupported(const audio_config_base_t& config, + const audio_attributes_t& attributes) { + Parcel data, reply; + data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor()); + data.write(&config, sizeof(audio_config_base_t)); + data.write(&attributes, sizeof(audio_attributes_t)); + status_t status = remote()->transact(IS_DIRECT_OUTPUT_SUPPORTED, data, &reply); + return status == NO_ERROR ? static_cast(reply.readInt32()) : false; + } + virtual status_t listAudioPorts(audio_port_role_t role, audio_port_type_t type, unsigned int *num_ports, @@ -1388,6 +1399,18 @@ status_t BnAudioPolicyService::onTransact( return NO_ERROR; } + case IS_DIRECT_OUTPUT_SUPPORTED: { + CHECK_INTERFACE(IAudioPolicyService, data, reply); + audio_config_base_t config = {}; + audio_attributes_t attributes = {}; + status_t status = data.read(&config, sizeof(audio_config_base_t)); + if (status != NO_ERROR) return status; + status = data.read(&attributes, sizeof(audio_attributes_t)); + if (status != NO_ERROR) return status; + reply->writeInt32(isDirectOutputSupported(config, attributes)); + return NO_ERROR; + } + case LIST_AUDIO_PORTS: { CHECK_INTERFACE(IAudioPolicyService, data, reply); audio_port_role_t role = (audio_port_role_t)data.readInt32(); diff --git a/media/libaudioclient/include/media/AudioPolicyHelper.h b/media/libaudioclient/include/media/AudioPolicyHelper.h index 49432b7e40..46de6b397d 100644 --- a/media/libaudioclient/include/media/AudioPolicyHelper.h +++ b/media/libaudioclient/include/media/AudioPolicyHelper.h @@ -123,4 +123,21 @@ void stream_type_to_audio_attributes(audio_stream_type_t streamType, } } +// Convert flags sent from Java AudioAttributes.getFlags() method to audio_output_flags_t +static inline +void audio_attributes_flags_to_audio_output_flags(const audio_flags_mask_t audioAttributeFlags, + audio_output_flags_t &flags) { + if ((audioAttributeFlags & AUDIO_FLAG_HW_AV_SYNC) != 0) { + flags = static_cast(flags | + AUDIO_OUTPUT_FLAG_HW_AV_SYNC | AUDIO_OUTPUT_FLAG_DIRECT); + } + if ((audioAttributeFlags & AUDIO_FLAG_LOW_LATENCY) != 0) { + flags = static_cast(flags | AUDIO_OUTPUT_FLAG_FAST); + } + // check deep buffer after flags have been modified above + if (flags == AUDIO_OUTPUT_FLAG_NONE && (audioAttributeFlags & AUDIO_FLAG_DEEP_BUFFER) != 0) { + flags = AUDIO_OUTPUT_FLAG_DEEP_BUFFER; + } +} + #endif //AUDIO_POLICY_HELPER_H_ diff --git a/media/libaudioclient/include/media/AudioTrack.h b/media/libaudioclient/include/media/AudioTrack.h index 8238ea2671..7fdf7cc7bb 100644 --- a/media/libaudioclient/include/media/AudioTrack.h +++ b/media/libaudioclient/include/media/AudioTrack.h @@ -147,6 +147,12 @@ public: audio_stream_type_t streamType, uint32_t sampleRate); + /* Check if direct playback is possible for the given audio configuration and attributes. + * Return true if output is possible for the given parameters. Otherwise returns false. + */ + static bool isDirectOutputSupported(const audio_config_base_t& config, + const audio_attributes_t& attributes); + /* How data is transferred to AudioTrack */ enum transfer_type { diff --git a/media/libaudioclient/include/media/IAudioPolicyService.h b/media/libaudioclient/include/media/IAudioPolicyService.h index e5fcfb5c2f..e3386a4688 100644 --- a/media/libaudioclient/include/media/IAudioPolicyService.h +++ b/media/libaudioclient/include/media/IAudioPolicyService.h @@ -125,6 +125,10 @@ public: // bit rate, duration, video and streaming or offload property is enabled virtual bool isOffloadSupported(const audio_offload_info_t& info) = 0; + // Check if direct playback is possible for given format, sample rate, channel mask and flags. + virtual bool isDirectOutputSupported(const audio_config_base_t& config, + const audio_attributes_t& attributes) = 0; + /* List available audio ports and their attributes */ virtual status_t listAudioPorts(audio_port_role_t role, audio_port_type_t type, diff --git a/services/audiopolicy/AudioPolicyInterface.h b/services/audiopolicy/AudioPolicyInterface.h index 3fb505d7b2..c1db78be96 100644 --- a/services/audiopolicy/AudioPolicyInterface.h +++ b/services/audiopolicy/AudioPolicyInterface.h @@ -181,6 +181,8 @@ public: virtual status_t dump(int fd) = 0; virtual bool isOffloadSupported(const audio_offload_info_t& offloadInfo) = 0; + virtual bool isDirectOutputSupported(const audio_config_base_t& config, + const audio_attributes_t& attributes) = 0; virtual status_t listAudioPorts(audio_port_role_t role, audio_port_type_t type, diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp index da7df11104..fb0e436273 100644 --- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp +++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp @@ -712,22 +712,25 @@ void AudioPolicyManager::setSystemProperty(const char* property, const char* val ALOGV("setSystemProperty() property %s, value %s", property, value); } -// Find a direct output profile compatible with the parameters passed, even if the input flags do -// not explicitly request a direct output -sp AudioPolicyManager::getProfileForDirectOutput( - audio_devices_t device, - uint32_t samplingRate, - audio_format_t format, - audio_channel_mask_t channelMask, - audio_output_flags_t flags) +// Find an output profile compatible with the parameters passed. When "directOnly" is set, restrict +// search to profiles for direct outputs. +sp AudioPolicyManager::getProfileForOutput( + audio_devices_t device, + uint32_t samplingRate, + audio_format_t format, + audio_channel_mask_t channelMask, + audio_output_flags_t flags, + bool 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); - flags = - (audio_output_flags_t)((flags & kRelevantFlags) | AUDIO_OUTPUT_FLAG_DIRECT); + 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); + flags = + (audio_output_flags_t)((flags & kRelevantFlags) | AUDIO_OUTPUT_FLAG_DIRECT); + } sp profile; @@ -744,7 +747,9 @@ sp AudioPolicyManager::getProfileForDirectOutput( if ((mAvailableOutputDevices.types() & curProfile->getSupportedDevicesType()) == 0) { continue; } - // if several profiles are compatible, give priority to one with offload capability + 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)) { continue; } @@ -980,11 +985,12 @@ audio_io_handle_t AudioPolicyManager::getOutputForDevice( if (((*flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) == 0) || !(mEffects.isNonOffloadableEffectEnabled() || mMasterMono)) { - profile = getProfileForDirectOutput(device, - config->sample_rate, - config->format, - config->channel_mask, - (audio_output_flags_t)*flags); + profile = getProfileForOutput(device, + config->sample_rate, + config->format, + config->channel_mask, + (audio_output_flags_t)*flags, + true /* directOnly */); } if (profile != 0) { @@ -2691,15 +2697,34 @@ bool AudioPolicyManager::isOffloadSupported(const audio_offload_info_t& offloadI // See if there is a profile to support this. // AUDIO_DEVICE_NONE - sp profile = getProfileForDirectOutput(AUDIO_DEVICE_NONE /*ignore device */, + sp profile = getProfileForOutput(AUDIO_DEVICE_NONE /*ignore device */, offloadInfo.sample_rate, offloadInfo.format, offloadInfo.channel_mask, - AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD); + AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD, + true /* directOnly */); ALOGV("isOffloadSupported() profile %sfound", profile != 0 ? "" : "NOT "); return (profile != 0); } +bool AudioPolicyManager::isDirectOutputSupported(const audio_config_base_t& config, + const audio_attributes_t& attributes) { + audio_output_flags_t output_flags = AUDIO_OUTPUT_FLAG_NONE; + audio_attributes_flags_to_audio_output_flags(attributes.flags, output_flags); + sp profile = getProfileForOutput(AUDIO_DEVICE_NONE /*ignore device */, + config.sample_rate, + config.format, + config.channel_mask, + output_flags, + true /* directOnly */); + ALOGV("%s() 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().string() : "null"), + config.sample_rate, config.format, config.channel_mask, output_flags); + return (profile != 0); +} + status_t AudioPolicyManager::listAudioPorts(audio_port_role_t role, audio_port_type_t type, unsigned int *num_ports, diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.h b/services/audiopolicy/managerdefault/AudioPolicyManager.h index fcc8976766..709cce0683 100644 --- a/services/audiopolicy/managerdefault/AudioPolicyManager.h +++ b/services/audiopolicy/managerdefault/AudioPolicyManager.h @@ -192,6 +192,9 @@ public: virtual bool isOffloadSupported(const audio_offload_info_t& offloadInfo); + virtual bool isDirectOutputSupported(const audio_config_base_t& config, + const audio_attributes_t& attributes); + virtual status_t listAudioPorts(audio_port_role_t role, audio_port_type_t type, unsigned int *num_ports, @@ -479,11 +482,12 @@ protected: audio_format_t& format, audio_channel_mask_t& channelMask, audio_input_flags_t flags); - sp getProfileForDirectOutput(audio_devices_t device, - uint32_t samplingRate, - audio_format_t format, - audio_channel_mask_t channelMask, - audio_output_flags_t flags); + sp getProfileForOutput(audio_devices_t device, + uint32_t samplingRate, + audio_format_t format, + audio_channel_mask_t channelMask, + audio_output_flags_t flags, + bool directOnly); audio_io_handle_t selectOutputForMusicEffects(); diff --git a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp index c2ce754616..ae92ae5d00 100644 --- a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp +++ b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp @@ -909,6 +909,17 @@ bool AudioPolicyService::isOffloadSupported(const audio_offload_info_t& info) return mAudioPolicyManager->isOffloadSupported(info); } +bool AudioPolicyService::isDirectOutputSupported(const audio_config_base_t& config, + const audio_attributes_t& attributes) { + if (mAudioPolicyManager == NULL) { + ALOGV("mAudioPolicyManager == NULL"); + return false; + } + Mutex::Autolock _l(mLock); + return mAudioPolicyManager->isDirectOutputSupported(config, attributes); +} + + status_t AudioPolicyService::listAudioPorts(audio_port_role_t role, audio_port_type_t type, unsigned int *num_ports, diff --git a/services/audiopolicy/service/AudioPolicyService.h b/services/audiopolicy/service/AudioPolicyService.h index dc5a36d34c..f490fb9a06 100644 --- a/services/audiopolicy/service/AudioPolicyService.h +++ b/services/audiopolicy/service/AudioPolicyService.h @@ -167,6 +167,8 @@ public: int delayMs = 0); virtual status_t setVoiceVolume(float volume, int delayMs = 0); virtual bool isOffloadSupported(const audio_offload_info_t &config); + virtual bool isDirectOutputSupported(const audio_config_base_t& config, + const audio_attributes_t& attributes); virtual status_t listAudioPorts(audio_port_role_t role, audio_port_type_t type,