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

Commit 3bcf8597 authored by Eric Laurent's avatar Eric Laurent
Browse files

audio flinger: improve device to device audio patches

Allow creation of audio patches between input and output
devices managed by the same audio HW module.

Change-Id: I4b83268a4d5c41f3d5905d7581202cf5193efd32
parent 322b4d25
Loading
Loading
Loading
Loading
+17 −21
Original line number Diff line number Diff line
@@ -200,26 +200,17 @@ status_t AudioFlinger::PatchPanel::createAudioPatch(const struct audio_patch *pa
                    status = BAD_VALUE;
                    goto exit;
                }
                // limit to connections between devices and input streams for HAL before 3.0
                if (patch->sinks[i].ext.mix.hw_module == srcModule &&
                        (audioHwDevice->version() < AUDIO_DEVICE_API_VERSION_3_0) &&
                        (patch->sinks[i].type != AUDIO_PORT_TYPE_MIX)) {
                    ALOGW("createAudioPatch() invalid sink type %d for device source",
                          patch->sinks[i].type);
                    status = BAD_VALUE;
                    goto exit;
                }
            }

            if (patch->sinks[0].ext.device.hw_module != srcModule) {
                // limit to device to device connection if not on same hw module
                if (patch->sinks[0].type != AUDIO_PORT_TYPE_DEVICE) {
                    ALOGW("createAudioPatch() invalid sink type for cross hw module");
                    status = INVALID_OPERATION;
                    goto exit;
                }
                // special case num sources == 2 -=> reuse an exiting output mix to connect to the
                // sink
            // manage patches requiring a software bridge
            // - Device to device AND
            //    - source HW module != destination HW module OR
            //    - audio HAL version < 3.0
            //    - special patch request with 2 sources (reuse one existing output mix)
            if ((patch->sinks[0].type == AUDIO_PORT_TYPE_DEVICE) &&
                    ((patch->sinks[0].ext.device.hw_module != srcModule) ||
                    (audioHwDevice->version() < AUDIO_DEVICE_API_VERSION_3_0) ||
                    (patch->num_sources == 2))) {
                if (patch->num_sources == 2) {
                    if (patch->sources[1].type != AUDIO_PORT_TYPE_MIX ||
                            patch->sinks[0].ext.device.hw_module !=
@@ -304,6 +295,11 @@ status_t AudioFlinger::PatchPanel::createAudioPatch(const struct audio_patch *pa
                                                               &halHandle);
                    }
                } else {
                    if (patch->sinks[0].type != AUDIO_PORT_TYPE_MIX) {
                        status = INVALID_OPERATION;
                        goto exit;
                    }

                    sp<ThreadBase> thread = audioflinger->checkRecordThread_l(
                                                                    patch->sinks[0].ext.mix.handle);
                    if (thread == 0) {
@@ -472,6 +468,7 @@ status_t AudioFlinger::PatchPanel::createPatchConnections(Patch *patch,
    // this track is given the same buffer as the PatchRecord buffer
    patch->mPatchTrack = new PlaybackThread::PatchTrack(
                                           patch->mPlaybackThread.get(),
                                           audioPatch->sources[1].ext.mix.usecase.stream,
                                           sampleRate,
                                           outChannelMask,
                                           format,
@@ -578,8 +575,8 @@ status_t AudioFlinger::PatchPanel::releaseAudioPatch(audio_patch_handle_t handle
                break;
            }

            if (patch->sinks[0].type == AUDIO_PORT_TYPE_DEVICE &&
                    patch->sinks[0].ext.device.hw_module != srcModule) {
            if (removedPatch->mRecordPatchHandle != AUDIO_PATCH_HANDLE_NONE ||
                    removedPatch->mPlaybackPatchHandle != AUDIO_PATCH_HANDLE_NONE) {
                clearPatchConnections(removedPatch);
                break;
            }
@@ -693,5 +690,4 @@ status_t AudioFlinger::PatchPanel::setAudioPortConfig(const struct audio_port_co
    return NO_ERROR;
}


} // namespace android
+1 −0
Original line number Diff line number Diff line
@@ -298,6 +298,7 @@ class PatchTrack : public Track, public PatchProxyBufferProvider {
public:

                        PatchTrack(PlaybackThread *playbackThread,
                                   audio_stream_type_t streamType,
                                   uint32_t sampleRate,
                                   audio_channel_mask_t channelMask,
                                   audio_format_t format,
+2 −1
Original line number Diff line number Diff line
@@ -1861,13 +1861,14 @@ void AudioFlinger::PlaybackThread::OutputTrack::clearBufferQueue()


AudioFlinger::PlaybackThread::PatchTrack::PatchTrack(PlaybackThread *playbackThread,
                                                     audio_stream_type_t streamType,
                                                     uint32_t sampleRate,
                                                     audio_channel_mask_t channelMask,
                                                     audio_format_t format,
                                                     size_t frameCount,
                                                     void *buffer,
                                                     IAudioFlinger::track_flags_t flags)
    :   Track(playbackThread, NULL, AUDIO_STREAM_PATCH,
    :   Track(playbackThread, NULL, streamType,
              sampleRate, format, channelMask, frameCount,
              buffer, 0, 0, getuid(), flags, TYPE_PATCH),
              mProxy(new ClientProxy(mCblk, mBuffer, frameCount, mFrameSize, true, true))
+9 −2
Original line number Diff line number Diff line
@@ -353,6 +353,7 @@ void AudioPolicyManager::updateCallRouting(audio_devices_t rxDevice, int delayMs
            ALOG_ASSERT(!outputDesc->isDuplicated(),
                        "updateCallRouting() RX device output is duplicated");
            outputDesc->toAudioPortConfig(&patch.sources[1]);
            patch.sources[1].ext.mix.usecase.stream = AUDIO_STREAM_PATCH;
            patch.num_sources = 2;
        }

@@ -395,6 +396,7 @@ void AudioPolicyManager::updateCallRouting(audio_devices_t rxDevice, int delayMs
            ALOG_ASSERT(!outputDesc->isDuplicated(),
                        "updateCallRouting() RX device output is duplicated");
            outputDesc->toAudioPortConfig(&patch.sources[1]);
            patch.sources[1].ext.mix.usecase.stream = AUDIO_STREAM_PATCH;
            patch.num_sources = 2;
        }

@@ -2184,8 +2186,12 @@ status_t AudioPolicyManager::createAudioPatch(const struct audio_patch *patch,
                }
                sinkDeviceDesc->toAudioPortConfig(&newPatch.sinks[i], &patch->sinks[i]);

                if (srcDeviceDesc->getModuleHandle() != sinkDeviceDesc->getModuleHandle()) {
                    // only one sink supported when connected devices across HW modules
                // create a software bridge in PatchPanel if:
                // - source and sink devices are on differnt HW modules OR
                // - audio HAL version is < 3.0
                if ((srcDeviceDesc->getModuleHandle() != sinkDeviceDesc->getModuleHandle()) ||
                        (srcDeviceDesc->mModule->mHalVersion < AUDIO_DEVICE_API_VERSION_3_0)) {
                    // support only one sink device for now to simplify output selection logic
                    if (patch->num_sinks > 1) {
                        return INVALID_OPERATION;
                    }
@@ -2202,6 +2208,7 @@ status_t AudioPolicyManager::createAudioPatch(const struct audio_patch *patch,
                            return INVALID_OPERATION;
                        }
                        outputDesc->toAudioPortConfig(&newPatch.sources[1], &patch->sources[0]);
                        newPatch.sources[1].ext.mix.usecase.stream = AUDIO_STREAM_PATCH;
                        newPatch.num_sources = 2;
                    }
                }