diff options
author | Eric Laurent <elaurent@google.com> | 2014-09-08 16:44:28 -0700 |
---|---|---|
committer | Eric Laurent <elaurent@google.com> | 2014-09-08 16:44:28 -0700 |
commit | 8838a3895c365d443ee22e169ccf45956780c081 (patch) | |
tree | 6f8d8de1cd91a541e67102078b7fe2f1c303009f /services | |
parent | 2e97b01cecec65e690ac7da5df9433c52ff75bd8 (diff) | |
download | frameworks_av-8838a3895c365d443ee22e169ccf45956780c081.zip frameworks_av-8838a3895c365d443ee22e169ccf45956780c081.tar.gz frameworks_av-8838a3895c365d443ee22e169ccf45956780c081.tar.bz2 |
audio policy: fix output stream selection
Make sure that all outputs considered by selectOutput()
when called from AudioPolicyManager::getOutputForDevice()
support the requested audio format.
Bug: 17340382.
Change-Id: I76520ce60e9a8fe4d2d23125d6143bb016522754
Diffstat (limited to 'services')
-rw-r--r-- | services/audiopolicy/AudioPolicyManager.cpp | 30 | ||||
-rw-r--r-- | services/audiopolicy/AudioPolicyManager.h | 3 |
2 files changed, 27 insertions, 6 deletions
diff --git a/services/audiopolicy/AudioPolicyManager.cpp b/services/audiopolicy/AudioPolicyManager.cpp index 6446a6e..6adcde4 100644 --- a/services/audiopolicy/AudioPolicyManager.cpp +++ b/services/audiopolicy/AudioPolicyManager.cpp @@ -485,7 +485,9 @@ void AudioPolicyManager::updateCallRouting(audio_devices_t rxDevice, int delayMs // request to reuse existing output stream if one is already opened to reach the RX device SortedVector<audio_io_handle_t> outputs = getOutputsForDevice(rxDevice, mOutputs); - audio_io_handle_t output = selectOutput(outputs, AUDIO_OUTPUT_FLAG_NONE); + audio_io_handle_t output = selectOutput(outputs, + AUDIO_OUTPUT_FLAG_NONE, + AUDIO_FORMAT_INVALID); if (output != AUDIO_IO_HANDLE_NONE) { sp<AudioOutputDescriptor> outputDesc = mOutputs.valueFor(output); ALOG_ASSERT(!outputDesc->isDuplicated(), @@ -524,7 +526,9 @@ void AudioPolicyManager::updateCallRouting(audio_devices_t rxDevice, int delayMs SortedVector<audio_io_handle_t> outputs = getOutputsForDevice(AUDIO_DEVICE_OUT_TELEPHONY_TX, mOutputs); - audio_io_handle_t output = selectOutput(outputs, AUDIO_OUTPUT_FLAG_NONE); + audio_io_handle_t output = selectOutput(outputs, + AUDIO_OUTPUT_FLAG_NONE, + AUDIO_FORMAT_INVALID); // request to reuse existing output stream if one is already opened to reach the TX // path output device if (output != AUDIO_IO_HANDLE_NONE) { @@ -1016,7 +1020,9 @@ audio_io_handle_t AudioPolicyManager::getOutputForDevice( // routing change will happen when startOutput() will be called SortedVector<audio_io_handle_t> outputs = getOutputsForDevice(device, mOutputs); - output = selectOutput(outputs, flags); + // at this stage we should ignore the DIRECT flag as no direct output could be found earlier + flags = (audio_output_flags_t)(flags & ~AUDIO_OUTPUT_FLAG_DIRECT); + output = selectOutput(outputs, flags, format); } ALOGW_IF((output == 0), "getOutput() could not find output for stream %d, samplingRate %d," "format %d, channels %x, flags %x", stream, samplingRate, format, channelMask, flags); @@ -1027,7 +1033,8 @@ audio_io_handle_t AudioPolicyManager::getOutputForDevice( } audio_io_handle_t AudioPolicyManager::selectOutput(const SortedVector<audio_io_handle_t>& outputs, - audio_output_flags_t flags) + audio_output_flags_t flags, + audio_format_t format) { // select one output among several that provide a path to a particular device or set of // devices (the list was previously build by getOutputsForDevice()). @@ -1050,6 +1057,17 @@ audio_io_handle_t AudioPolicyManager::selectOutput(const SortedVector<audio_io_h for (size_t i = 0; i < outputs.size(); i++) { sp<AudioOutputDescriptor> outputDesc = mOutputs.valueFor(outputs[i]); if (!outputDesc->isDuplicated()) { + // if a valid format is specified, skip output if not compatible + if (format != AUDIO_FORMAT_INVALID) { + if (outputDesc->mFlags & AUDIO_OUTPUT_FLAG_DIRECT) { + if (format != outputDesc->mFormat) { + continue; + } + } else if (!audio_is_linear_pcm(format)) { + continue; + } + } + int commonFlags = popcount(outputDesc->mProfile->mFlags & flags); if (commonFlags > maxCommonFlags) { outputFlags = outputs[i]; @@ -2307,7 +2325,9 @@ status_t AudioPolicyManager::createAudioPatch(const struct audio_patch *patch, mOutputs); // if the sink device is reachable via an opened output stream, request to go via // this output stream by adding a second source to the patch description - audio_io_handle_t output = selectOutput(outputs, AUDIO_OUTPUT_FLAG_NONE); + audio_io_handle_t output = selectOutput(outputs, + AUDIO_OUTPUT_FLAG_NONE, + AUDIO_FORMAT_INVALID); if (output != AUDIO_IO_HANDLE_NONE) { sp<AudioOutputDescriptor> outputDesc = mOutputs.valueFor(output); if (outputDesc->isDuplicated()) { diff --git a/services/audiopolicy/AudioPolicyManager.h b/services/audiopolicy/AudioPolicyManager.h index 57e015e..da0d95d 100644 --- a/services/audiopolicy/AudioPolicyManager.h +++ b/services/audiopolicy/AudioPolicyManager.h @@ -713,7 +713,8 @@ protected: uint32_t delayMs); audio_io_handle_t selectOutput(const SortedVector<audio_io_handle_t>& outputs, - audio_output_flags_t flags); + audio_output_flags_t flags, + audio_format_t format); // samplingRate parameter is an in/out and so may be modified sp<IOProfile> getInputProfile(audio_devices_t device, uint32_t& samplingRate, |