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 status_t status = NO_ERROR; 143951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent audio_patch_handle_t halHandle = AUDIO_PATCH_HANDLE_NONE; 144951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent sp<AudioFlinger> audioflinger = mAudioFlinger.promote(); 145f27ce4051c81a90f8f937a1b381e9e6ffa2bfa6bGreg Kaiser if (handle == NULL || patch == NULL) { 146f27ce4051c81a90f8f937a1b381e9e6ffa2bfa6bGreg Kaiser return BAD_VALUE; 147f27ce4051c81a90f8f937a1b381e9e6ffa2bfa6bGreg Kaiser } 148f27ce4051c81a90f8f937a1b381e9e6ffa2bfa6bGreg Kaiser ALOGV("createAudioPatch() num_sources %d num_sinks %d handle %d", 149f27ce4051c81a90f8f937a1b381e9e6ffa2bfa6bGreg Kaiser patch->num_sources, patch->num_sinks, *handle); 150951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent if (audioflinger == 0) { 151951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent return NO_INIT; 152951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } 15383b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent 154874c4287a4e49c59ac88767751dce00fcd3edb73Eric Laurent if (patch->num_sources == 0 || patch->num_sources > AUDIO_PATCH_PORTS_MAX || 155d60560af7cb559762593161c8202459cc01fb0f5Eric Laurent (patch->num_sinks == 0 && patch->num_sources != 2) || 156d60560af7cb559762593161c8202459cc01fb0f5Eric Laurent patch->num_sinks > AUDIO_PATCH_PORTS_MAX) { 157951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent return BAD_VALUE; 158951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } 159874c4287a4e49c59ac88767751dce00fcd3edb73Eric Laurent // limit number of sources to 1 for now or 2 sources for special cross hw module case. 160874c4287a4e49c59ac88767751dce00fcd3edb73Eric Laurent // only the audio policy manager can request a patch creation with 2 sources. 161874c4287a4e49c59ac88767751dce00fcd3edb73Eric Laurent if (patch->num_sources > 2) { 162874c4287a4e49c59ac88767751dce00fcd3edb73Eric Laurent return INVALID_OPERATION; 163874c4287a4e49c59ac88767751dce00fcd3edb73Eric Laurent } 164951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent 16583b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent if (*handle != AUDIO_PATCH_HANDLE_NONE) { 16683b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent for (size_t index = 0; *handle != 0 && index < mPatches.size(); index++) { 16783b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent if (*handle == mPatches[index]->mHandle) { 16883b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent ALOGV("createAudioPatch() removing patch handle %d", *handle); 16983b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent halHandle = mPatches[index]->mHalHandle; 170d8cd47792bac11a44096ef8233bb5268a6674becsoon Patch *removedPatch = mPatches[index]; 171b997d3a3d61a86dc9525860e863c7b690356d405Eric Laurent // free resources owned by the removed patch if applicable 172b997d3a3d61a86dc9525860e863c7b690356d405Eric Laurent // 1) if a software patch is present, release the playback and capture threads and 173b997d3a3d61a86dc9525860e863c7b690356d405Eric Laurent // tracks created. This will also release the corresponding audio HAL patches 1740666cc5b6b430cc5a815dab0bcba3dd73da8061aEric Laurent if ((removedPatch->mRecordPatchHandle 1750666cc5b6b430cc5a815dab0bcba3dd73da8061aEric Laurent != AUDIO_PATCH_HANDLE_NONE) || 1760666cc5b6b430cc5a815dab0bcba3dd73da8061aEric Laurent (removedPatch->mPlaybackPatchHandle != 1770666cc5b6b430cc5a815dab0bcba3dd73da8061aEric Laurent AUDIO_PATCH_HANDLE_NONE)) { 1780666cc5b6b430cc5a815dab0bcba3dd73da8061aEric Laurent clearPatchConnections(removedPatch); 1790666cc5b6b430cc5a815dab0bcba3dd73da8061aEric Laurent } 180b997d3a3d61a86dc9525860e863c7b690356d405Eric Laurent // 2) if the new patch and old patch source or sink are devices from different 181b997d3a3d61a86dc9525860e863c7b690356d405Eric Laurent // hw modules, clear the audio HAL patches now because they will not be updated 182b997d3a3d61a86dc9525860e863c7b690356d405Eric Laurent // by call to create_audio_patch() below which will happen on a different HW module 183b997d3a3d61a86dc9525860e863c7b690356d405Eric Laurent if (halHandle != AUDIO_PATCH_HANDLE_NONE) { 184b997d3a3d61a86dc9525860e863c7b690356d405Eric Laurent audio_module_handle_t hwModule = AUDIO_MODULE_HANDLE_NONE; 185b997d3a3d61a86dc9525860e863c7b690356d405Eric Laurent if ((removedPatch->mAudioPatch.sources[0].type == AUDIO_PORT_TYPE_DEVICE) && 186b997d3a3d61a86dc9525860e863c7b690356d405Eric Laurent ((patch->sources[0].type != AUDIO_PORT_TYPE_DEVICE) || 187b997d3a3d61a86dc9525860e863c7b690356d405Eric Laurent (removedPatch->mAudioPatch.sources[0].ext.device.hw_module != 188b997d3a3d61a86dc9525860e863c7b690356d405Eric Laurent patch->sources[0].ext.device.hw_module))) { 189b997d3a3d61a86dc9525860e863c7b690356d405Eric Laurent hwModule = removedPatch->mAudioPatch.sources[0].ext.device.hw_module; 190b997d3a3d61a86dc9525860e863c7b690356d405Eric Laurent } else if ((patch->num_sinks == 0) || 191b997d3a3d61a86dc9525860e863c7b690356d405Eric Laurent ((removedPatch->mAudioPatch.sinks[0].type == AUDIO_PORT_TYPE_DEVICE) && 192b997d3a3d61a86dc9525860e863c7b690356d405Eric Laurent ((patch->sinks[0].type != AUDIO_PORT_TYPE_DEVICE) || 193b997d3a3d61a86dc9525860e863c7b690356d405Eric Laurent (removedPatch->mAudioPatch.sinks[0].ext.device.hw_module != 194b997d3a3d61a86dc9525860e863c7b690356d405Eric Laurent patch->sinks[0].ext.device.hw_module)))) { 195b997d3a3d61a86dc9525860e863c7b690356d405Eric Laurent // Note on (patch->num_sinks == 0): this situation should not happen as 196b997d3a3d61a86dc9525860e863c7b690356d405Eric Laurent // these special patches are only created by the policy manager but just 197b997d3a3d61a86dc9525860e863c7b690356d405Eric Laurent // in case, systematically clear the HAL patch. 198b997d3a3d61a86dc9525860e863c7b690356d405Eric Laurent // Note that removedPatch->mAudioPatch.num_sinks cannot be 0 here because 199b997d3a3d61a86dc9525860e863c7b690356d405Eric Laurent // halHandle would be AUDIO_PATCH_HANDLE_NONE in this case. 200b997d3a3d61a86dc9525860e863c7b690356d405Eric Laurent hwModule = removedPatch->mAudioPatch.sinks[0].ext.device.hw_module; 201b997d3a3d61a86dc9525860e863c7b690356d405Eric Laurent } 202b997d3a3d61a86dc9525860e863c7b690356d405Eric Laurent if (hwModule != AUDIO_MODULE_HANDLE_NONE) { 203b997d3a3d61a86dc9525860e863c7b690356d405Eric Laurent ssize_t index = audioflinger->mAudioHwDevs.indexOfKey(hwModule); 204b997d3a3d61a86dc9525860e863c7b690356d405Eric Laurent if (index >= 0) { 205b997d3a3d61a86dc9525860e863c7b690356d405Eric Laurent audio_hw_device_t *hwDevice = 206b997d3a3d61a86dc9525860e863c7b690356d405Eric Laurent audioflinger->mAudioHwDevs.valueAt(index)->hwDevice(); 207b997d3a3d61a86dc9525860e863c7b690356d405Eric Laurent hwDevice->release_audio_patch(hwDevice, halHandle); 208b997d3a3d61a86dc9525860e863c7b690356d405Eric Laurent } 209b997d3a3d61a86dc9525860e863c7b690356d405Eric Laurent } 210b997d3a3d61a86dc9525860e863c7b690356d405Eric Laurent } 21183b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent mPatches.removeAt(index); 212d8cd47792bac11a44096ef8233bb5268a6674becsoon delete removedPatch; 21383b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent break; 21483b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent } 215951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } 216951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } 217951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent 21883b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent Patch *newPatch = new Patch(patch); 21983b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent 220951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent switch (patch->sources[0].type) { 221951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent case AUDIO_PORT_TYPE_DEVICE: { 222874c4287a4e49c59ac88767751dce00fcd3edb73Eric Laurent audio_module_handle_t srcModule = patch->sources[0].ext.device.hw_module; 223874c4287a4e49c59ac88767751dce00fcd3edb73Eric Laurent ssize_t index = audioflinger->mAudioHwDevs.indexOfKey(srcModule); 224951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent if (index < 0) { 225874c4287a4e49c59ac88767751dce00fcd3edb73Eric Laurent ALOGW("createAudioPatch() bad src hw module %d", srcModule); 22683b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent status = BAD_VALUE; 22783b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent goto exit; 228951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } 2296a94d69dc4f32abb53c466a96f905bb199be6417Eric Laurent AudioHwDevice *audioHwDevice = audioflinger->mAudioHwDevs.valueAt(index); 230951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent for (unsigned int i = 0; i < patch->num_sinks; i++) { 231874c4287a4e49c59ac88767751dce00fcd3edb73Eric Laurent // support only one sink if connection to a mix or across HW modules 232874c4287a4e49c59ac88767751dce00fcd3edb73Eric Laurent if ((patch->sinks[i].type == AUDIO_PORT_TYPE_MIX || 233874c4287a4e49c59ac88767751dce00fcd3edb73Eric Laurent patch->sinks[i].ext.mix.hw_module != srcModule) && 234874c4287a4e49c59ac88767751dce00fcd3edb73Eric Laurent patch->num_sinks > 1) { 235874c4287a4e49c59ac88767751dce00fcd3edb73Eric Laurent status = INVALID_OPERATION; 236874c4287a4e49c59ac88767751dce00fcd3edb73Eric Laurent goto exit; 237874c4287a4e49c59ac88767751dce00fcd3edb73Eric Laurent } 2386a94d69dc4f32abb53c466a96f905bb199be6417Eric Laurent // reject connection to different sink types 2396a94d69dc4f32abb53c466a96f905bb199be6417Eric Laurent if (patch->sinks[i].type != patch->sinks[0].type) { 2406a94d69dc4f32abb53c466a96f905bb199be6417Eric Laurent ALOGW("createAudioPatch() different sink types in same patch not supported"); 24183b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent status = BAD_VALUE; 24283b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent goto exit; 243951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } 244951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } 245951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent 2463bcf8597189c592713675ec58326ecbef0ac4ae9Eric Laurent // manage patches requiring a software bridge 247d60560af7cb559762593161c8202459cc01fb0f5Eric Laurent // - special patch request with 2 sources (reuse one existing output mix) OR 2483bcf8597189c592713675ec58326ecbef0ac4ae9Eric Laurent // - Device to device AND 2493bcf8597189c592713675ec58326ecbef0ac4ae9Eric Laurent // - source HW module != destination HW module OR 2503bcf8597189c592713675ec58326ecbef0ac4ae9Eric Laurent // - audio HAL version < 3.0 251d60560af7cb559762593161c8202459cc01fb0f5Eric Laurent if ((patch->num_sources == 2) || 252d60560af7cb559762593161c8202459cc01fb0f5Eric Laurent ((patch->sinks[0].type == AUDIO_PORT_TYPE_DEVICE) && 253d60560af7cb559762593161c8202459cc01fb0f5Eric Laurent ((patch->sinks[0].ext.device.hw_module != srcModule) || 254d60560af7cb559762593161c8202459cc01fb0f5Eric Laurent (audioHwDevice->version() < AUDIO_DEVICE_API_VERSION_3_0)))) { 25583b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent if (patch->num_sources == 2) { 25683b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent if (patch->sources[1].type != AUDIO_PORT_TYPE_MIX || 257d60560af7cb559762593161c8202459cc01fb0f5Eric Laurent (patch->num_sinks != 0 && patch->sinks[0].ext.device.hw_module != 258d60560af7cb559762593161c8202459cc01fb0f5Eric Laurent patch->sources[1].ext.mix.hw_module)) { 25983b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent ALOGW("createAudioPatch() invalid source combination"); 26083b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent status = INVALID_OPERATION; 26183b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent goto exit; 26283b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent } 26383b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent 26483b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent sp<ThreadBase> thread = 26583b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent audioflinger->checkPlaybackThread_l(patch->sources[1].ext.mix.handle); 26683b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent newPatch->mPlaybackThread = (MixerThread *)thread.get(); 267951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent if (thread == 0) { 26883b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent ALOGW("createAudioPatch() cannot get playback thread"); 26983b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent status = INVALID_OPERATION; 27083b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent goto exit; 271951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } 272951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } else { 273cf2c0210c8afbe7d0661ccbbae3835b5ce73c0bfEric Laurent audio_config_t config = AUDIO_CONFIG_INITIALIZER; 274cf2c0210c8afbe7d0661ccbbae3835b5ce73c0bfEric Laurent audio_devices_t device = patch->sinks[0].ext.device.type; 275cf2c0210c8afbe7d0661ccbbae3835b5ce73c0bfEric Laurent String8 address = String8(patch->sinks[0].ext.device.address); 276cf2c0210c8afbe7d0661ccbbae3835b5ce73c0bfEric Laurent audio_io_handle_t output = AUDIO_IO_HANDLE_NONE; 27783b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent newPatch->mPlaybackThread = audioflinger->openOutput_l( 27883b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent patch->sinks[0].ext.device.hw_module, 279cf2c0210c8afbe7d0661ccbbae3835b5ce73c0bfEric Laurent &output, 28083b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent &config, 281cf2c0210c8afbe7d0661ccbbae3835b5ce73c0bfEric Laurent device, 282cf2c0210c8afbe7d0661ccbbae3835b5ce73c0bfEric Laurent address, 28383b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent AUDIO_OUTPUT_FLAG_NONE); 28483b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent ALOGV("audioflinger->openOutput_l() returned %p", 28583b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent newPatch->mPlaybackThread.get()); 28683b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent if (newPatch->mPlaybackThread == 0) { 28783b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent status = NO_MEMORY; 28883b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent goto exit; 28983b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent } 29083b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent } 29183b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent audio_devices_t device = patch->sources[0].ext.device.type; 292cf2c0210c8afbe7d0661ccbbae3835b5ce73c0bfEric Laurent String8 address = String8(patch->sources[0].ext.device.address); 293cf2c0210c8afbe7d0661ccbbae3835b5ce73c0bfEric Laurent audio_config_t config = AUDIO_CONFIG_INITIALIZER; 2948ae73129e7e79d826b293238c2f037f723d0e6e8Eric Laurent // open input stream with source device audio properties if provided or 2958ae73129e7e79d826b293238c2f037f723d0e6e8Eric Laurent // default to peer output stream properties otherwise. 2968ae73129e7e79d826b293238c2f037f723d0e6e8Eric Laurent if (patch->sources[0].config_mask & AUDIO_PORT_CONFIG_SAMPLE_RATE) { 2978ae73129e7e79d826b293238c2f037f723d0e6e8Eric Laurent config.sample_rate = patch->sources[0].sample_rate; 2988ae73129e7e79d826b293238c2f037f723d0e6e8Eric Laurent } else { 2998ae73129e7e79d826b293238c2f037f723d0e6e8Eric Laurent config.sample_rate = newPatch->mPlaybackThread->sampleRate(); 3008ae73129e7e79d826b293238c2f037f723d0e6e8Eric Laurent } 3018ae73129e7e79d826b293238c2f037f723d0e6e8Eric Laurent if (patch->sources[0].config_mask & AUDIO_PORT_CONFIG_CHANNEL_MASK) { 3028ae73129e7e79d826b293238c2f037f723d0e6e8Eric Laurent config.channel_mask = patch->sources[0].channel_mask; 3038ae73129e7e79d826b293238c2f037f723d0e6e8Eric Laurent } else { 3048ae73129e7e79d826b293238c2f037f723d0e6e8Eric Laurent config.channel_mask = 3058ae73129e7e79d826b293238c2f037f723d0e6e8Eric Laurent audio_channel_in_mask_from_count(newPatch->mPlaybackThread->channelCount()); 3068ae73129e7e79d826b293238c2f037f723d0e6e8Eric Laurent } 3078ae73129e7e79d826b293238c2f037f723d0e6e8Eric Laurent if (patch->sources[0].config_mask & AUDIO_PORT_CONFIG_FORMAT) { 3088ae73129e7e79d826b293238c2f037f723d0e6e8Eric Laurent config.format = patch->sources[0].format; 3098ae73129e7e79d826b293238c2f037f723d0e6e8Eric Laurent } else { 3108ae73129e7e79d826b293238c2f037f723d0e6e8Eric Laurent config.format = newPatch->mPlaybackThread->format(); 3118ae73129e7e79d826b293238c2f037f723d0e6e8Eric Laurent } 312cf2c0210c8afbe7d0661ccbbae3835b5ce73c0bfEric Laurent audio_io_handle_t input = AUDIO_IO_HANDLE_NONE; 313874c4287a4e49c59ac88767751dce00fcd3edb73Eric Laurent newPatch->mRecordThread = audioflinger->openInput_l(srcModule, 314cf2c0210c8afbe7d0661ccbbae3835b5ce73c0bfEric Laurent &input, 31583b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent &config, 316cf2c0210c8afbe7d0661ccbbae3835b5ce73c0bfEric Laurent device, 317cf2c0210c8afbe7d0661ccbbae3835b5ce73c0bfEric Laurent address, 318cf2c0210c8afbe7d0661ccbbae3835b5ce73c0bfEric Laurent AUDIO_SOURCE_MIC, 31983b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent AUDIO_INPUT_FLAG_NONE); 32083b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent ALOGV("audioflinger->openInput_l() returned %p inChannelMask %08x", 3218ae73129e7e79d826b293238c2f037f723d0e6e8Eric Laurent newPatch->mRecordThread.get(), config.channel_mask); 32283b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent if (newPatch->mRecordThread == 0) { 32383b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent status = NO_MEMORY; 32483b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent goto exit; 32583b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent } 32683b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent status = createPatchConnections(newPatch, patch); 32783b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent if (status != NO_ERROR) { 32883b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent goto exit; 329951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } 330951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } else { 331054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent if (patch->sinks[0].type == AUDIO_PORT_TYPE_MIX) { 33283b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent sp<ThreadBase> thread = audioflinger->checkRecordThread_l( 333054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent patch->sinks[0].ext.mix.handle); 33483b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent if (thread == 0) { 33583b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent ALOGW("createAudioPatch() bad capture I/O handle %d", 336054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent patch->sinks[0].ext.mix.handle); 33783b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent status = BAD_VALUE; 33883b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent goto exit; 33983b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent } 340054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent status = thread->sendCreateAudioPatchConfigEvent(patch, &halHandle); 341054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent } else { 342054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent if (audioHwDevice->version() < AUDIO_DEVICE_API_VERSION_3_0) { 343054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent status = INVALID_OPERATION; 344054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent goto exit; 345cf2c0210c8afbe7d0661ccbbae3835b5ce73c0bfEric Laurent } 346054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent 347054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent audio_hw_device_t *hwDevice = audioHwDevice->hwDevice(); 348054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent status = hwDevice->create_audio_patch(hwDevice, 349054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent patch->num_sources, 350054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent patch->sources, 351054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent patch->num_sinks, 352054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent patch->sinks, 353054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent &halHandle); 354951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } 355951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } 356951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } break; 357951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent case AUDIO_PORT_TYPE_MIX: { 358874c4287a4e49c59ac88767751dce00fcd3edb73Eric Laurent audio_module_handle_t srcModule = patch->sources[0].ext.mix.hw_module; 359874c4287a4e49c59ac88767751dce00fcd3edb73Eric Laurent ssize_t index = audioflinger->mAudioHwDevs.indexOfKey(srcModule); 360951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent if (index < 0) { 361874c4287a4e49c59ac88767751dce00fcd3edb73Eric Laurent ALOGW("createAudioPatch() bad src hw module %d", srcModule); 36283b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent status = BAD_VALUE; 36383b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent goto exit; 364951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } 365951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent // limit to connections between devices and output streams 366054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent audio_devices_t type = AUDIO_DEVICE_NONE; 367951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent for (unsigned int i = 0; i < patch->num_sinks; i++) { 368951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent if (patch->sinks[i].type != AUDIO_PORT_TYPE_DEVICE) { 36983b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent ALOGW("createAudioPatch() invalid sink type %d for mix source", 370951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent patch->sinks[i].type); 37183b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent status = BAD_VALUE; 37283b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent goto exit; 373951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } 374951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent // limit to connections between sinks and sources on same HW module 375874c4287a4e49c59ac88767751dce00fcd3edb73Eric Laurent if (patch->sinks[i].ext.device.hw_module != srcModule) { 37683b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent status = BAD_VALUE; 37783b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent goto exit; 378951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } 379054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent type |= patch->sinks[i].ext.device.type; 380951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } 381951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent sp<ThreadBase> thread = 382951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent audioflinger->checkPlaybackThread_l(patch->sources[0].ext.mix.handle); 383951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent if (thread == 0) { 384951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent ALOGW("createAudioPatch() bad playback I/O handle %d", 385951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent patch->sources[0].ext.mix.handle); 38683b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent status = BAD_VALUE; 38783b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent goto exit; 388951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } 389054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent if (thread == audioflinger->primaryPlaybackThread_l()) { 390054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent AudioParameter param = AudioParameter(); 391cf2c0210c8afbe7d0661ccbbae3835b5ce73c0bfEric Laurent param.addInt(String8(AUDIO_PARAMETER_STREAM_ROUTING), (int)type); 392054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent 393054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent audioflinger->broacastParametersToRecordThreads_l(param.toString()); 394951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } 395951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent 396054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent status = thread->sendCreateAudioPatchConfigEvent(patch, &halHandle); 397951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } break; 398951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent default: 39983b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent status = BAD_VALUE; 40083b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent goto exit; 401951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } 40283b8808faad1e91690c64d7007348be8d9ebde73Eric Laurentexit: 403951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent ALOGV("createAudioPatch() status %d", status); 404951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent if (status == NO_ERROR) { 405a13cde98a880341f0a56d91da6364b093fb5d24eGlenn Kasten *handle = (audio_patch_handle_t) audioflinger->nextUniqueId(AUDIO_UNIQUE_ID_USE_PATCH); 406951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent newPatch->mHandle = *handle; 407951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent newPatch->mHalHandle = halHandle; 408951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent mPatches.add(newPatch); 409951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent ALOGV("createAudioPatch() added new patch handle %d halHandle %d", *handle, halHandle); 41083b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent } else { 41183b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent clearPatchConnections(newPatch); 41283b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent delete newPatch; 41383b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent } 41483b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent return status; 41583b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent} 41683b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent 41783b8808faad1e91690c64d7007348be8d9ebde73Eric Laurentstatus_t AudioFlinger::PatchPanel::createPatchConnections(Patch *patch, 41883b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent const struct audio_patch *audioPatch) 41983b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent{ 42083b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent // create patch from source device to record thread input 42183b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent struct audio_patch subPatch; 42283b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent subPatch.num_sources = 1; 42383b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent subPatch.sources[0] = audioPatch->sources[0]; 42483b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent subPatch.num_sinks = 1; 42583b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent 42683b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent patch->mRecordThread->getAudioPortConfig(&subPatch.sinks[0]); 42783b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent subPatch.sinks[0].ext.mix.usecase.source = AUDIO_SOURCE_MIC; 42883b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent 42983b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent status_t status = createAudioPatch(&subPatch, &patch->mRecordPatchHandle); 43083b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent if (status != NO_ERROR) { 43183b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent patch->mRecordPatchHandle = AUDIO_PATCH_HANDLE_NONE; 43283b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent return status; 43383b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent } 43483b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent 43583b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent // create patch from playback thread output to sink device 436d60560af7cb559762593161c8202459cc01fb0f5Eric Laurent if (audioPatch->num_sinks != 0) { 437d60560af7cb559762593161c8202459cc01fb0f5Eric Laurent patch->mPlaybackThread->getAudioPortConfig(&subPatch.sources[0]); 438d60560af7cb559762593161c8202459cc01fb0f5Eric Laurent subPatch.sinks[0] = audioPatch->sinks[0]; 439d60560af7cb559762593161c8202459cc01fb0f5Eric Laurent status = createAudioPatch(&subPatch, &patch->mPlaybackPatchHandle); 440d60560af7cb559762593161c8202459cc01fb0f5Eric Laurent if (status != NO_ERROR) { 441d60560af7cb559762593161c8202459cc01fb0f5Eric Laurent patch->mPlaybackPatchHandle = AUDIO_PATCH_HANDLE_NONE; 442d60560af7cb559762593161c8202459cc01fb0f5Eric Laurent return status; 443d60560af7cb559762593161c8202459cc01fb0f5Eric Laurent } 444d60560af7cb559762593161c8202459cc01fb0f5Eric Laurent } else { 44583b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent patch->mPlaybackPatchHandle = AUDIO_PATCH_HANDLE_NONE; 44683b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent } 44783b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent 44883b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent // use a pseudo LCM between input and output framecount 44983b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent size_t playbackFrameCount = patch->mPlaybackThread->frameCount(); 45083b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent int playbackShift = __builtin_ctz(playbackFrameCount); 45183b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent size_t recordFramecount = patch->mRecordThread->frameCount(); 45283b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent int shift = __builtin_ctz(recordFramecount); 45383b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent if (playbackShift < shift) { 45483b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent shift = playbackShift; 45583b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent } 45683b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent size_t frameCount = (playbackFrameCount * recordFramecount) >> shift; 457c42e9b462661673dff480ee71757a58b0f806370Glenn Kasten ALOGV("createPatchConnections() playframeCount %zu recordFramecount %zu frameCount %zu", 45883b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent playbackFrameCount, recordFramecount, frameCount); 45983b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent 46083b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent // create a special record track to capture from record thread 46183b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent uint32_t channelCount = patch->mPlaybackThread->channelCount(); 46283b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent audio_channel_mask_t inChannelMask = audio_channel_in_mask_from_count(channelCount); 46383b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent audio_channel_mask_t outChannelMask = patch->mPlaybackThread->channelMask(); 46483b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent uint32_t sampleRate = patch->mPlaybackThread->sampleRate(); 46583b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent audio_format_t format = patch->mPlaybackThread->format(); 46683b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent 46783b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent patch->mPatchRecord = new RecordThread::PatchRecord( 46883b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent patch->mRecordThread.get(), 46983b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent sampleRate, 47083b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent inChannelMask, 47183b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent format, 47283b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent frameCount, 47383b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent NULL, 474050677873c10d4da308ac222f8533c96cca3207eEric Laurent AUDIO_INPUT_FLAG_NONE); 47583b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent if (patch->mPatchRecord == 0) { 47683b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent return NO_MEMORY; 47783b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent } 47883b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent status = patch->mPatchRecord->initCheck(); 47983b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent if (status != NO_ERROR) { 48083b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent return status; 481951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } 48283b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent patch->mRecordThread->addPatchRecord(patch->mPatchRecord); 48383b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent 48483b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent // create a special playback track to render to playback thread. 48583b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent // this track is given the same buffer as the PatchRecord buffer 48683b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent patch->mPatchTrack = new PlaybackThread::PatchTrack( 48783b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent patch->mPlaybackThread.get(), 4883bcf8597189c592713675ec58326ecbef0ac4ae9Eric Laurent audioPatch->sources[1].ext.mix.usecase.stream, 48983b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent sampleRate, 49083b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent outChannelMask, 49183b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent format, 49283b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent frameCount, 49383b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent patch->mPatchRecord->buffer(), 494050677873c10d4da308ac222f8533c96cca3207eEric Laurent AUDIO_OUTPUT_FLAG_NONE); 49583b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent if (patch->mPatchTrack == 0) { 49683b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent return NO_MEMORY; 49783b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent } 49883b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent status = patch->mPatchTrack->initCheck(); 49983b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent if (status != NO_ERROR) { 50083b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent return status; 50183b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent } 50283b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent patch->mPlaybackThread->addPatchTrack(patch->mPatchTrack); 50383b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent 50483b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent // tie playback and record tracks together 50583b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent patch->mPatchRecord->setPeerProxy(patch->mPatchTrack.get()); 50683b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent patch->mPatchTrack->setPeerProxy(patch->mPatchRecord.get()); 50783b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent 50883b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent // start capture and playback 509d848eb48c121c119e8ba7583efc75415fe102570Glenn Kasten patch->mPatchRecord->start(AudioSystem::SYNC_EVENT_NONE, AUDIO_SESSION_NONE); 51083b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent patch->mPatchTrack->start(); 51183b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent 512951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent return status; 513951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent} 514951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent 51583b8808faad1e91690c64d7007348be8d9ebde73Eric Laurentvoid AudioFlinger::PatchPanel::clearPatchConnections(Patch *patch) 51683b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent{ 51783b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent sp<AudioFlinger> audioflinger = mAudioFlinger.promote(); 51883b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent if (audioflinger == 0) { 51983b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent return; 52083b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent } 52183b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent 52283b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent ALOGV("clearPatchConnections() patch->mRecordPatchHandle %d patch->mPlaybackPatchHandle %d", 52383b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent patch->mRecordPatchHandle, patch->mPlaybackPatchHandle); 52483b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent 52583b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent if (patch->mPatchRecord != 0) { 52683b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent patch->mPatchRecord->stop(); 52783b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent } 52883b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent if (patch->mPatchTrack != 0) { 52983b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent patch->mPatchTrack->stop(); 53083b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent } 53183b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent if (patch->mRecordPatchHandle != AUDIO_PATCH_HANDLE_NONE) { 53283b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent releaseAudioPatch(patch->mRecordPatchHandle); 53383b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent patch->mRecordPatchHandle = AUDIO_PATCH_HANDLE_NONE; 53483b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent } 53583b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent if (patch->mPlaybackPatchHandle != AUDIO_PATCH_HANDLE_NONE) { 53683b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent releaseAudioPatch(patch->mPlaybackPatchHandle); 53783b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent patch->mPlaybackPatchHandle = AUDIO_PATCH_HANDLE_NONE; 53883b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent } 53983b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent if (patch->mRecordThread != 0) { 54083b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent if (patch->mPatchRecord != 0) { 54183b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent patch->mRecordThread->deletePatchRecord(patch->mPatchRecord); 54283b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent } 54383b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent audioflinger->closeInputInternal_l(patch->mRecordThread); 54483b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent } 54583b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent if (patch->mPlaybackThread != 0) { 54683b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent if (patch->mPatchTrack != 0) { 54783b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent patch->mPlaybackThread->deletePatchTrack(patch->mPatchTrack); 54883b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent } 54983b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent // if num sources == 2 we are reusing an existing playback thread so we do not close it 55083b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent if (patch->mAudioPatch.num_sources != 2) { 55183b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent audioflinger->closeOutputInternal_l(patch->mPlaybackThread); 55283b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent } 553a0169a073d88efefbfb35fa0ea8e94f7b31d7469Eric Laurent } 554a0169a073d88efefbfb35fa0ea8e94f7b31d7469Eric Laurent if (patch->mRecordThread != 0) { 555a0169a073d88efefbfb35fa0ea8e94f7b31d7469Eric Laurent if (patch->mPatchRecord != 0) { 556a0169a073d88efefbfb35fa0ea8e94f7b31d7469Eric Laurent patch->mPatchRecord.clear(); 557a0169a073d88efefbfb35fa0ea8e94f7b31d7469Eric Laurent } 558a0169a073d88efefbfb35fa0ea8e94f7b31d7469Eric Laurent patch->mRecordThread.clear(); 559a0169a073d88efefbfb35fa0ea8e94f7b31d7469Eric Laurent } 560a0169a073d88efefbfb35fa0ea8e94f7b31d7469Eric Laurent if (patch->mPlaybackThread != 0) { 561a0169a073d88efefbfb35fa0ea8e94f7b31d7469Eric Laurent if (patch->mPatchTrack != 0) { 562a0169a073d88efefbfb35fa0ea8e94f7b31d7469Eric Laurent patch->mPatchTrack.clear(); 563a0169a073d88efefbfb35fa0ea8e94f7b31d7469Eric Laurent } 56483b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent patch->mPlaybackThread.clear(); 56583b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent } 566a0169a073d88efefbfb35fa0ea8e94f7b31d7469Eric Laurent 56783b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent} 56883b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent 569951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent/* Disconnect a patch */ 570951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurentstatus_t AudioFlinger::PatchPanel::releaseAudioPatch(audio_patch_handle_t handle) 571951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent{ 572951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent ALOGV("releaseAudioPatch handle %d", handle); 573951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent status_t status = NO_ERROR; 574951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent size_t index; 575951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent 576951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent sp<AudioFlinger> audioflinger = mAudioFlinger.promote(); 577951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent if (audioflinger == 0) { 578951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent return NO_INIT; 579951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } 580951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent 581951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent for (index = 0; index < mPatches.size(); index++) { 582951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent if (handle == mPatches[index]->mHandle) { 583951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent break; 584951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } 585951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } 586951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent if (index == mPatches.size()) { 587951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent return BAD_VALUE; 588951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } 58983b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent Patch *removedPatch = mPatches[index]; 59083b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent mPatches.removeAt(index); 591951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent 59283b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent struct audio_patch *patch = &removedPatch->mAudioPatch; 593951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent 594951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent switch (patch->sources[0].type) { 595951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent case AUDIO_PORT_TYPE_DEVICE: { 596874c4287a4e49c59ac88767751dce00fcd3edb73Eric Laurent audio_module_handle_t srcModule = patch->sources[0].ext.device.hw_module; 597874c4287a4e49c59ac88767751dce00fcd3edb73Eric Laurent ssize_t index = audioflinger->mAudioHwDevs.indexOfKey(srcModule); 598951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent if (index < 0) { 599874c4287a4e49c59ac88767751dce00fcd3edb73Eric Laurent ALOGW("releaseAudioPatch() bad src hw module %d", srcModule); 600951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent status = BAD_VALUE; 601951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent break; 602951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } 60383b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent 6043bcf8597189c592713675ec58326ecbef0ac4ae9Eric Laurent if (removedPatch->mRecordPatchHandle != AUDIO_PATCH_HANDLE_NONE || 6053bcf8597189c592713675ec58326ecbef0ac4ae9Eric Laurent removedPatch->mPlaybackPatchHandle != AUDIO_PATCH_HANDLE_NONE) { 60683b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent clearPatchConnections(removedPatch); 60783b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent break; 60883b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent } 60983b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent 610054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent if (patch->sinks[0].type == AUDIO_PORT_TYPE_MIX) { 611951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent sp<ThreadBase> thread = audioflinger->checkRecordThread_l( 612054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent patch->sinks[0].ext.mix.handle); 613951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent if (thread == 0) { 614951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent ALOGW("releaseAudioPatch() bad capture I/O handle %d", 615054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent patch->sinks[0].ext.mix.handle); 616951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent status = BAD_VALUE; 617951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent break; 618951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } 619054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent status = thread->sendReleaseAudioPatchConfigEvent(removedPatch->mHalHandle); 620054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent } else { 621054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent AudioHwDevice *audioHwDevice = audioflinger->mAudioHwDevs.valueAt(index); 622054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent if (audioHwDevice->version() < AUDIO_DEVICE_API_VERSION_3_0) { 623054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent status = INVALID_OPERATION; 624054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent break; 625054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent } 626054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent audio_hw_device_t *hwDevice = audioHwDevice->hwDevice(); 627054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent status = hwDevice->release_audio_patch(hwDevice, removedPatch->mHalHandle); 628951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } 629951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } break; 630951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent case AUDIO_PORT_TYPE_MIX: { 631874c4287a4e49c59ac88767751dce00fcd3edb73Eric Laurent audio_module_handle_t srcModule = patch->sources[0].ext.mix.hw_module; 632874c4287a4e49c59ac88767751dce00fcd3edb73Eric Laurent ssize_t index = audioflinger->mAudioHwDevs.indexOfKey(srcModule); 633951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent if (index < 0) { 634874c4287a4e49c59ac88767751dce00fcd3edb73Eric Laurent ALOGW("releaseAudioPatch() bad src hw module %d", srcModule); 635951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent status = BAD_VALUE; 636951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent break; 637951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } 638951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent sp<ThreadBase> thread = 639951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent audioflinger->checkPlaybackThread_l(patch->sources[0].ext.mix.handle); 640951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent if (thread == 0) { 641951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent ALOGW("releaseAudioPatch() bad playback I/O handle %d", 642951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent patch->sources[0].ext.mix.handle); 643951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent status = BAD_VALUE; 644951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent break; 645951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } 646054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent status = thread->sendReleaseAudioPatchConfigEvent(removedPatch->mHalHandle); 647951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } break; 648951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent default: 649951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent status = BAD_VALUE; 650951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent break; 651951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } 652951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent 65383b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent delete removedPatch; 654951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent return status; 655951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent} 656951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent 657951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent 658951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent/* List connected audio ports and they attributes */ 659951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurentstatus_t AudioFlinger::PatchPanel::listAudioPatches(unsigned int *num_patches __unused, 660951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent struct audio_patch *patches __unused) 661951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent{ 662951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent ALOGV("listAudioPatches"); 663951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent return NO_ERROR; 664951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent} 665951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent 666951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent/* Set audio port configuration */ 667e1715a465a29db625da9d0ea365edf371e39e201Eric Laurentstatus_t AudioFlinger::PatchPanel::setAudioPortConfig(const struct audio_port_config *config) 668951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent{ 669951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent ALOGV("setAudioPortConfig"); 670e1715a465a29db625da9d0ea365edf371e39e201Eric Laurent 671e1715a465a29db625da9d0ea365edf371e39e201Eric Laurent sp<AudioFlinger> audioflinger = mAudioFlinger.promote(); 672e1715a465a29db625da9d0ea365edf371e39e201Eric Laurent if (audioflinger == 0) { 673e1715a465a29db625da9d0ea365edf371e39e201Eric Laurent return NO_INIT; 674e1715a465a29db625da9d0ea365edf371e39e201Eric Laurent } 675e1715a465a29db625da9d0ea365edf371e39e201Eric Laurent 676e1715a465a29db625da9d0ea365edf371e39e201Eric Laurent audio_module_handle_t module; 677e1715a465a29db625da9d0ea365edf371e39e201Eric Laurent if (config->type == AUDIO_PORT_TYPE_DEVICE) { 678e1715a465a29db625da9d0ea365edf371e39e201Eric Laurent module = config->ext.device.hw_module; 679e1715a465a29db625da9d0ea365edf371e39e201Eric Laurent } else { 680e1715a465a29db625da9d0ea365edf371e39e201Eric Laurent module = config->ext.mix.hw_module; 681e1715a465a29db625da9d0ea365edf371e39e201Eric Laurent } 682e1715a465a29db625da9d0ea365edf371e39e201Eric Laurent 683e1715a465a29db625da9d0ea365edf371e39e201Eric Laurent ssize_t index = audioflinger->mAudioHwDevs.indexOfKey(module); 684e1715a465a29db625da9d0ea365edf371e39e201Eric Laurent if (index < 0) { 685e1715a465a29db625da9d0ea365edf371e39e201Eric Laurent ALOGW("setAudioPortConfig() bad hw module %d", module); 686e1715a465a29db625da9d0ea365edf371e39e201Eric Laurent return BAD_VALUE; 687e1715a465a29db625da9d0ea365edf371e39e201Eric Laurent } 688e1715a465a29db625da9d0ea365edf371e39e201Eric Laurent 689e1715a465a29db625da9d0ea365edf371e39e201Eric Laurent AudioHwDevice *audioHwDevice = audioflinger->mAudioHwDevs.valueAt(index); 690e1715a465a29db625da9d0ea365edf371e39e201Eric Laurent if (audioHwDevice->version() >= AUDIO_DEVICE_API_VERSION_3_0) { 691e1715a465a29db625da9d0ea365edf371e39e201Eric Laurent audio_hw_device_t *hwDevice = audioHwDevice->hwDevice(); 692e1715a465a29db625da9d0ea365edf371e39e201Eric Laurent return hwDevice->set_audio_port_config(hwDevice, config); 693e1715a465a29db625da9d0ea365edf371e39e201Eric Laurent } else { 694e1715a465a29db625da9d0ea365edf371e39e201Eric Laurent return INVALID_OPERATION; 695e1715a465a29db625da9d0ea365edf371e39e201Eric Laurent } 696951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent return NO_ERROR; 697951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent} 698951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent 69963238efb0d674758902918e3cdaac322126484b7Glenn Kasten} // namespace android 700