From 861a628adbcbe7c3baa6eab1b765b87b480ff4a2 Mon Sep 17 00:00:00 2001 From: Eric Laurent Date: Mon, 18 May 2015 15:40:16 -0700 Subject: audio policy: fix direct output profile selection Fix logic in AudioPolicyManager::getProfileForDirectOutput() to select the direct output with most matching flags and not just the first compatible one. Also fixes issue 17783395 which was fixed by commit f7bc29b02 in lmp-tv-dev branch only but in a way that caused a regression for HW A/V sync (issue 19384172). Also removed duplicated code lines in getOutputForDevice() Bug: 20819715. Bug: 17783395. Bug: 19384172. Change-Id: I7fc793b37f9b53fabd92cab6b884ef85cfdafee4 --- .../managerdefault/AudioPolicyManager.cpp | 56 +++++++++++++++++----- 1 file changed, 44 insertions(+), 12 deletions(-) (limited to 'services/audiopolicy/managerdefault') diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp index d1ee400..17060e9 100644 --- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp +++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp @@ -579,24 +579,43 @@ sp AudioPolicyManager::getProfileForDirectOutput( audio_channel_mask_t channelMask, audio_output_flags_t flags) { + // 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); + flags = + (audio_output_flags_t)((flags & kRelevantFlags) | AUDIO_OUTPUT_FLAG_DIRECT); + + sp profile; + for (size_t i = 0; i < mHwModules.size(); i++) { if (mHwModules[i]->mHandle == 0) { continue; } for (size_t j = 0; j < mHwModules[i]->mOutputProfiles.size(); j++) { - sp profile = mHwModules[i]->mOutputProfiles[j]; - bool found = profile->isCompatibleProfile(device, String8(""), + sp curProfile = mHwModules[i]->mOutputProfiles[j]; + if (!curProfile->isCompatibleProfile(device, String8(""), samplingRate, NULL /*updatedSamplingRate*/, format, NULL /*updatedFormat*/, channelMask, NULL /*updatedChannelMask*/, - flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD ? - AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD : AUDIO_OUTPUT_FLAG_DIRECT); - if (found && (mAvailableOutputDevices.types() & profile->mSupportedDevices.types())) { - return profile; + flags)) { + continue; + } + // reject profiles not corresponding to a device currently available + if ((mAvailableOutputDevices.types() & curProfile->mSupportedDevices.types()) == 0) { + continue; + } + // if several profiles are compatible, give priority to one with offload capability + if (profile != 0 && ((curProfile->mFlags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) == 0)) { + continue; + } + profile = curProfile; + if ((profile->mFlags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) != 0) { + break; } } } - return 0; + return profile; } audio_io_handle_t AudioPolicyManager::getOutput(audio_stream_type_t stream, @@ -819,10 +838,27 @@ audio_io_handle_t AudioPolicyManager::getOutputForDevice( if (outputDesc != NULL) { closeOutput(outputDesc->mIoHandle); } + + // if the selected profile is offloaded and no offload info was specified, + // create a default one + audio_offload_info_t defaultOffloadInfo = AUDIO_INFO_INITIALIZER; + if ((profile->mFlags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) && !offloadInfo) { + flags = (audio_output_flags_t)(flags | AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD); + defaultOffloadInfo.sample_rate = samplingRate; + defaultOffloadInfo.channel_mask = channelMask; + defaultOffloadInfo.format = format; + defaultOffloadInfo.stream_type = stream; + defaultOffloadInfo.bit_rate = 0; + defaultOffloadInfo.duration_us = -1; + defaultOffloadInfo.has_video = true; // conservative + defaultOffloadInfo.is_streaming = true; // likely + offloadInfo = &defaultOffloadInfo; + } + outputDesc = new SwAudioOutputDescriptor(profile, mpClientInterface); outputDesc->mDevice = device; outputDesc->mLatency = 0; - outputDesc->mFlags =(audio_output_flags_t) (outputDesc->mFlags | flags); + outputDesc->mFlags = (audio_output_flags_t)(outputDesc->mFlags | flags); audio_config_t config = AUDIO_CONFIG_INITIALIZER; config.sample_rate = samplingRate; config.channel_mask = channelMask; @@ -854,10 +890,6 @@ audio_io_handle_t AudioPolicyManager::getOutputForDevice( if (audio_is_linear_pcm(format) && samplingRate <= MAX_MIXER_SAMPLING_RATE) { goto non_direct_output; } - // fall back to mixer output if possible when the direct output could not be open - if (audio_is_linear_pcm(format) && samplingRate <= MAX_MIXER_SAMPLING_RATE) { - goto non_direct_output; - } return AUDIO_IO_HANDLE_NONE; } outputDesc->mSamplingRate = config.sample_rate; -- cgit v1.1