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

Commit 2d059936 authored by Phil Burk's avatar Phil Burk
Browse files

audiopolicymanager: prevent MMAP stream collisions

An allocation of a second MMAP stream with a different
rate or channel count could collide with an existing MMAP
stream and cause it to fail.

Bug: 73369112
Test: test_interference.cpp
Change-Id: I8318ba897dd4999dd747d40a77b6850525616998
parent cdf22ce8
Loading
Loading
Loading
Loading
+20 −16
Original line number Diff line number Diff line
@@ -810,7 +810,7 @@ status_t AudioPolicyManager::getOutputForAttr(const audio_attributes_t *attr,
          "flags %#x",
          device, config->sample_rate, config->format, config->channel_mask, *flags);

    *output = getOutputForDevice(device, session, *stream, config, flags);
    *output = getOutputForDevice(device, session, *stream, *output, config, flags);
    if (*output == AUDIO_IO_HANDLE_NONE) {
        mOutputRoutes.removeRoute(session);
        return INVALID_OPERATION;
@@ -829,10 +829,11 @@ audio_io_handle_t AudioPolicyManager::getOutputForDevice(
        audio_devices_t device,
        audio_session_t session,
        audio_stream_type_t stream,
        audio_io_handle_t originalOutput,
        const audio_config_t *config,
        audio_output_flags_t *flags)
{
    audio_io_handle_t output = AUDIO_IO_HANDLE_NONE;
    audio_io_handle_t output = originalOutput;
    status_t status;

    // open a direct output if required by specified parameters
@@ -896,6 +897,8 @@ audio_io_handle_t AudioPolicyManager::getOutputForDevice(
    }

    if (profile != 0) {
        // exclude MMAP streams
        if ((*flags & AUDIO_OUTPUT_FLAG_MMAP_NOIRQ) == 0 || output != AUDIO_IO_HANDLE_NONE) {
            for (size_t i = 0; i < mOutputs.size(); i++) {
                sp<SwAudioOutputDescriptor> desc = mOutputs.valueAt(i);
                if (!desc->isDuplicated() && (profile == desc->mProfile)) {
@@ -906,12 +909,13 @@ audio_io_handle_t AudioPolicyManager::getOutputForDevice(
                        (config->channel_mask == desc->mChannelMask) &&
                        (session == desc->mDirectClientSession)) {
                        desc->mDirectOpenCount++;
                    ALOGV("getOutputForDevice() reusing direct output %d for session %d",
                        ALOGI("getOutputForDevice() reusing direct output %d for session %d",
                              mOutputs.keyAt(i), session);
                        return mOutputs.keyAt(i);
                    }
                }
            }
        }

        if (!profile->canOpenNewIo()) {
            goto non_direct_output;
@@ -962,7 +966,7 @@ non_direct_output:

    // A request for HW A/V sync cannot fallback to a mixed output because time
    // stamps are embedded in audio data
    if ((*flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC) != 0) {
    if ((*flags & (AUDIO_OUTPUT_FLAG_HW_AV_SYNC | AUDIO_OUTPUT_FLAG_MMAP_NOIRQ)) != 0) {
        return AUDIO_IO_HANDLE_NONE;
    }

+1 −0
Original line number Diff line number Diff line
@@ -628,6 +628,7 @@ private:
                audio_devices_t device,
                audio_session_t session,
                audio_stream_type_t stream,
                audio_io_handle_t originalOutput,
                const audio_config_t *config,
                audio_output_flags_t *flags);
        // internal method to return the input handle for the given device and format