Support open output stream with haptic channel mask.
When haptic playback is supported according to audio policy
configuration file, try to open the output stream with haptic channel
mask. When trying to creat a track with haptic channel mask, use haptic
output if it is available.
Bug: 111454766
Test: Manually test
Change-Id: Ia8c70dd7f602a134d0509630eb734b8c540dea7d
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index 6ec6a76..4c339bc 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -482,7 +482,7 @@
audio_devices_t outputDevice = isRx ? device : AUDIO_DEVICE_OUT_TELEPHONY_TX;
SortedVector<audio_io_handle_t> outputs = getOutputsForDevice(outputDevice, mOutputs);
- audio_io_handle_t output = selectOutput(outputs, AUDIO_OUTPUT_FLAG_NONE, AUDIO_FORMAT_INVALID);
+ 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);
@@ -749,7 +749,7 @@
// and AudioSystem::getOutputSamplingRate().
SortedVector<audio_io_handle_t> outputs = getOutputsForDevice(device, mOutputs);
- audio_io_handle_t output = selectOutput(outputs, AUDIO_OUTPUT_FLAG_NONE, AUDIO_FORMAT_INVALID);
+ audio_io_handle_t output = selectOutput(outputs);
ALOGV("getOutput() stream %d selected device %08x, output %d", stream, device, output);
return output;
@@ -1064,7 +1064,8 @@
// 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, config->format);
+ output = selectOutput(outputs, *flags, config->format,
+ config->channel_mask, config->sample_rate);
}
ALOGW_IF((output == 0), "getOutputForDevice() could not find output for stream %d, "
"sampling rate %d, format %#x, channels %#x, flags %#x",
@@ -1233,15 +1234,18 @@
audio_io_handle_t AudioPolicyManager::selectOutput(const SortedVector<audio_io_handle_t>& outputs,
audio_output_flags_t flags,
- audio_format_t format)
+ audio_format_t format,
+ audio_channel_mask_t channelMask,
+ uint32_t samplingRate)
{
// select one output among several that provide a path to a particular device or set of
// devices (the list was previously build by getOutputsForDevice()).
// The priority is as follows:
- // 1: the output with the highest number of requested policy flags
- // 2: the output with the bit depth the closest to the requested one
- // 3: the primary output
- // 4: the first output in the list
+ // 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;
@@ -1251,6 +1255,8 @@
}
int maxCommonFlags = 0;
+ const size_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;
@@ -1263,6 +1269,24 @@
if (outputDesc->mFlags & AUDIO_OUTPUT_FLAG_DIRECT) {
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
+ && format == outputDesc->mFormat
+ && samplingRate == outputDesc->mSamplingRate) {
+ return output;
+ }
+ } else {
+ // When haptic channel is not specified, skip haptic output.
+ if (outputDesc->mChannelMask & AUDIO_CHANNEL_HAPTIC_ALL) {
+ continue;
+ }
+ }
+
// if a valid format is specified, skip output if not compatible
if (format != AUDIO_FORMAT_INVALID) {
if (!audio_is_linear_pcm(format)) {
@@ -3101,9 +3125,7 @@
getOutputsForDevice(sinkDeviceDesc->type(), 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_FORMAT_INVALID);
+ audio_io_handle_t output = selectOutput(outputs);
if (output != AUDIO_IO_HANDLE_NONE) {
sp<AudioOutputDescriptor> outputDesc = mOutputs.valueFor(output);
if (outputDesc->isDuplicated()) {
@@ -3447,8 +3469,7 @@
// create Hwoutput and add to mHwOutputs
} else {
SortedVector<audio_io_handle_t> outputs = getOutputsForDevice(sinkDevice, mOutputs);
- audio_io_handle_t output =
- selectOutput(outputs, AUDIO_OUTPUT_FLAG_NONE, AUDIO_FORMAT_INVALID);
+ audio_io_handle_t output = selectOutput(outputs);
if (output == AUDIO_IO_HANDLE_NONE) {
ALOGV("%s no output for device %08x", __FUNCTION__, sinkDevice);
return INVALID_OPERATION;