Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 40573325 authored by jiabin's avatar jiabin
Browse files

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
parent 6b6a0f05
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -233,6 +233,12 @@ const OutputChannelConverter::Table OutputChannelConverter::mTable[] = {
    MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
    MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_OUT_7POINT1POINT2),
    MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_OUT_7POINT1POINT4),
    MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_OUT_HAPTIC_A),
    MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_OUT_MONO_HAPTIC_A),
    MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_OUT_STEREO_HAPTIC_A),
    MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_OUT_HAPTIC_AB),
    MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_OUT_MONO_HAPTIC_AB),
    MAKE_STRING_FROM_ENUM(AUDIO_CHANNEL_OUT_STEREO_HAPTIC_AB),
    TERMINATOR
};

+9 −8
Original line number Diff line number Diff line
@@ -365,16 +365,17 @@ private:
    static inline bool isValidPcmSinkChannelMask(audio_channel_mask_t channelMask) {
        switch (audio_channel_mask_get_representation(channelMask)) {
        case AUDIO_CHANNEL_REPRESENTATION_POSITION: {
            uint32_t channelCount = FCC_2; // stereo is default
            if (kEnableExtendedChannels) {
                channelCount = audio_channel_count_from_out_mask(channelMask);
            // Haptic channel mask is only applicable for channel position mask.
            const uint32_t channelCount = audio_channel_count_from_out_mask(
                    channelMask & ~AUDIO_CHANNEL_HAPTIC_ALL);
            const uint32_t maxChannelCount = kEnableExtendedChannels
                    ? AudioMixer::MAX_NUM_CHANNELS : FCC_2;
            if (channelCount < FCC_2 // mono is not supported at this time
                        || channelCount > AudioMixer::MAX_NUM_CHANNELS) {
                    || channelCount > maxChannelCount) {
                return false;
            }
            }
            // check that channelMask is the "canonical" one we expect for the channelCount.
            return channelMask == audio_channel_out_mask_from_count(channelCount);
            return audio_channel_position_mask_is_out_canonical(channelMask);
            }
        case AUDIO_CHANNEL_REPRESENTATION_INDEX:
            if (kEnableExtendedChannels) {
+34 −13
Original line number Diff line number Diff line
@@ -482,7 +482,7 @@ sp<AudioPatch> AudioPolicyManager::createTelephonyPatch(

    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 @@ audio_io_handle_t AudioPolicyManager::getOutput(audio_stream_type_t stream)
    // 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 @@ non_direct_output:

        // 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 @@ status_t AudioPolicyManager::setMsdPatch(audio_devices_t outputDevice) {

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 @@ audio_io_handle_t AudioPolicyManager::selectOutput(const SortedVector<audio_io_h
    }

    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 @@ audio_io_handle_t AudioPolicyManager::selectOutput(const SortedVector<audio_io_h
            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 @@ status_t AudioPolicyManager::createAudioPatch(const struct audio_patch *patch,
                                            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 @@ status_t AudioPolicyManager::connectAudioSource(const sp<SourceClientDescriptor>
        //   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;
+4 −2
Original line number Diff line number Diff line
@@ -470,8 +470,10 @@ protected:
                                            uint32_t delayMs);

        audio_io_handle_t selectOutput(const SortedVector<audio_io_handle_t>& outputs,
                                       audio_output_flags_t flags,
                                       audio_format_t format);
                                       audio_output_flags_t flags = AUDIO_OUTPUT_FLAG_NONE,
                                       audio_format_t format = AUDIO_FORMAT_INVALID,
                                       audio_channel_mask_t channelMask = AUDIO_CHANNEL_NONE,
                                       uint32_t samplingRate = 0);
        // samplingRate, format, channelMask are in/out and so may be modified
        sp<IOProfile> getInputProfile(audio_devices_t device,
                                      const String8& address,