From 3bcf8597189c592713675ec58326ecbef0ac4ae9 Mon Sep 17 00:00:00 2001 From: Eric Laurent Date: Fri, 3 Apr 2015 12:13:24 -0700 Subject: 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 --- services/audioflinger/PatchPanel.cpp | 38 ++++++++++------------ services/audioflinger/PlaybackTracks.h | 1 + services/audioflinger/Tracks.cpp | 3 +- .../managerdefault/AudioPolicyManager.cpp | 11 +++++-- 4 files changed, 29 insertions(+), 24 deletions(-) (limited to 'services') diff --git a/services/audioflinger/PatchPanel.cpp b/services/audioflinger/PatchPanel.cpp index efbdcff..834947f 100644 --- a/services/audioflinger/PatchPanel.cpp +++ b/services/audioflinger/PatchPanel.cpp @@ -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 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 diff --git a/services/audioflinger/PlaybackTracks.h b/services/audioflinger/PlaybackTracks.h index 45df6a9..c51021b 100644 --- a/services/audioflinger/PlaybackTracks.h +++ b/services/audioflinger/PlaybackTracks.h @@ -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, diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp index dc9f249..5625661 100644 --- a/services/audioflinger/Tracks.cpp +++ b/services/audioflinger/Tracks.cpp @@ -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)) diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp index a7d9fd5..ffa689a 100644 --- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp +++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp @@ -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; } } -- cgit v1.1