PatchPanel.cpp revision a0169a073d88efefbfb35fa0ea8e94f7b31d7469
1951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent/* 2951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent** 3951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent** Copyright 2014, The Android Open Source Project 4951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent** 5951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent** Licensed under the Apache License, Version 2.0 (the "License"); 6951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent** you may not use this file except in compliance with the License. 7951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent** You may obtain a copy of the License at 8951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent** 9951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent** http://www.apache.org/licenses/LICENSE-2.0 10951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent** 11951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent** Unless required by applicable law or agreed to in writing, software 12951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent** distributed under the License is distributed on an "AS IS" BASIS, 13951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent** See the License for the specific language governing permissions and 15951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent** limitations under the License. 16951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent*/ 17951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent 18951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent 19951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent#define LOG_TAG "AudioFlinger::PatchPanel" 20951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent//#define LOG_NDEBUG 0 21951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent 22951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent#include "Configuration.h" 23951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent#include <utils/Log.h> 24951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent#include <audio_utils/primitives.h> 25951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent 26951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent#include "AudioFlinger.h" 27951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent#include "ServiceUtilities.h" 28951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent#include <media/AudioParameter.h> 29951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent 30951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent// ---------------------------------------------------------------------------- 31951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent 32951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent// Note: the following macro is used for extremely verbose logging message. In 33951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent// order to run with ALOG_ASSERT turned on, we need to have LOG_NDEBUG set to 34951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent// 0; but one side effect of this is to turn all LOGV's as well. Some messages 35951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent// are so verbose that we want to suppress them even when we have ALOG_ASSERT 36951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent// turned on. Do not uncomment the #def below unless you really know what you 37951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent// are doing and want to see all of the extremely verbose messages. 38951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent//#define VERY_VERY_VERBOSE_LOGGING 39951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent#ifdef VERY_VERY_VERBOSE_LOGGING 40951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent#define ALOGVV ALOGV 41951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent#else 42951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent#define ALOGVV(a...) do { } while(0) 43951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent#endif 44951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent 45951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurentnamespace android { 46951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent 47951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent/* List connected audio ports and their attributes */ 48951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurentstatus_t AudioFlinger::listAudioPorts(unsigned int *num_ports, 49951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent struct audio_port *ports) 50951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent{ 51951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent Mutex::Autolock _l(mLock); 52951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent if (mPatchPanel != 0) { 53951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent return mPatchPanel->listAudioPorts(num_ports, ports); 54951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } 55951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent return NO_INIT; 56951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent} 57951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent 58951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent/* Get supported attributes for a given audio port */ 59951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurentstatus_t AudioFlinger::getAudioPort(struct audio_port *port) 60951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent{ 61951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent Mutex::Autolock _l(mLock); 62951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent if (mPatchPanel != 0) { 63951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent return mPatchPanel->getAudioPort(port); 64951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } 65951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent return NO_INIT; 66951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent} 67951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent 68951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent 69951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent/* Connect a patch between several source and sink ports */ 70951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurentstatus_t AudioFlinger::createAudioPatch(const struct audio_patch *patch, 71951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent audio_patch_handle_t *handle) 72951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent{ 73951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent Mutex::Autolock _l(mLock); 74951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent if (mPatchPanel != 0) { 75951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent return mPatchPanel->createAudioPatch(patch, handle); 76951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } 77951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent return NO_INIT; 78951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent} 79951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent 80951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent/* Disconnect a patch */ 81951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurentstatus_t AudioFlinger::releaseAudioPatch(audio_patch_handle_t handle) 82951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent{ 83951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent Mutex::Autolock _l(mLock); 84951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent if (mPatchPanel != 0) { 85951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent return mPatchPanel->releaseAudioPatch(handle); 86951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } 87951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent return NO_INIT; 88951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent} 89951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent 90951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent 91951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent/* List connected audio ports and they attributes */ 92951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurentstatus_t AudioFlinger::listAudioPatches(unsigned int *num_patches, 93951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent struct audio_patch *patches) 94951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent{ 95951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent Mutex::Autolock _l(mLock); 96951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent if (mPatchPanel != 0) { 97951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent return mPatchPanel->listAudioPatches(num_patches, patches); 98951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } 99951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent return NO_INIT; 100951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent} 101951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent 102951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent/* Set audio port configuration */ 103951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurentstatus_t AudioFlinger::setAudioPortConfig(const struct audio_port_config *config) 104951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent{ 105951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent Mutex::Autolock _l(mLock); 106951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent if (mPatchPanel != 0) { 107951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent return mPatchPanel->setAudioPortConfig(config); 108951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } 109951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent return NO_INIT; 110951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent} 111951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent 112951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent 113951f455566775e5f01e67c5ee26863d7d19209d7Eric LaurentAudioFlinger::PatchPanel::PatchPanel(const sp<AudioFlinger>& audioFlinger) 114951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent : mAudioFlinger(audioFlinger) 115951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent{ 116951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent} 117951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent 118951f455566775e5f01e67c5ee26863d7d19209d7Eric LaurentAudioFlinger::PatchPanel::~PatchPanel() 119951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent{ 120951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent} 121951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent 122951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent/* List connected audio ports and their attributes */ 123951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurentstatus_t AudioFlinger::PatchPanel::listAudioPorts(unsigned int *num_ports __unused, 124951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent struct audio_port *ports __unused) 125951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent{ 126951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent ALOGV("listAudioPorts"); 127951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent return NO_ERROR; 128951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent} 129951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent 130951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent/* Get supported attributes for a given audio port */ 131951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurentstatus_t AudioFlinger::PatchPanel::getAudioPort(struct audio_port *port __unused) 132951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent{ 133951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent ALOGV("getAudioPort"); 134951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent return NO_ERROR; 135951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent} 136951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent 137951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent 138951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent/* Connect a patch between several source and sink ports */ 139951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurentstatus_t AudioFlinger::PatchPanel::createAudioPatch(const struct audio_patch *patch, 140951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent audio_patch_handle_t *handle) 141951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent{ 142951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent ALOGV("createAudioPatch() num_sources %d num_sinks %d handle %d", 143951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent patch->num_sources, patch->num_sinks, *handle); 144951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent status_t status = NO_ERROR; 145951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent audio_patch_handle_t halHandle = AUDIO_PATCH_HANDLE_NONE; 146951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent sp<AudioFlinger> audioflinger = mAudioFlinger.promote(); 147951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent if (audioflinger == 0) { 148951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent return NO_INIT; 149951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } 15083b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent 151951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent if (handle == NULL || patch == NULL) { 152951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent return BAD_VALUE; 153951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } 154874c4287a4e49c59ac88767751dce00fcd3edb73Eric Laurent if (patch->num_sources == 0 || patch->num_sources > AUDIO_PATCH_PORTS_MAX || 155951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent patch->num_sinks == 0 || patch->num_sinks > AUDIO_PATCH_PORTS_MAX) { 156951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent return BAD_VALUE; 157951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } 158874c4287a4e49c59ac88767751dce00fcd3edb73Eric Laurent // limit number of sources to 1 for now or 2 sources for special cross hw module case. 159874c4287a4e49c59ac88767751dce00fcd3edb73Eric Laurent // only the audio policy manager can request a patch creation with 2 sources. 160874c4287a4e49c59ac88767751dce00fcd3edb73Eric Laurent if (patch->num_sources > 2) { 161874c4287a4e49c59ac88767751dce00fcd3edb73Eric Laurent return INVALID_OPERATION; 162874c4287a4e49c59ac88767751dce00fcd3edb73Eric Laurent } 163951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent 16483b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent if (*handle != AUDIO_PATCH_HANDLE_NONE) { 16583b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent for (size_t index = 0; *handle != 0 && index < mPatches.size(); index++) { 16683b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent if (*handle == mPatches[index]->mHandle) { 16783b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent ALOGV("createAudioPatch() removing patch handle %d", *handle); 16883b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent halHandle = mPatches[index]->mHalHandle; 169d8cd47792bac11a44096ef8233bb5268a6674becsoon Patch *removedPatch = mPatches[index]; 17083b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent mPatches.removeAt(index); 171d8cd47792bac11a44096ef8233bb5268a6674becsoon delete removedPatch; 17283b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent break; 17383b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent } 174951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } 175951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } 176951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent 17783b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent Patch *newPatch = new Patch(patch); 17883b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent 179951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent switch (patch->sources[0].type) { 180951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent case AUDIO_PORT_TYPE_DEVICE: { 181874c4287a4e49c59ac88767751dce00fcd3edb73Eric Laurent audio_module_handle_t srcModule = patch->sources[0].ext.device.hw_module; 182874c4287a4e49c59ac88767751dce00fcd3edb73Eric Laurent ssize_t index = audioflinger->mAudioHwDevs.indexOfKey(srcModule); 183951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent if (index < 0) { 184874c4287a4e49c59ac88767751dce00fcd3edb73Eric Laurent ALOGW("createAudioPatch() bad src hw module %d", srcModule); 18583b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent status = BAD_VALUE; 18683b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent goto exit; 187951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } 1886a94d69dc4f32abb53c466a96f905bb199be6417Eric Laurent AudioHwDevice *audioHwDevice = audioflinger->mAudioHwDevs.valueAt(index); 189951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent for (unsigned int i = 0; i < patch->num_sinks; i++) { 190874c4287a4e49c59ac88767751dce00fcd3edb73Eric Laurent // support only one sink if connection to a mix or across HW modules 191874c4287a4e49c59ac88767751dce00fcd3edb73Eric Laurent if ((patch->sinks[i].type == AUDIO_PORT_TYPE_MIX || 192874c4287a4e49c59ac88767751dce00fcd3edb73Eric Laurent patch->sinks[i].ext.mix.hw_module != srcModule) && 193874c4287a4e49c59ac88767751dce00fcd3edb73Eric Laurent patch->num_sinks > 1) { 194874c4287a4e49c59ac88767751dce00fcd3edb73Eric Laurent status = INVALID_OPERATION; 195874c4287a4e49c59ac88767751dce00fcd3edb73Eric Laurent goto exit; 196874c4287a4e49c59ac88767751dce00fcd3edb73Eric Laurent } 1976a94d69dc4f32abb53c466a96f905bb199be6417Eric Laurent // reject connection to different sink types 1986a94d69dc4f32abb53c466a96f905bb199be6417Eric Laurent if (patch->sinks[i].type != patch->sinks[0].type) { 1996a94d69dc4f32abb53c466a96f905bb199be6417Eric Laurent ALOGW("createAudioPatch() different sink types in same patch not supported"); 20083b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent status = BAD_VALUE; 20183b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent goto exit; 202951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } 203951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } 204951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent 2053bcf8597189c592713675ec58326ecbef0ac4ae9Eric Laurent // manage patches requiring a software bridge 2063bcf8597189c592713675ec58326ecbef0ac4ae9Eric Laurent // - Device to device AND 2073bcf8597189c592713675ec58326ecbef0ac4ae9Eric Laurent // - source HW module != destination HW module OR 2083bcf8597189c592713675ec58326ecbef0ac4ae9Eric Laurent // - audio HAL version < 3.0 2093bcf8597189c592713675ec58326ecbef0ac4ae9Eric Laurent // - special patch request with 2 sources (reuse one existing output mix) 2103bcf8597189c592713675ec58326ecbef0ac4ae9Eric Laurent if ((patch->sinks[0].type == AUDIO_PORT_TYPE_DEVICE) && 2113bcf8597189c592713675ec58326ecbef0ac4ae9Eric Laurent ((patch->sinks[0].ext.device.hw_module != srcModule) || 2123bcf8597189c592713675ec58326ecbef0ac4ae9Eric Laurent (audioHwDevice->version() < AUDIO_DEVICE_API_VERSION_3_0) || 2133bcf8597189c592713675ec58326ecbef0ac4ae9Eric Laurent (patch->num_sources == 2))) { 21483b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent if (patch->num_sources == 2) { 21583b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent if (patch->sources[1].type != AUDIO_PORT_TYPE_MIX || 21683b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent patch->sinks[0].ext.device.hw_module != 21783b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent patch->sources[1].ext.mix.hw_module) { 21883b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent ALOGW("createAudioPatch() invalid source combination"); 21983b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent status = INVALID_OPERATION; 22083b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent goto exit; 22183b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent } 22283b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent 22383b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent sp<ThreadBase> thread = 22483b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent audioflinger->checkPlaybackThread_l(patch->sources[1].ext.mix.handle); 22583b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent newPatch->mPlaybackThread = (MixerThread *)thread.get(); 226951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent if (thread == 0) { 22783b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent ALOGW("createAudioPatch() cannot get playback thread"); 22883b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent status = INVALID_OPERATION; 22983b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent goto exit; 230951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } 231951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } else { 232cf2c0210c8afbe7d0661ccbbae3835b5ce73c0bfEric Laurent audio_config_t config = AUDIO_CONFIG_INITIALIZER; 233cf2c0210c8afbe7d0661ccbbae3835b5ce73c0bfEric Laurent audio_devices_t device = patch->sinks[0].ext.device.type; 234cf2c0210c8afbe7d0661ccbbae3835b5ce73c0bfEric Laurent String8 address = String8(patch->sinks[0].ext.device.address); 235cf2c0210c8afbe7d0661ccbbae3835b5ce73c0bfEric Laurent audio_io_handle_t output = AUDIO_IO_HANDLE_NONE; 23683b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent newPatch->mPlaybackThread = audioflinger->openOutput_l( 23783b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent patch->sinks[0].ext.device.hw_module, 238cf2c0210c8afbe7d0661ccbbae3835b5ce73c0bfEric Laurent &output, 23983b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent &config, 240cf2c0210c8afbe7d0661ccbbae3835b5ce73c0bfEric Laurent device, 241cf2c0210c8afbe7d0661ccbbae3835b5ce73c0bfEric Laurent address, 24283b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent AUDIO_OUTPUT_FLAG_NONE); 24383b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent ALOGV("audioflinger->openOutput_l() returned %p", 24483b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent newPatch->mPlaybackThread.get()); 24583b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent if (newPatch->mPlaybackThread == 0) { 24683b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent status = NO_MEMORY; 24783b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent goto exit; 24883b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent } 24983b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent } 25083b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent uint32_t channelCount = newPatch->mPlaybackThread->channelCount(); 25183b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent audio_devices_t device = patch->sources[0].ext.device.type; 252cf2c0210c8afbe7d0661ccbbae3835b5ce73c0bfEric Laurent String8 address = String8(patch->sources[0].ext.device.address); 253cf2c0210c8afbe7d0661ccbbae3835b5ce73c0bfEric Laurent audio_config_t config = AUDIO_CONFIG_INITIALIZER; 25483b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent audio_channel_mask_t inChannelMask = audio_channel_in_mask_from_count(channelCount); 25583b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent config.sample_rate = newPatch->mPlaybackThread->sampleRate(); 25683b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent config.channel_mask = inChannelMask; 25783b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent config.format = newPatch->mPlaybackThread->format(); 258cf2c0210c8afbe7d0661ccbbae3835b5ce73c0bfEric Laurent audio_io_handle_t input = AUDIO_IO_HANDLE_NONE; 259874c4287a4e49c59ac88767751dce00fcd3edb73Eric Laurent newPatch->mRecordThread = audioflinger->openInput_l(srcModule, 260cf2c0210c8afbe7d0661ccbbae3835b5ce73c0bfEric Laurent &input, 26183b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent &config, 262cf2c0210c8afbe7d0661ccbbae3835b5ce73c0bfEric Laurent device, 263cf2c0210c8afbe7d0661ccbbae3835b5ce73c0bfEric Laurent address, 264cf2c0210c8afbe7d0661ccbbae3835b5ce73c0bfEric Laurent AUDIO_SOURCE_MIC, 26583b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent AUDIO_INPUT_FLAG_NONE); 26683b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent ALOGV("audioflinger->openInput_l() returned %p inChannelMask %08x", 26783b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent newPatch->mRecordThread.get(), inChannelMask); 26883b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent if (newPatch->mRecordThread == 0) { 26983b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent status = NO_MEMORY; 27083b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent goto exit; 27183b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent } 27283b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent status = createPatchConnections(newPatch, patch); 27383b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent if (status != NO_ERROR) { 27483b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent goto exit; 275951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } 276951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } else { 277054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent if (patch->sinks[0].type == AUDIO_PORT_TYPE_MIX) { 27883b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent sp<ThreadBase> thread = audioflinger->checkRecordThread_l( 279054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent patch->sinks[0].ext.mix.handle); 28083b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent if (thread == 0) { 28183b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent ALOGW("createAudioPatch() bad capture I/O handle %d", 282054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent patch->sinks[0].ext.mix.handle); 28383b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent status = BAD_VALUE; 28483b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent goto exit; 28583b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent } 286054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent status = thread->sendCreateAudioPatchConfigEvent(patch, &halHandle); 287054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent } else { 288054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent if (audioHwDevice->version() < AUDIO_DEVICE_API_VERSION_3_0) { 289054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent status = INVALID_OPERATION; 290054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent goto exit; 291cf2c0210c8afbe7d0661ccbbae3835b5ce73c0bfEric Laurent } 292054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent 293054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent audio_hw_device_t *hwDevice = audioHwDevice->hwDevice(); 294054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent status = hwDevice->create_audio_patch(hwDevice, 295054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent patch->num_sources, 296054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent patch->sources, 297054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent patch->num_sinks, 298054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent patch->sinks, 299054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent &halHandle); 300951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } 301951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } 302951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } break; 303951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent case AUDIO_PORT_TYPE_MIX: { 304874c4287a4e49c59ac88767751dce00fcd3edb73Eric Laurent audio_module_handle_t srcModule = patch->sources[0].ext.mix.hw_module; 305874c4287a4e49c59ac88767751dce00fcd3edb73Eric Laurent ssize_t index = audioflinger->mAudioHwDevs.indexOfKey(srcModule); 306951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent if (index < 0) { 307874c4287a4e49c59ac88767751dce00fcd3edb73Eric Laurent ALOGW("createAudioPatch() bad src hw module %d", srcModule); 30883b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent status = BAD_VALUE; 30983b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent goto exit; 310951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } 311951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent // limit to connections between devices and output streams 312054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent audio_devices_t type = AUDIO_DEVICE_NONE; 313951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent for (unsigned int i = 0; i < patch->num_sinks; i++) { 314951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent if (patch->sinks[i].type != AUDIO_PORT_TYPE_DEVICE) { 31583b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent ALOGW("createAudioPatch() invalid sink type %d for mix source", 316951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent patch->sinks[i].type); 31783b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent status = BAD_VALUE; 31883b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent goto exit; 319951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } 320951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent // limit to connections between sinks and sources on same HW module 321874c4287a4e49c59ac88767751dce00fcd3edb73Eric Laurent if (patch->sinks[i].ext.device.hw_module != srcModule) { 32283b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent status = BAD_VALUE; 32383b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent goto exit; 324951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } 325054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent type |= patch->sinks[i].ext.device.type; 326951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } 327951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent sp<ThreadBase> thread = 328951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent audioflinger->checkPlaybackThread_l(patch->sources[0].ext.mix.handle); 329951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent if (thread == 0) { 330951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent ALOGW("createAudioPatch() bad playback I/O handle %d", 331951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent patch->sources[0].ext.mix.handle); 33283b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent status = BAD_VALUE; 33383b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent goto exit; 334951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } 335054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent if (thread == audioflinger->primaryPlaybackThread_l()) { 336054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent AudioParameter param = AudioParameter(); 337cf2c0210c8afbe7d0661ccbbae3835b5ce73c0bfEric Laurent param.addInt(String8(AUDIO_PARAMETER_STREAM_ROUTING), (int)type); 338054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent 339054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent audioflinger->broacastParametersToRecordThreads_l(param.toString()); 340951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } 341951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent 342054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent status = thread->sendCreateAudioPatchConfigEvent(patch, &halHandle); 343951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } break; 344951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent default: 34583b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent status = BAD_VALUE; 34683b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent goto exit; 347951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } 34883b8808faad1e91690c64d7007348be8d9ebde73Eric Laurentexit: 349951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent ALOGV("createAudioPatch() status %d", status); 350951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent if (status == NO_ERROR) { 351951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent *handle = audioflinger->nextUniqueId(); 352951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent newPatch->mHandle = *handle; 353951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent newPatch->mHalHandle = halHandle; 354951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent mPatches.add(newPatch); 355951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent ALOGV("createAudioPatch() added new patch handle %d halHandle %d", *handle, halHandle); 35683b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent } else { 35783b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent clearPatchConnections(newPatch); 35883b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent delete newPatch; 35983b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent } 36083b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent return status; 36183b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent} 36283b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent 36383b8808faad1e91690c64d7007348be8d9ebde73Eric Laurentstatus_t AudioFlinger::PatchPanel::createPatchConnections(Patch *patch, 36483b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent const struct audio_patch *audioPatch) 36583b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent{ 36683b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent // create patch from source device to record thread input 36783b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent struct audio_patch subPatch; 36883b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent subPatch.num_sources = 1; 36983b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent subPatch.sources[0] = audioPatch->sources[0]; 37083b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent subPatch.num_sinks = 1; 37183b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent 37283b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent patch->mRecordThread->getAudioPortConfig(&subPatch.sinks[0]); 37383b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent subPatch.sinks[0].ext.mix.usecase.source = AUDIO_SOURCE_MIC; 37483b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent 37583b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent status_t status = createAudioPatch(&subPatch, &patch->mRecordPatchHandle); 37683b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent if (status != NO_ERROR) { 37783b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent patch->mRecordPatchHandle = AUDIO_PATCH_HANDLE_NONE; 37883b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent return status; 37983b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent } 38083b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent 38183b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent // create patch from playback thread output to sink device 38283b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent patch->mPlaybackThread->getAudioPortConfig(&subPatch.sources[0]); 38383b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent subPatch.sinks[0] = audioPatch->sinks[0]; 38483b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent status = createAudioPatch(&subPatch, &patch->mPlaybackPatchHandle); 38583b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent if (status != NO_ERROR) { 38683b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent patch->mPlaybackPatchHandle = AUDIO_PATCH_HANDLE_NONE; 38783b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent return status; 38883b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent } 38983b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent 39083b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent // use a pseudo LCM between input and output framecount 39183b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent size_t playbackFrameCount = patch->mPlaybackThread->frameCount(); 39283b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent int playbackShift = __builtin_ctz(playbackFrameCount); 39383b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent size_t recordFramecount = patch->mRecordThread->frameCount(); 39483b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent int shift = __builtin_ctz(recordFramecount); 39583b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent if (playbackShift < shift) { 39683b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent shift = playbackShift; 39783b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent } 39883b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent size_t frameCount = (playbackFrameCount * recordFramecount) >> shift; 39983b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent ALOGV("createPatchConnections() playframeCount %d recordFramecount %d frameCount %d ", 40083b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent playbackFrameCount, recordFramecount, frameCount); 40183b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent 40283b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent // create a special record track to capture from record thread 40383b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent uint32_t channelCount = patch->mPlaybackThread->channelCount(); 40483b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent audio_channel_mask_t inChannelMask = audio_channel_in_mask_from_count(channelCount); 40583b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent audio_channel_mask_t outChannelMask = patch->mPlaybackThread->channelMask(); 40683b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent uint32_t sampleRate = patch->mPlaybackThread->sampleRate(); 40783b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent audio_format_t format = patch->mPlaybackThread->format(); 40883b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent 40983b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent patch->mPatchRecord = new RecordThread::PatchRecord( 41083b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent patch->mRecordThread.get(), 41183b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent sampleRate, 41283b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent inChannelMask, 41383b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent format, 41483b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent frameCount, 41583b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent NULL, 41683b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent IAudioFlinger::TRACK_DEFAULT); 41783b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent if (patch->mPatchRecord == 0) { 41883b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent return NO_MEMORY; 41983b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent } 42083b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent status = patch->mPatchRecord->initCheck(); 42183b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent if (status != NO_ERROR) { 42283b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent return status; 423951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } 42483b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent patch->mRecordThread->addPatchRecord(patch->mPatchRecord); 42583b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent 42683b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent // create a special playback track to render to playback thread. 42783b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent // this track is given the same buffer as the PatchRecord buffer 42883b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent patch->mPatchTrack = new PlaybackThread::PatchTrack( 42983b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent patch->mPlaybackThread.get(), 4303bcf8597189c592713675ec58326ecbef0ac4ae9Eric Laurent audioPatch->sources[1].ext.mix.usecase.stream, 43183b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent sampleRate, 43283b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent outChannelMask, 43383b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent format, 43483b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent frameCount, 43583b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent patch->mPatchRecord->buffer(), 43683b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent IAudioFlinger::TRACK_DEFAULT); 43783b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent if (patch->mPatchTrack == 0) { 43883b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent return NO_MEMORY; 43983b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent } 44083b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent status = patch->mPatchTrack->initCheck(); 44183b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent if (status != NO_ERROR) { 44283b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent return status; 44383b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent } 44483b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent patch->mPlaybackThread->addPatchTrack(patch->mPatchTrack); 44583b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent 44683b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent // tie playback and record tracks together 44783b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent patch->mPatchRecord->setPeerProxy(patch->mPatchTrack.get()); 44883b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent patch->mPatchTrack->setPeerProxy(patch->mPatchRecord.get()); 44983b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent 45083b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent // start capture and playback 45183b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent patch->mPatchRecord->start(AudioSystem::SYNC_EVENT_NONE, 0); 45283b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent patch->mPatchTrack->start(); 45383b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent 454951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent return status; 455951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent} 456951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent 45783b8808faad1e91690c64d7007348be8d9ebde73Eric Laurentvoid AudioFlinger::PatchPanel::clearPatchConnections(Patch *patch) 45883b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent{ 45983b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent sp<AudioFlinger> audioflinger = mAudioFlinger.promote(); 46083b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent if (audioflinger == 0) { 46183b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent return; 46283b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent } 46383b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent 46483b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent ALOGV("clearPatchConnections() patch->mRecordPatchHandle %d patch->mPlaybackPatchHandle %d", 46583b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent patch->mRecordPatchHandle, patch->mPlaybackPatchHandle); 46683b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent 46783b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent if (patch->mPatchRecord != 0) { 46883b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent patch->mPatchRecord->stop(); 46983b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent } 47083b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent if (patch->mPatchTrack != 0) { 47183b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent patch->mPatchTrack->stop(); 47283b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent } 47383b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent if (patch->mRecordPatchHandle != AUDIO_PATCH_HANDLE_NONE) { 47483b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent releaseAudioPatch(patch->mRecordPatchHandle); 47583b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent patch->mRecordPatchHandle = AUDIO_PATCH_HANDLE_NONE; 47683b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent } 47783b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent if (patch->mPlaybackPatchHandle != AUDIO_PATCH_HANDLE_NONE) { 47883b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent releaseAudioPatch(patch->mPlaybackPatchHandle); 47983b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent patch->mPlaybackPatchHandle = AUDIO_PATCH_HANDLE_NONE; 48083b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent } 48183b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent if (patch->mRecordThread != 0) { 48283b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent if (patch->mPatchRecord != 0) { 48383b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent patch->mRecordThread->deletePatchRecord(patch->mPatchRecord); 48483b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent } 48583b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent audioflinger->closeInputInternal_l(patch->mRecordThread); 48683b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent } 48783b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent if (patch->mPlaybackThread != 0) { 48883b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent if (patch->mPatchTrack != 0) { 48983b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent patch->mPlaybackThread->deletePatchTrack(patch->mPatchTrack); 49083b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent } 49183b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent // if num sources == 2 we are reusing an existing playback thread so we do not close it 49283b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent if (patch->mAudioPatch.num_sources != 2) { 49383b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent audioflinger->closeOutputInternal_l(patch->mPlaybackThread); 49483b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent } 495a0169a073d88efefbfb35fa0ea8e94f7b31d7469Eric Laurent } 496a0169a073d88efefbfb35fa0ea8e94f7b31d7469Eric Laurent if (patch->mRecordThread != 0) { 497a0169a073d88efefbfb35fa0ea8e94f7b31d7469Eric Laurent if (patch->mPatchRecord != 0) { 498a0169a073d88efefbfb35fa0ea8e94f7b31d7469Eric Laurent patch->mPatchRecord.clear(); 499a0169a073d88efefbfb35fa0ea8e94f7b31d7469Eric Laurent } 500a0169a073d88efefbfb35fa0ea8e94f7b31d7469Eric Laurent patch->mRecordThread.clear(); 501a0169a073d88efefbfb35fa0ea8e94f7b31d7469Eric Laurent } 502a0169a073d88efefbfb35fa0ea8e94f7b31d7469Eric Laurent if (patch->mPlaybackThread != 0) { 503a0169a073d88efefbfb35fa0ea8e94f7b31d7469Eric Laurent if (patch->mPatchTrack != 0) { 504a0169a073d88efefbfb35fa0ea8e94f7b31d7469Eric Laurent patch->mPatchTrack.clear(); 505a0169a073d88efefbfb35fa0ea8e94f7b31d7469Eric Laurent } 50683b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent patch->mPlaybackThread.clear(); 50783b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent } 508a0169a073d88efefbfb35fa0ea8e94f7b31d7469Eric Laurent 50983b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent} 51083b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent 511951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent/* Disconnect a patch */ 512951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurentstatus_t AudioFlinger::PatchPanel::releaseAudioPatch(audio_patch_handle_t handle) 513951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent{ 514951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent ALOGV("releaseAudioPatch handle %d", handle); 515951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent status_t status = NO_ERROR; 516951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent size_t index; 517951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent 518951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent sp<AudioFlinger> audioflinger = mAudioFlinger.promote(); 519951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent if (audioflinger == 0) { 520951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent return NO_INIT; 521951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } 522951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent 523951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent for (index = 0; index < mPatches.size(); index++) { 524951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent if (handle == mPatches[index]->mHandle) { 525951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent break; 526951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } 527951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } 528951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent if (index == mPatches.size()) { 529951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent return BAD_VALUE; 530951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } 53183b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent Patch *removedPatch = mPatches[index]; 53283b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent mPatches.removeAt(index); 533951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent 53483b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent struct audio_patch *patch = &removedPatch->mAudioPatch; 535951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent 536951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent switch (patch->sources[0].type) { 537951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent case AUDIO_PORT_TYPE_DEVICE: { 538874c4287a4e49c59ac88767751dce00fcd3edb73Eric Laurent audio_module_handle_t srcModule = patch->sources[0].ext.device.hw_module; 539874c4287a4e49c59ac88767751dce00fcd3edb73Eric Laurent ssize_t index = audioflinger->mAudioHwDevs.indexOfKey(srcModule); 540951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent if (index < 0) { 541874c4287a4e49c59ac88767751dce00fcd3edb73Eric Laurent ALOGW("releaseAudioPatch() bad src hw module %d", srcModule); 542951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent status = BAD_VALUE; 543951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent break; 544951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } 54583b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent 5463bcf8597189c592713675ec58326ecbef0ac4ae9Eric Laurent if (removedPatch->mRecordPatchHandle != AUDIO_PATCH_HANDLE_NONE || 5473bcf8597189c592713675ec58326ecbef0ac4ae9Eric Laurent removedPatch->mPlaybackPatchHandle != AUDIO_PATCH_HANDLE_NONE) { 54883b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent clearPatchConnections(removedPatch); 54983b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent break; 55083b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent } 55183b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent 552054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent if (patch->sinks[0].type == AUDIO_PORT_TYPE_MIX) { 553951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent sp<ThreadBase> thread = audioflinger->checkRecordThread_l( 554054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent patch->sinks[0].ext.mix.handle); 555951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent if (thread == 0) { 556951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent ALOGW("releaseAudioPatch() bad capture I/O handle %d", 557054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent patch->sinks[0].ext.mix.handle); 558951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent status = BAD_VALUE; 559951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent break; 560951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } 561054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent status = thread->sendReleaseAudioPatchConfigEvent(removedPatch->mHalHandle); 562054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent } else { 563054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent AudioHwDevice *audioHwDevice = audioflinger->mAudioHwDevs.valueAt(index); 564054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent if (audioHwDevice->version() < AUDIO_DEVICE_API_VERSION_3_0) { 565054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent status = INVALID_OPERATION; 566054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent break; 567054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent } 568054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent audio_hw_device_t *hwDevice = audioHwDevice->hwDevice(); 569054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent status = hwDevice->release_audio_patch(hwDevice, removedPatch->mHalHandle); 570951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } 571951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } break; 572951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent case AUDIO_PORT_TYPE_MIX: { 573874c4287a4e49c59ac88767751dce00fcd3edb73Eric Laurent audio_module_handle_t srcModule = patch->sources[0].ext.mix.hw_module; 574874c4287a4e49c59ac88767751dce00fcd3edb73Eric Laurent ssize_t index = audioflinger->mAudioHwDevs.indexOfKey(srcModule); 575951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent if (index < 0) { 576874c4287a4e49c59ac88767751dce00fcd3edb73Eric Laurent ALOGW("releaseAudioPatch() bad src hw module %d", srcModule); 577951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent status = BAD_VALUE; 578951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent break; 579951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } 580951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent sp<ThreadBase> thread = 581951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent audioflinger->checkPlaybackThread_l(patch->sources[0].ext.mix.handle); 582951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent if (thread == 0) { 583951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent ALOGW("releaseAudioPatch() bad playback I/O handle %d", 584951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent patch->sources[0].ext.mix.handle); 585951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent status = BAD_VALUE; 586951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent break; 587951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } 588054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent status = thread->sendReleaseAudioPatchConfigEvent(removedPatch->mHalHandle); 589951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } break; 590951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent default: 591951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent status = BAD_VALUE; 592951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent break; 593951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } 594951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent 59583b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent delete removedPatch; 596951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent return status; 597951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent} 598951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent 599951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent 600951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent/* List connected audio ports and they attributes */ 601951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurentstatus_t AudioFlinger::PatchPanel::listAudioPatches(unsigned int *num_patches __unused, 602951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent struct audio_patch *patches __unused) 603951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent{ 604951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent ALOGV("listAudioPatches"); 605951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent return NO_ERROR; 606951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent} 607951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent 608951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent/* Set audio port configuration */ 609e1715a465a29db625da9d0ea365edf371e39e201Eric Laurentstatus_t AudioFlinger::PatchPanel::setAudioPortConfig(const struct audio_port_config *config) 610951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent{ 611951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent ALOGV("setAudioPortConfig"); 612e1715a465a29db625da9d0ea365edf371e39e201Eric Laurent status_t status = NO_ERROR; 613e1715a465a29db625da9d0ea365edf371e39e201Eric Laurent 614e1715a465a29db625da9d0ea365edf371e39e201Eric Laurent sp<AudioFlinger> audioflinger = mAudioFlinger.promote(); 615e1715a465a29db625da9d0ea365edf371e39e201Eric Laurent if (audioflinger == 0) { 616e1715a465a29db625da9d0ea365edf371e39e201Eric Laurent return NO_INIT; 617e1715a465a29db625da9d0ea365edf371e39e201Eric Laurent } 618e1715a465a29db625da9d0ea365edf371e39e201Eric Laurent 619e1715a465a29db625da9d0ea365edf371e39e201Eric Laurent audio_module_handle_t module; 620e1715a465a29db625da9d0ea365edf371e39e201Eric Laurent if (config->type == AUDIO_PORT_TYPE_DEVICE) { 621e1715a465a29db625da9d0ea365edf371e39e201Eric Laurent module = config->ext.device.hw_module; 622e1715a465a29db625da9d0ea365edf371e39e201Eric Laurent } else { 623e1715a465a29db625da9d0ea365edf371e39e201Eric Laurent module = config->ext.mix.hw_module; 624e1715a465a29db625da9d0ea365edf371e39e201Eric Laurent } 625e1715a465a29db625da9d0ea365edf371e39e201Eric Laurent 626e1715a465a29db625da9d0ea365edf371e39e201Eric Laurent ssize_t index = audioflinger->mAudioHwDevs.indexOfKey(module); 627e1715a465a29db625da9d0ea365edf371e39e201Eric Laurent if (index < 0) { 628e1715a465a29db625da9d0ea365edf371e39e201Eric Laurent ALOGW("setAudioPortConfig() bad hw module %d", module); 629e1715a465a29db625da9d0ea365edf371e39e201Eric Laurent return BAD_VALUE; 630e1715a465a29db625da9d0ea365edf371e39e201Eric Laurent } 631e1715a465a29db625da9d0ea365edf371e39e201Eric Laurent 632e1715a465a29db625da9d0ea365edf371e39e201Eric Laurent AudioHwDevice *audioHwDevice = audioflinger->mAudioHwDevs.valueAt(index); 633e1715a465a29db625da9d0ea365edf371e39e201Eric Laurent if (audioHwDevice->version() >= AUDIO_DEVICE_API_VERSION_3_0) { 634e1715a465a29db625da9d0ea365edf371e39e201Eric Laurent audio_hw_device_t *hwDevice = audioHwDevice->hwDevice(); 635e1715a465a29db625da9d0ea365edf371e39e201Eric Laurent return hwDevice->set_audio_port_config(hwDevice, config); 636e1715a465a29db625da9d0ea365edf371e39e201Eric Laurent } else { 637e1715a465a29db625da9d0ea365edf371e39e201Eric Laurent return INVALID_OPERATION; 638e1715a465a29db625da9d0ea365edf371e39e201Eric Laurent } 639951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent return NO_ERROR; 640951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent} 641951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent 64263238efb0d674758902918e3cdaac322126484b7Glenn Kasten} // namespace android 643