Loading media/libaaudio/src/legacy/AudioStreamRecord.cpp +3 −1 Original line number Diff line number Diff line Loading @@ -63,7 +63,9 @@ aaudio_result_t AudioStreamRecord::open(const AudioStreamBuilder& builder) // TODO Support UNSPECIFIED in AudioRecord. For now, use stereo if unspecified. int32_t samplesPerFrame = (getSamplesPerFrame() == AAUDIO_UNSPECIFIED) ? 2 : getSamplesPerFrame(); audio_channel_mask_t channelMask = audio_channel_in_mask_from_count(samplesPerFrame); audio_channel_mask_t channelMask = samplesPerFrame <= 2 ? audio_channel_in_mask_from_count(samplesPerFrame) : audio_channel_mask_for_index_assignment_from_count(samplesPerFrame); size_t frameCount = (builder.getBufferCapacity() == AAUDIO_UNSPECIFIED) ? 0 : builder.getBufferCapacity(); Loading media/libaaudio/src/legacy/AudioStreamTrack.cpp +3 −1 Original line number Diff line number Diff line Loading @@ -66,7 +66,9 @@ aaudio_result_t AudioStreamTrack::open(const AudioStreamBuilder& builder) // Use stereo if unspecified. int32_t samplesPerFrame = (getSamplesPerFrame() == AAUDIO_UNSPECIFIED) ? 2 : getSamplesPerFrame(); audio_channel_mask_t channelMask = audio_channel_out_mask_from_count(samplesPerFrame); audio_channel_mask_t channelMask = samplesPerFrame <= 2 ? audio_channel_out_mask_from_count(samplesPerFrame) : audio_channel_mask_for_index_assignment_from_count(samplesPerFrame); audio_output_flags_t flags; aaudio_performance_mode_t perfMode = getPerformanceMode(); Loading services/audiopolicy/common/managerdefinitions/include/AudioPort.h +3 −0 Original line number Diff line number Diff line Loading @@ -112,6 +112,9 @@ public: static bool isBetterFormatMatch(audio_format_t newFormat, audio_format_t currentFormat, audio_format_t targetFormat); static uint32_t formatDistance(audio_format_t format1, audio_format_t format2); static const uint32_t kFormatDistanceMax = 4; audio_module_handle_t getModuleHandle() const; uint32_t getModuleVersionMajor() const; Loading services/audiopolicy/common/managerdefinitions/src/AudioPort.cpp +15 −20 Original line number Diff line number Diff line Loading @@ -282,30 +282,25 @@ int AudioPort::compareFormats(audio_format_t format1, audio_format_t format2) return index1 - index2; } bool AudioPort::isBetterFormatMatch(audio_format_t newFormat, audio_format_t currentFormat, audio_format_t targetFormat) uint32_t AudioPort::formatDistance(audio_format_t format1, audio_format_t format2) { if (newFormat == currentFormat) { return false; } if (currentFormat == AUDIO_FORMAT_INVALID) { return true; if (format1 == format2) { return 0; } if (newFormat == targetFormat) { return true; if (format1 == AUDIO_FORMAT_INVALID || format2 == AUDIO_FORMAT_INVALID) { return kFormatDistanceMax; } int currentDiffBytes = (int)audio_bytes_per_sample(targetFormat) - audio_bytes_per_sample(currentFormat); int newDiffBytes = (int)audio_bytes_per_sample(targetFormat) - audio_bytes_per_sample(newFormat); int diffBytes = (int)audio_bytes_per_sample(format1) - audio_bytes_per_sample(format2); if (abs(newDiffBytes) < abs(currentDiffBytes)) { return true; } else if (abs(newDiffBytes) == abs(currentDiffBytes)) { return (newDiffBytes >= 0); return abs(diffBytes); } return false; bool AudioPort::isBetterFormatMatch(audio_format_t newFormat, audio_format_t currentFormat, audio_format_t targetFormat) { return formatDistance(newFormat, targetFormat) < formatDistance(currentFormat, targetFormat); } void AudioPort::pickAudioProfile(uint32_t &samplingRate, Loading services/audiopolicy/managerdefault/AudioPolicyManager.cpp +108 −91 Original line number Diff line number Diff line Loading @@ -36,12 +36,12 @@ #define AUDIO_POLICY_BLUETOOTH_LEGACY_HAL_XML_CONFIG_FILE_NAME \ "audio_policy_configuration_bluetooth_legacy_hal.xml" #include <algorithm> #include <inttypes.h> #include <math.h> #include <set> #include <unordered_set> #include <vector> #include <AudioPolicyManagerInterface.h> #include <AudioPolicyEngineInstance.h> #include <cutils/properties.h> Loading Loading @@ -592,7 +592,7 @@ sp<AudioPatch> AudioPolicyManager::createTelephonyPatch( AUDIO_DEVICE_OUT_TELEPHONY_TX, String8(), AUDIO_FORMAT_DEFAULT); SortedVector<audio_io_handle_t> outputs = getOutputsForDevices(DeviceVector(outputDevice), mOutputs); audio_io_handle_t output = selectOutput(outputs, AUDIO_OUTPUT_FLAG_NONE, AUDIO_FORMAT_INVALID); const audio_io_handle_t output = selectOutput(outputs); // request to reuse existing output stream if one is already opened to reach the target device if (output != AUDIO_IO_HANDLE_NONE) { sp<AudioOutputDescriptor> outputDesc = mOutputs.valueFor(output); Loading Loading @@ -883,7 +883,7 @@ audio_io_handle_t AudioPolicyManager::getOutput(audio_stream_type_t stream) // and AudioSystem::getOutputSamplingRate(). SortedVector<audio_io_handle_t> outputs = getOutputsForDevices(devices, mOutputs); audio_io_handle_t output = selectOutput(outputs, AUDIO_OUTPUT_FLAG_NONE, AUDIO_FORMAT_INVALID); const audio_io_handle_t output = selectOutput(outputs); ALOGV("getOutput() stream %d selected devices %s, output %d", stream, devices.toString().c_str(), output); Loading Loading @@ -1430,108 +1430,125 @@ audio_io_handle_t AudioPolicyManager::selectOutput(const SortedVector<audio_io_h audio_channel_mask_t channelMask, uint32_t samplingRate) { LOG_ALWAYS_FATAL_IF(!(format == AUDIO_FORMAT_INVALID || audio_is_linear_pcm(format)), "%s called with format %#x", __func__, format); // Flags disqualifying an output: the match must happen before calling selectOutput() static const audio_output_flags_t kExcludedFlags = (audio_output_flags_t) (AUDIO_OUTPUT_FLAG_HW_AV_SYNC | AUDIO_OUTPUT_FLAG_MMAP_NOIRQ | AUDIO_OUTPUT_FLAG_DIRECT); // Flags expressing a functional request: must be honored in priority over // other criteria static const audio_output_flags_t kFunctionalFlags = (audio_output_flags_t) (AUDIO_OUTPUT_FLAG_VOIP_RX | AUDIO_OUTPUT_FLAG_INCALL_MUSIC | AUDIO_OUTPUT_FLAG_TTS | AUDIO_OUTPUT_FLAG_DIRECT_PCM); // Flags expressing a performance request: have lower priority than serving // requested sampling rate or channel mask static const audio_output_flags_t kPerformanceFlags = (audio_output_flags_t) (AUDIO_OUTPUT_FLAG_FAST | AUDIO_OUTPUT_FLAG_DEEP_BUFFER | AUDIO_OUTPUT_FLAG_RAW | AUDIO_OUTPUT_FLAG_SYNC); const audio_output_flags_t functionalFlags = (audio_output_flags_t)(flags & kFunctionalFlags); const audio_output_flags_t performanceFlags = (audio_output_flags_t)(flags & kPerformanceFlags); audio_io_handle_t bestOutput = (outputs.size() == 0) ? AUDIO_IO_HANDLE_NONE : outputs[0]; // select one output among several that provide a path to a particular device or set of // devices (the list was previously build by getOutputsForDevices()). // The priority is as follows: // 1: the output supporting haptic playback when requesting haptic playback // 2: the output with the highest number of requested policy flags // 3: the output with the bit depth the closest to the requested one // 4: the primary output // 5: the first output in the list if (outputs.size() == 0) { return AUDIO_IO_HANDLE_NONE; } if (outputs.size() == 1) { return outputs[0]; } int maxCommonFlags = 0; const size_t hapticChannelCount = audio_channel_count_from_out_mask( // 2: the output with the highest number of requested functional flags // 3: the output supporting the exact channel mask // 4: the output with a higher channel count than requested // 5: the output with a higher sampling rate than requested // 6: the output with the highest number of requested performance flags // 7: the output with the bit depth the closest to the requested one // 8: the primary output // 9: the first output in the list // matching criteria values in priority order for best matching output so far std::vector<uint32_t> bestMatchCriteria(8, 0); const uint32_t channelCount = audio_channel_count_from_out_mask(channelMask); const uint32_t hapticChannelCount = audio_channel_count_from_out_mask( channelMask & AUDIO_CHANNEL_HAPTIC_ALL); audio_io_handle_t outputForFlags = AUDIO_IO_HANDLE_NONE; audio_io_handle_t outputForPrimary = AUDIO_IO_HANDLE_NONE; audio_io_handle_t outputForFormat = AUDIO_IO_HANDLE_NONE; audio_format_t bestFormat = AUDIO_FORMAT_INVALID; audio_format_t bestFormatForFlags = AUDIO_FORMAT_INVALID; // Flags which must be present on both the request and the selected output static const audio_output_flags_t kMandatedFlags = (audio_output_flags_t) (AUDIO_OUTPUT_FLAG_HW_AV_SYNC | AUDIO_OUTPUT_FLAG_MMAP_NOIRQ); for (audio_io_handle_t output : outputs) { sp<SwAudioOutputDescriptor> outputDesc = mOutputs.valueFor(output); if (!outputDesc->isDuplicated()) { if (outputDesc->mFlags & AUDIO_OUTPUT_FLAG_DIRECT) { // matching criteria values in priority order for current output std::vector<uint32_t> currentMatchCriteria(8, 0); if (outputDesc->isDuplicated()) { continue; } if ((kExcludedFlags & outputDesc->mFlags) != 0) { continue; } // If haptic channel is specified, use the haptic output if present. // When using haptic output, same audio format and sample rate are required. if (hapticChannelCount > 0) { // If haptic channel is specified, use the first output that // support haptic playback. if (audio_channel_count_from_out_mask( outputDesc->mChannelMask & AUDIO_CHANNEL_HAPTIC_ALL) >= hapticChannelCount const uint32_t outputHapticChannelCount = audio_channel_count_from_out_mask( outputDesc->mChannelMask & AUDIO_CHANNEL_HAPTIC_ALL); if ((hapticChannelCount == 0) != (outputHapticChannelCount == 0)) { continue; } if (outputHapticChannelCount >= hapticChannelCount && format == outputDesc->mFormat && samplingRate == outputDesc->mSamplingRate) { return output; currentMatchCriteria[0] = outputHapticChannelCount; } } else { // When haptic channel is not specified, skip haptic output. if (outputDesc->mChannelMask & AUDIO_CHANNEL_HAPTIC_ALL) { continue; // functional flags match currentMatchCriteria[1] = popcount(outputDesc->mFlags & functionalFlags); // channel mask and channel count match uint32_t outputChannelCount = audio_channel_count_from_out_mask(outputDesc->mChannelMask); if (channelMask != AUDIO_CHANNEL_NONE && channelCount > 2 && channelCount <= outputChannelCount) { if ((audio_channel_mask_get_representation(channelMask) == audio_channel_mask_get_representation(outputDesc->mChannelMask)) && ((channelMask & outputDesc->mChannelMask) == channelMask)) { currentMatchCriteria[2] = outputChannelCount; } currentMatchCriteria[3] = outputChannelCount; } if ((kMandatedFlags & flags) != (kMandatedFlags & outputDesc->mProfile->getFlags())) { continue; // sampling rate match if (samplingRate > SAMPLE_RATE_HZ_DEFAULT && samplingRate <= outputDesc->mSamplingRate) { currentMatchCriteria[4] = outputDesc->mSamplingRate; } // if a valid format is specified, skip output if not compatible // performance flags match currentMatchCriteria[5] = popcount(outputDesc->mFlags & performanceFlags); // format match if (format != AUDIO_FORMAT_INVALID) { if (!audio_is_linear_pcm(format)) { continue; } if (AudioPort::isBetterFormatMatch( outputDesc->mFormat, bestFormat, format)) { outputForFormat = output; bestFormat = outputDesc->mFormat; } currentMatchCriteria[6] = AudioPort::kFormatDistanceMax - AudioPort::formatDistance(format, outputDesc->mFormat); } int commonFlags = popcount(outputDesc->mProfile->getFlags() & flags); if (commonFlags >= maxCommonFlags) { if (commonFlags == maxCommonFlags) { if (format != AUDIO_FORMAT_INVALID && AudioPort::isBetterFormatMatch( outputDesc->mFormat, bestFormatForFlags, format)) { outputForFlags = output; bestFormatForFlags = outputDesc->mFormat; } } else { outputForFlags = output; maxCommonFlags = commonFlags; bestFormatForFlags = outputDesc->mFormat; } ALOGV("selectOutput() commonFlags for output %d, %04x", output, commonFlags); } if (outputDesc->mProfile->getFlags() & AUDIO_OUTPUT_FLAG_PRIMARY) { outputForPrimary = output; } } } // primary output match currentMatchCriteria[7] = outputDesc->mFlags & AUDIO_OUTPUT_FLAG_PRIMARY; if (outputForFlags != AUDIO_IO_HANDLE_NONE) { return outputForFlags; } if (outputForFormat != AUDIO_IO_HANDLE_NONE) { return outputForFormat; // compare match criteria by priority then value if (std::lexicographical_compare(bestMatchCriteria.begin(), bestMatchCriteria.end(), currentMatchCriteria.begin(), currentMatchCriteria.end())) { bestMatchCriteria = currentMatchCriteria; bestOutput = output; std::stringstream result; std::copy(bestMatchCriteria.begin(), bestMatchCriteria.end(), std::ostream_iterator<int>(result, " ")); ALOGV("%s new bestOutput %d criteria %s", __func__, bestOutput, result.str().c_str()); } if (outputForPrimary != AUDIO_IO_HANDLE_NONE) { return outputForPrimary; } return outputs[0]; return bestOutput; } status_t AudioPolicyManager::startOutput(audio_port_handle_t portId) Loading Loading @@ -3474,7 +3491,7 @@ status_t AudioPolicyManager::createAudioPatch(const struct audio_patch *patch, getOutputsForDevices(DeviceVector(sinkDevice), 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); const audio_io_handle_t output = selectOutput(outputs); if (output != AUDIO_IO_HANDLE_NONE) { sp<AudioOutputDescriptor> outputDesc = mOutputs.valueFor(output); if (outputDesc->isDuplicated()) { Loading Loading
media/libaaudio/src/legacy/AudioStreamRecord.cpp +3 −1 Original line number Diff line number Diff line Loading @@ -63,7 +63,9 @@ aaudio_result_t AudioStreamRecord::open(const AudioStreamBuilder& builder) // TODO Support UNSPECIFIED in AudioRecord. For now, use stereo if unspecified. int32_t samplesPerFrame = (getSamplesPerFrame() == AAUDIO_UNSPECIFIED) ? 2 : getSamplesPerFrame(); audio_channel_mask_t channelMask = audio_channel_in_mask_from_count(samplesPerFrame); audio_channel_mask_t channelMask = samplesPerFrame <= 2 ? audio_channel_in_mask_from_count(samplesPerFrame) : audio_channel_mask_for_index_assignment_from_count(samplesPerFrame); size_t frameCount = (builder.getBufferCapacity() == AAUDIO_UNSPECIFIED) ? 0 : builder.getBufferCapacity(); Loading
media/libaaudio/src/legacy/AudioStreamTrack.cpp +3 −1 Original line number Diff line number Diff line Loading @@ -66,7 +66,9 @@ aaudio_result_t AudioStreamTrack::open(const AudioStreamBuilder& builder) // Use stereo if unspecified. int32_t samplesPerFrame = (getSamplesPerFrame() == AAUDIO_UNSPECIFIED) ? 2 : getSamplesPerFrame(); audio_channel_mask_t channelMask = audio_channel_out_mask_from_count(samplesPerFrame); audio_channel_mask_t channelMask = samplesPerFrame <= 2 ? audio_channel_out_mask_from_count(samplesPerFrame) : audio_channel_mask_for_index_assignment_from_count(samplesPerFrame); audio_output_flags_t flags; aaudio_performance_mode_t perfMode = getPerformanceMode(); Loading
services/audiopolicy/common/managerdefinitions/include/AudioPort.h +3 −0 Original line number Diff line number Diff line Loading @@ -112,6 +112,9 @@ public: static bool isBetterFormatMatch(audio_format_t newFormat, audio_format_t currentFormat, audio_format_t targetFormat); static uint32_t formatDistance(audio_format_t format1, audio_format_t format2); static const uint32_t kFormatDistanceMax = 4; audio_module_handle_t getModuleHandle() const; uint32_t getModuleVersionMajor() const; Loading
services/audiopolicy/common/managerdefinitions/src/AudioPort.cpp +15 −20 Original line number Diff line number Diff line Loading @@ -282,30 +282,25 @@ int AudioPort::compareFormats(audio_format_t format1, audio_format_t format2) return index1 - index2; } bool AudioPort::isBetterFormatMatch(audio_format_t newFormat, audio_format_t currentFormat, audio_format_t targetFormat) uint32_t AudioPort::formatDistance(audio_format_t format1, audio_format_t format2) { if (newFormat == currentFormat) { return false; } if (currentFormat == AUDIO_FORMAT_INVALID) { return true; if (format1 == format2) { return 0; } if (newFormat == targetFormat) { return true; if (format1 == AUDIO_FORMAT_INVALID || format2 == AUDIO_FORMAT_INVALID) { return kFormatDistanceMax; } int currentDiffBytes = (int)audio_bytes_per_sample(targetFormat) - audio_bytes_per_sample(currentFormat); int newDiffBytes = (int)audio_bytes_per_sample(targetFormat) - audio_bytes_per_sample(newFormat); int diffBytes = (int)audio_bytes_per_sample(format1) - audio_bytes_per_sample(format2); if (abs(newDiffBytes) < abs(currentDiffBytes)) { return true; } else if (abs(newDiffBytes) == abs(currentDiffBytes)) { return (newDiffBytes >= 0); return abs(diffBytes); } return false; bool AudioPort::isBetterFormatMatch(audio_format_t newFormat, audio_format_t currentFormat, audio_format_t targetFormat) { return formatDistance(newFormat, targetFormat) < formatDistance(currentFormat, targetFormat); } void AudioPort::pickAudioProfile(uint32_t &samplingRate, Loading
services/audiopolicy/managerdefault/AudioPolicyManager.cpp +108 −91 Original line number Diff line number Diff line Loading @@ -36,12 +36,12 @@ #define AUDIO_POLICY_BLUETOOTH_LEGACY_HAL_XML_CONFIG_FILE_NAME \ "audio_policy_configuration_bluetooth_legacy_hal.xml" #include <algorithm> #include <inttypes.h> #include <math.h> #include <set> #include <unordered_set> #include <vector> #include <AudioPolicyManagerInterface.h> #include <AudioPolicyEngineInstance.h> #include <cutils/properties.h> Loading Loading @@ -592,7 +592,7 @@ sp<AudioPatch> AudioPolicyManager::createTelephonyPatch( AUDIO_DEVICE_OUT_TELEPHONY_TX, String8(), AUDIO_FORMAT_DEFAULT); SortedVector<audio_io_handle_t> outputs = getOutputsForDevices(DeviceVector(outputDevice), mOutputs); audio_io_handle_t output = selectOutput(outputs, AUDIO_OUTPUT_FLAG_NONE, AUDIO_FORMAT_INVALID); const audio_io_handle_t output = selectOutput(outputs); // request to reuse existing output stream if one is already opened to reach the target device if (output != AUDIO_IO_HANDLE_NONE) { sp<AudioOutputDescriptor> outputDesc = mOutputs.valueFor(output); Loading Loading @@ -883,7 +883,7 @@ audio_io_handle_t AudioPolicyManager::getOutput(audio_stream_type_t stream) // and AudioSystem::getOutputSamplingRate(). SortedVector<audio_io_handle_t> outputs = getOutputsForDevices(devices, mOutputs); audio_io_handle_t output = selectOutput(outputs, AUDIO_OUTPUT_FLAG_NONE, AUDIO_FORMAT_INVALID); const audio_io_handle_t output = selectOutput(outputs); ALOGV("getOutput() stream %d selected devices %s, output %d", stream, devices.toString().c_str(), output); Loading Loading @@ -1430,108 +1430,125 @@ audio_io_handle_t AudioPolicyManager::selectOutput(const SortedVector<audio_io_h audio_channel_mask_t channelMask, uint32_t samplingRate) { LOG_ALWAYS_FATAL_IF(!(format == AUDIO_FORMAT_INVALID || audio_is_linear_pcm(format)), "%s called with format %#x", __func__, format); // Flags disqualifying an output: the match must happen before calling selectOutput() static const audio_output_flags_t kExcludedFlags = (audio_output_flags_t) (AUDIO_OUTPUT_FLAG_HW_AV_SYNC | AUDIO_OUTPUT_FLAG_MMAP_NOIRQ | AUDIO_OUTPUT_FLAG_DIRECT); // Flags expressing a functional request: must be honored in priority over // other criteria static const audio_output_flags_t kFunctionalFlags = (audio_output_flags_t) (AUDIO_OUTPUT_FLAG_VOIP_RX | AUDIO_OUTPUT_FLAG_INCALL_MUSIC | AUDIO_OUTPUT_FLAG_TTS | AUDIO_OUTPUT_FLAG_DIRECT_PCM); // Flags expressing a performance request: have lower priority than serving // requested sampling rate or channel mask static const audio_output_flags_t kPerformanceFlags = (audio_output_flags_t) (AUDIO_OUTPUT_FLAG_FAST | AUDIO_OUTPUT_FLAG_DEEP_BUFFER | AUDIO_OUTPUT_FLAG_RAW | AUDIO_OUTPUT_FLAG_SYNC); const audio_output_flags_t functionalFlags = (audio_output_flags_t)(flags & kFunctionalFlags); const audio_output_flags_t performanceFlags = (audio_output_flags_t)(flags & kPerformanceFlags); audio_io_handle_t bestOutput = (outputs.size() == 0) ? AUDIO_IO_HANDLE_NONE : outputs[0]; // select one output among several that provide a path to a particular device or set of // devices (the list was previously build by getOutputsForDevices()). // The priority is as follows: // 1: the output supporting haptic playback when requesting haptic playback // 2: the output with the highest number of requested policy flags // 3: the output with the bit depth the closest to the requested one // 4: the primary output // 5: the first output in the list if (outputs.size() == 0) { return AUDIO_IO_HANDLE_NONE; } if (outputs.size() == 1) { return outputs[0]; } int maxCommonFlags = 0; const size_t hapticChannelCount = audio_channel_count_from_out_mask( // 2: the output with the highest number of requested functional flags // 3: the output supporting the exact channel mask // 4: the output with a higher channel count than requested // 5: the output with a higher sampling rate than requested // 6: the output with the highest number of requested performance flags // 7: the output with the bit depth the closest to the requested one // 8: the primary output // 9: the first output in the list // matching criteria values in priority order for best matching output so far std::vector<uint32_t> bestMatchCriteria(8, 0); const uint32_t channelCount = audio_channel_count_from_out_mask(channelMask); const uint32_t hapticChannelCount = audio_channel_count_from_out_mask( channelMask & AUDIO_CHANNEL_HAPTIC_ALL); audio_io_handle_t outputForFlags = AUDIO_IO_HANDLE_NONE; audio_io_handle_t outputForPrimary = AUDIO_IO_HANDLE_NONE; audio_io_handle_t outputForFormat = AUDIO_IO_HANDLE_NONE; audio_format_t bestFormat = AUDIO_FORMAT_INVALID; audio_format_t bestFormatForFlags = AUDIO_FORMAT_INVALID; // Flags which must be present on both the request and the selected output static const audio_output_flags_t kMandatedFlags = (audio_output_flags_t) (AUDIO_OUTPUT_FLAG_HW_AV_SYNC | AUDIO_OUTPUT_FLAG_MMAP_NOIRQ); for (audio_io_handle_t output : outputs) { sp<SwAudioOutputDescriptor> outputDesc = mOutputs.valueFor(output); if (!outputDesc->isDuplicated()) { if (outputDesc->mFlags & AUDIO_OUTPUT_FLAG_DIRECT) { // matching criteria values in priority order for current output std::vector<uint32_t> currentMatchCriteria(8, 0); if (outputDesc->isDuplicated()) { continue; } if ((kExcludedFlags & outputDesc->mFlags) != 0) { continue; } // If haptic channel is specified, use the haptic output if present. // When using haptic output, same audio format and sample rate are required. if (hapticChannelCount > 0) { // If haptic channel is specified, use the first output that // support haptic playback. if (audio_channel_count_from_out_mask( outputDesc->mChannelMask & AUDIO_CHANNEL_HAPTIC_ALL) >= hapticChannelCount const uint32_t outputHapticChannelCount = audio_channel_count_from_out_mask( outputDesc->mChannelMask & AUDIO_CHANNEL_HAPTIC_ALL); if ((hapticChannelCount == 0) != (outputHapticChannelCount == 0)) { continue; } if (outputHapticChannelCount >= hapticChannelCount && format == outputDesc->mFormat && samplingRate == outputDesc->mSamplingRate) { return output; currentMatchCriteria[0] = outputHapticChannelCount; } } else { // When haptic channel is not specified, skip haptic output. if (outputDesc->mChannelMask & AUDIO_CHANNEL_HAPTIC_ALL) { continue; // functional flags match currentMatchCriteria[1] = popcount(outputDesc->mFlags & functionalFlags); // channel mask and channel count match uint32_t outputChannelCount = audio_channel_count_from_out_mask(outputDesc->mChannelMask); if (channelMask != AUDIO_CHANNEL_NONE && channelCount > 2 && channelCount <= outputChannelCount) { if ((audio_channel_mask_get_representation(channelMask) == audio_channel_mask_get_representation(outputDesc->mChannelMask)) && ((channelMask & outputDesc->mChannelMask) == channelMask)) { currentMatchCriteria[2] = outputChannelCount; } currentMatchCriteria[3] = outputChannelCount; } if ((kMandatedFlags & flags) != (kMandatedFlags & outputDesc->mProfile->getFlags())) { continue; // sampling rate match if (samplingRate > SAMPLE_RATE_HZ_DEFAULT && samplingRate <= outputDesc->mSamplingRate) { currentMatchCriteria[4] = outputDesc->mSamplingRate; } // if a valid format is specified, skip output if not compatible // performance flags match currentMatchCriteria[5] = popcount(outputDesc->mFlags & performanceFlags); // format match if (format != AUDIO_FORMAT_INVALID) { if (!audio_is_linear_pcm(format)) { continue; } if (AudioPort::isBetterFormatMatch( outputDesc->mFormat, bestFormat, format)) { outputForFormat = output; bestFormat = outputDesc->mFormat; } currentMatchCriteria[6] = AudioPort::kFormatDistanceMax - AudioPort::formatDistance(format, outputDesc->mFormat); } int commonFlags = popcount(outputDesc->mProfile->getFlags() & flags); if (commonFlags >= maxCommonFlags) { if (commonFlags == maxCommonFlags) { if (format != AUDIO_FORMAT_INVALID && AudioPort::isBetterFormatMatch( outputDesc->mFormat, bestFormatForFlags, format)) { outputForFlags = output; bestFormatForFlags = outputDesc->mFormat; } } else { outputForFlags = output; maxCommonFlags = commonFlags; bestFormatForFlags = outputDesc->mFormat; } ALOGV("selectOutput() commonFlags for output %d, %04x", output, commonFlags); } if (outputDesc->mProfile->getFlags() & AUDIO_OUTPUT_FLAG_PRIMARY) { outputForPrimary = output; } } } // primary output match currentMatchCriteria[7] = outputDesc->mFlags & AUDIO_OUTPUT_FLAG_PRIMARY; if (outputForFlags != AUDIO_IO_HANDLE_NONE) { return outputForFlags; } if (outputForFormat != AUDIO_IO_HANDLE_NONE) { return outputForFormat; // compare match criteria by priority then value if (std::lexicographical_compare(bestMatchCriteria.begin(), bestMatchCriteria.end(), currentMatchCriteria.begin(), currentMatchCriteria.end())) { bestMatchCriteria = currentMatchCriteria; bestOutput = output; std::stringstream result; std::copy(bestMatchCriteria.begin(), bestMatchCriteria.end(), std::ostream_iterator<int>(result, " ")); ALOGV("%s new bestOutput %d criteria %s", __func__, bestOutput, result.str().c_str()); } if (outputForPrimary != AUDIO_IO_HANDLE_NONE) { return outputForPrimary; } return outputs[0]; return bestOutput; } status_t AudioPolicyManager::startOutput(audio_port_handle_t portId) Loading Loading @@ -3474,7 +3491,7 @@ status_t AudioPolicyManager::createAudioPatch(const struct audio_patch *patch, getOutputsForDevices(DeviceVector(sinkDevice), 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); const audio_io_handle_t output = selectOutput(outputs); if (output != AUDIO_IO_HANDLE_NONE) { sp<AudioOutputDescriptor> outputDesc = mOutputs.valueFor(output); if (outputDesc->isDuplicated()) { Loading