PatchPanel.cpp revision d848eb48c121c119e8ba7583efc75415fe102570
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]; 17183b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent mPatches.removeAt(index); 172d8cd47792bac11a44096ef8233bb5268a6674becsoon delete removedPatch; 17383b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent break; 17483b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent } 175951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } 176951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } 177951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent 17883b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent Patch *newPatch = new Patch(patch); 17983b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent 180951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent switch (patch->sources[0].type) { 181951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent case AUDIO_PORT_TYPE_DEVICE: { 182874c4287a4e49c59ac88767751dce00fcd3edb73Eric Laurent audio_module_handle_t srcModule = patch->sources[0].ext.device.hw_module; 183874c4287a4e49c59ac88767751dce00fcd3edb73Eric Laurent ssize_t index = audioflinger->mAudioHwDevs.indexOfKey(srcModule); 184951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent if (index < 0) { 185874c4287a4e49c59ac88767751dce00fcd3edb73Eric Laurent ALOGW("createAudioPatch() bad src hw module %d", srcModule); 18683b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent status = BAD_VALUE; 18783b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent goto exit; 188951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } 1896a94d69dc4f32abb53c466a96f905bb199be6417Eric Laurent AudioHwDevice *audioHwDevice = audioflinger->mAudioHwDevs.valueAt(index); 190951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent for (unsigned int i = 0; i < patch->num_sinks; i++) { 191874c4287a4e49c59ac88767751dce00fcd3edb73Eric Laurent // support only one sink if connection to a mix or across HW modules 192874c4287a4e49c59ac88767751dce00fcd3edb73Eric Laurent if ((patch->sinks[i].type == AUDIO_PORT_TYPE_MIX || 193874c4287a4e49c59ac88767751dce00fcd3edb73Eric Laurent patch->sinks[i].ext.mix.hw_module != srcModule) && 194874c4287a4e49c59ac88767751dce00fcd3edb73Eric Laurent patch->num_sinks > 1) { 195874c4287a4e49c59ac88767751dce00fcd3edb73Eric Laurent status = INVALID_OPERATION; 196874c4287a4e49c59ac88767751dce00fcd3edb73Eric Laurent goto exit; 197874c4287a4e49c59ac88767751dce00fcd3edb73Eric Laurent } 1986a94d69dc4f32abb53c466a96f905bb199be6417Eric Laurent // reject connection to different sink types 1996a94d69dc4f32abb53c466a96f905bb199be6417Eric Laurent if (patch->sinks[i].type != patch->sinks[0].type) { 2006a94d69dc4f32abb53c466a96f905bb199be6417Eric Laurent ALOGW("createAudioPatch() different sink types in same patch not supported"); 20183b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent status = BAD_VALUE; 20283b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent goto exit; 203951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } 204951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } 205951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent 2063bcf8597189c592713675ec58326ecbef0ac4ae9Eric Laurent // manage patches requiring a software bridge 207d60560af7cb559762593161c8202459cc01fb0f5Eric Laurent // - special patch request with 2 sources (reuse one existing output mix) OR 2083bcf8597189c592713675ec58326ecbef0ac4ae9Eric Laurent // - Device to device AND 2093bcf8597189c592713675ec58326ecbef0ac4ae9Eric Laurent // - source HW module != destination HW module OR 2103bcf8597189c592713675ec58326ecbef0ac4ae9Eric Laurent // - audio HAL version < 3.0 211d60560af7cb559762593161c8202459cc01fb0f5Eric Laurent if ((patch->num_sources == 2) || 212d60560af7cb559762593161c8202459cc01fb0f5Eric Laurent ((patch->sinks[0].type == AUDIO_PORT_TYPE_DEVICE) && 213d60560af7cb559762593161c8202459cc01fb0f5Eric Laurent ((patch->sinks[0].ext.device.hw_module != srcModule) || 214d60560af7cb559762593161c8202459cc01fb0f5Eric Laurent (audioHwDevice->version() < AUDIO_DEVICE_API_VERSION_3_0)))) { 21583b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent if (patch->num_sources == 2) { 21683b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent if (patch->sources[1].type != AUDIO_PORT_TYPE_MIX || 217d60560af7cb559762593161c8202459cc01fb0f5Eric Laurent (patch->num_sinks != 0 && patch->sinks[0].ext.device.hw_module != 218d60560af7cb559762593161c8202459cc01fb0f5Eric Laurent patch->sources[1].ext.mix.hw_module)) { 21983b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent ALOGW("createAudioPatch() invalid source combination"); 22083b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent status = INVALID_OPERATION; 22183b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent goto exit; 22283b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent } 22383b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent 22483b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent sp<ThreadBase> thread = 22583b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent audioflinger->checkPlaybackThread_l(patch->sources[1].ext.mix.handle); 22683b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent newPatch->mPlaybackThread = (MixerThread *)thread.get(); 227951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent if (thread == 0) { 22883b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent ALOGW("createAudioPatch() cannot get playback thread"); 22983b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent status = INVALID_OPERATION; 23083b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent goto exit; 231951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } 232951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } else { 233cf2c0210c8afbe7d0661ccbbae3835b5ce73c0bfEric Laurent audio_config_t config = AUDIO_CONFIG_INITIALIZER; 234cf2c0210c8afbe7d0661ccbbae3835b5ce73c0bfEric Laurent audio_devices_t device = patch->sinks[0].ext.device.type; 235cf2c0210c8afbe7d0661ccbbae3835b5ce73c0bfEric Laurent String8 address = String8(patch->sinks[0].ext.device.address); 236cf2c0210c8afbe7d0661ccbbae3835b5ce73c0bfEric Laurent audio_io_handle_t output = AUDIO_IO_HANDLE_NONE; 23783b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent newPatch->mPlaybackThread = audioflinger->openOutput_l( 23883b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent patch->sinks[0].ext.device.hw_module, 239cf2c0210c8afbe7d0661ccbbae3835b5ce73c0bfEric Laurent &output, 24083b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent &config, 241cf2c0210c8afbe7d0661ccbbae3835b5ce73c0bfEric Laurent device, 242cf2c0210c8afbe7d0661ccbbae3835b5ce73c0bfEric Laurent address, 24383b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent AUDIO_OUTPUT_FLAG_NONE); 24483b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent ALOGV("audioflinger->openOutput_l() returned %p", 24583b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent newPatch->mPlaybackThread.get()); 24683b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent if (newPatch->mPlaybackThread == 0) { 24783b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent status = NO_MEMORY; 24883b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent goto exit; 24983b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent } 25083b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent } 25183b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent uint32_t channelCount = newPatch->mPlaybackThread->channelCount(); 25283b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent audio_devices_t device = patch->sources[0].ext.device.type; 253cf2c0210c8afbe7d0661ccbbae3835b5ce73c0bfEric Laurent String8 address = String8(patch->sources[0].ext.device.address); 254cf2c0210c8afbe7d0661ccbbae3835b5ce73c0bfEric Laurent audio_config_t config = AUDIO_CONFIG_INITIALIZER; 25583b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent audio_channel_mask_t inChannelMask = audio_channel_in_mask_from_count(channelCount); 25683b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent config.sample_rate = newPatch->mPlaybackThread->sampleRate(); 25783b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent config.channel_mask = inChannelMask; 25883b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent config.format = newPatch->mPlaybackThread->format(); 259cf2c0210c8afbe7d0661ccbbae3835b5ce73c0bfEric Laurent audio_io_handle_t input = AUDIO_IO_HANDLE_NONE; 260874c4287a4e49c59ac88767751dce00fcd3edb73Eric Laurent newPatch->mRecordThread = audioflinger->openInput_l(srcModule, 261cf2c0210c8afbe7d0661ccbbae3835b5ce73c0bfEric Laurent &input, 26283b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent &config, 263cf2c0210c8afbe7d0661ccbbae3835b5ce73c0bfEric Laurent device, 264cf2c0210c8afbe7d0661ccbbae3835b5ce73c0bfEric Laurent address, 265cf2c0210c8afbe7d0661ccbbae3835b5ce73c0bfEric Laurent AUDIO_SOURCE_MIC, 26683b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent AUDIO_INPUT_FLAG_NONE); 26783b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent ALOGV("audioflinger->openInput_l() returned %p inChannelMask %08x", 26883b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent newPatch->mRecordThread.get(), inChannelMask); 26983b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent if (newPatch->mRecordThread == 0) { 27083b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent status = NO_MEMORY; 27183b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent goto exit; 27283b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent } 27383b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent status = createPatchConnections(newPatch, patch); 27483b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent if (status != NO_ERROR) { 27583b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent goto exit; 276951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } 277951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } else { 278054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent if (patch->sinks[0].type == AUDIO_PORT_TYPE_MIX) { 27983b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent sp<ThreadBase> thread = audioflinger->checkRecordThread_l( 280054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent patch->sinks[0].ext.mix.handle); 28183b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent if (thread == 0) { 28283b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent ALOGW("createAudioPatch() bad capture I/O handle %d", 283054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent patch->sinks[0].ext.mix.handle); 28483b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent status = BAD_VALUE; 28583b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent goto exit; 28683b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent } 287054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent status = thread->sendCreateAudioPatchConfigEvent(patch, &halHandle); 288054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent } else { 289054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent if (audioHwDevice->version() < AUDIO_DEVICE_API_VERSION_3_0) { 290054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent status = INVALID_OPERATION; 291054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent goto exit; 292cf2c0210c8afbe7d0661ccbbae3835b5ce73c0bfEric Laurent } 293054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent 294054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent audio_hw_device_t *hwDevice = audioHwDevice->hwDevice(); 295054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent status = hwDevice->create_audio_patch(hwDevice, 296054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent patch->num_sources, 297054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent patch->sources, 298054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent patch->num_sinks, 299054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent patch->sinks, 300054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent &halHandle); 301951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } 302951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } 303951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } break; 304951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent case AUDIO_PORT_TYPE_MIX: { 305874c4287a4e49c59ac88767751dce00fcd3edb73Eric Laurent audio_module_handle_t srcModule = patch->sources[0].ext.mix.hw_module; 306874c4287a4e49c59ac88767751dce00fcd3edb73Eric Laurent ssize_t index = audioflinger->mAudioHwDevs.indexOfKey(srcModule); 307951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent if (index < 0) { 308874c4287a4e49c59ac88767751dce00fcd3edb73Eric Laurent ALOGW("createAudioPatch() bad src hw module %d", srcModule); 30983b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent status = BAD_VALUE; 31083b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent goto exit; 311951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } 312951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent // limit to connections between devices and output streams 313054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent audio_devices_t type = AUDIO_DEVICE_NONE; 314951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent for (unsigned int i = 0; i < patch->num_sinks; i++) { 315951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent if (patch->sinks[i].type != AUDIO_PORT_TYPE_DEVICE) { 31683b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent ALOGW("createAudioPatch() invalid sink type %d for mix source", 317951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent patch->sinks[i].type); 31883b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent status = BAD_VALUE; 31983b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent goto exit; 320951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } 321951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent // limit to connections between sinks and sources on same HW module 322874c4287a4e49c59ac88767751dce00fcd3edb73Eric Laurent if (patch->sinks[i].ext.device.hw_module != srcModule) { 32383b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent status = BAD_VALUE; 32483b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent goto exit; 325951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } 326054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent type |= patch->sinks[i].ext.device.type; 327951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } 328951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent sp<ThreadBase> thread = 329951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent audioflinger->checkPlaybackThread_l(patch->sources[0].ext.mix.handle); 330951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent if (thread == 0) { 331951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent ALOGW("createAudioPatch() bad playback I/O handle %d", 332951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent patch->sources[0].ext.mix.handle); 33383b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent status = BAD_VALUE; 33483b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent goto exit; 335951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } 336054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent if (thread == audioflinger->primaryPlaybackThread_l()) { 337054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent AudioParameter param = AudioParameter(); 338cf2c0210c8afbe7d0661ccbbae3835b5ce73c0bfEric Laurent param.addInt(String8(AUDIO_PARAMETER_STREAM_ROUTING), (int)type); 339054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent 340054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent audioflinger->broacastParametersToRecordThreads_l(param.toString()); 341951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } 342951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent 343054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent status = thread->sendCreateAudioPatchConfigEvent(patch, &halHandle); 344951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } break; 345951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent default: 34683b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent status = BAD_VALUE; 34783b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent goto exit; 348951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } 34983b8808faad1e91690c64d7007348be8d9ebde73Eric Laurentexit: 350951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent ALOGV("createAudioPatch() status %d", status); 351951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent if (status == NO_ERROR) { 352eeecb980ff4c202d0a3c4b0bfe040dce2f73336dGlenn Kasten *handle = audioflinger->nextUniqueId(AUDIO_UNIQUE_ID_USE_PATCH); 353951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent newPatch->mHandle = *handle; 354951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent newPatch->mHalHandle = halHandle; 355951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent mPatches.add(newPatch); 356951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent ALOGV("createAudioPatch() added new patch handle %d halHandle %d", *handle, halHandle); 35783b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent } else { 35883b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent clearPatchConnections(newPatch); 35983b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent delete newPatch; 36083b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent } 36183b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent return status; 36283b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent} 36383b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent 36483b8808faad1e91690c64d7007348be8d9ebde73Eric Laurentstatus_t AudioFlinger::PatchPanel::createPatchConnections(Patch *patch, 36583b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent const struct audio_patch *audioPatch) 36683b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent{ 36783b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent // create patch from source device to record thread input 36883b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent struct audio_patch subPatch; 36983b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent subPatch.num_sources = 1; 37083b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent subPatch.sources[0] = audioPatch->sources[0]; 37183b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent subPatch.num_sinks = 1; 37283b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent 37383b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent patch->mRecordThread->getAudioPortConfig(&subPatch.sinks[0]); 37483b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent subPatch.sinks[0].ext.mix.usecase.source = AUDIO_SOURCE_MIC; 37583b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent 37683b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent status_t status = createAudioPatch(&subPatch, &patch->mRecordPatchHandle); 37783b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent if (status != NO_ERROR) { 37883b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent patch->mRecordPatchHandle = AUDIO_PATCH_HANDLE_NONE; 37983b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent return status; 38083b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent } 38183b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent 38283b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent // create patch from playback thread output to sink device 383d60560af7cb559762593161c8202459cc01fb0f5Eric Laurent if (audioPatch->num_sinks != 0) { 384d60560af7cb559762593161c8202459cc01fb0f5Eric Laurent patch->mPlaybackThread->getAudioPortConfig(&subPatch.sources[0]); 385d60560af7cb559762593161c8202459cc01fb0f5Eric Laurent subPatch.sinks[0] = audioPatch->sinks[0]; 386d60560af7cb559762593161c8202459cc01fb0f5Eric Laurent status = createAudioPatch(&subPatch, &patch->mPlaybackPatchHandle); 387d60560af7cb559762593161c8202459cc01fb0f5Eric Laurent if (status != NO_ERROR) { 388d60560af7cb559762593161c8202459cc01fb0f5Eric Laurent patch->mPlaybackPatchHandle = AUDIO_PATCH_HANDLE_NONE; 389d60560af7cb559762593161c8202459cc01fb0f5Eric Laurent return status; 390d60560af7cb559762593161c8202459cc01fb0f5Eric Laurent } 391d60560af7cb559762593161c8202459cc01fb0f5Eric Laurent } else { 39283b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent patch->mPlaybackPatchHandle = AUDIO_PATCH_HANDLE_NONE; 39383b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent } 39483b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent 39583b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent // use a pseudo LCM between input and output framecount 39683b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent size_t playbackFrameCount = patch->mPlaybackThread->frameCount(); 39783b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent int playbackShift = __builtin_ctz(playbackFrameCount); 39883b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent size_t recordFramecount = patch->mRecordThread->frameCount(); 39983b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent int shift = __builtin_ctz(recordFramecount); 40083b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent if (playbackShift < shift) { 40183b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent shift = playbackShift; 40283b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent } 40383b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent size_t frameCount = (playbackFrameCount * recordFramecount) >> shift; 40483b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent ALOGV("createPatchConnections() playframeCount %d recordFramecount %d frameCount %d ", 40583b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent playbackFrameCount, recordFramecount, frameCount); 40683b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent 40783b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent // create a special record track to capture from record thread 40883b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent uint32_t channelCount = patch->mPlaybackThread->channelCount(); 40983b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent audio_channel_mask_t inChannelMask = audio_channel_in_mask_from_count(channelCount); 41083b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent audio_channel_mask_t outChannelMask = patch->mPlaybackThread->channelMask(); 41183b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent uint32_t sampleRate = patch->mPlaybackThread->sampleRate(); 41283b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent audio_format_t format = patch->mPlaybackThread->format(); 41383b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent 41483b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent patch->mPatchRecord = new RecordThread::PatchRecord( 41583b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent patch->mRecordThread.get(), 41683b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent sampleRate, 41783b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent inChannelMask, 41883b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent format, 41983b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent frameCount, 42083b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent NULL, 42183b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent IAudioFlinger::TRACK_DEFAULT); 42283b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent if (patch->mPatchRecord == 0) { 42383b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent return NO_MEMORY; 42483b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent } 42583b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent status = patch->mPatchRecord->initCheck(); 42683b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent if (status != NO_ERROR) { 42783b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent return status; 428951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } 42983b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent patch->mRecordThread->addPatchRecord(patch->mPatchRecord); 43083b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent 43183b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent // create a special playback track to render to playback thread. 43283b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent // this track is given the same buffer as the PatchRecord buffer 43383b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent patch->mPatchTrack = new PlaybackThread::PatchTrack( 43483b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent patch->mPlaybackThread.get(), 4353bcf8597189c592713675ec58326ecbef0ac4ae9Eric Laurent audioPatch->sources[1].ext.mix.usecase.stream, 43683b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent sampleRate, 43783b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent outChannelMask, 43883b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent format, 43983b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent frameCount, 44083b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent patch->mPatchRecord->buffer(), 44183b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent IAudioFlinger::TRACK_DEFAULT); 44283b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent if (patch->mPatchTrack == 0) { 44383b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent return NO_MEMORY; 44483b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent } 44583b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent status = patch->mPatchTrack->initCheck(); 44683b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent if (status != NO_ERROR) { 44783b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent return status; 44883b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent } 44983b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent patch->mPlaybackThread->addPatchTrack(patch->mPatchTrack); 45083b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent 45183b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent // tie playback and record tracks together 45283b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent patch->mPatchRecord->setPeerProxy(patch->mPatchTrack.get()); 45383b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent patch->mPatchTrack->setPeerProxy(patch->mPatchRecord.get()); 45483b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent 45583b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent // start capture and playback 456d848eb48c121c119e8ba7583efc75415fe102570Glenn Kasten patch->mPatchRecord->start(AudioSystem::SYNC_EVENT_NONE, AUDIO_SESSION_NONE); 45783b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent patch->mPatchTrack->start(); 45883b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent 459951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent return status; 460951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent} 461951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent 46283b8808faad1e91690c64d7007348be8d9ebde73Eric Laurentvoid AudioFlinger::PatchPanel::clearPatchConnections(Patch *patch) 46383b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent{ 46483b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent sp<AudioFlinger> audioflinger = mAudioFlinger.promote(); 46583b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent if (audioflinger == 0) { 46683b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent return; 46783b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent } 46883b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent 46983b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent ALOGV("clearPatchConnections() patch->mRecordPatchHandle %d patch->mPlaybackPatchHandle %d", 47083b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent patch->mRecordPatchHandle, patch->mPlaybackPatchHandle); 47183b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent 47283b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent if (patch->mPatchRecord != 0) { 47383b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent patch->mPatchRecord->stop(); 47483b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent } 47583b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent if (patch->mPatchTrack != 0) { 47683b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent patch->mPatchTrack->stop(); 47783b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent } 47883b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent if (patch->mRecordPatchHandle != AUDIO_PATCH_HANDLE_NONE) { 47983b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent releaseAudioPatch(patch->mRecordPatchHandle); 48083b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent patch->mRecordPatchHandle = AUDIO_PATCH_HANDLE_NONE; 48183b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent } 48283b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent if (patch->mPlaybackPatchHandle != AUDIO_PATCH_HANDLE_NONE) { 48383b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent releaseAudioPatch(patch->mPlaybackPatchHandle); 48483b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent patch->mPlaybackPatchHandle = AUDIO_PATCH_HANDLE_NONE; 48583b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent } 48683b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent if (patch->mRecordThread != 0) { 48783b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent if (patch->mPatchRecord != 0) { 48883b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent patch->mRecordThread->deletePatchRecord(patch->mPatchRecord); 48983b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent } 49083b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent audioflinger->closeInputInternal_l(patch->mRecordThread); 49183b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent } 49283b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent if (patch->mPlaybackThread != 0) { 49383b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent if (patch->mPatchTrack != 0) { 49483b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent patch->mPlaybackThread->deletePatchTrack(patch->mPatchTrack); 49583b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent } 49683b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent // if num sources == 2 we are reusing an existing playback thread so we do not close it 49783b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent if (patch->mAudioPatch.num_sources != 2) { 49883b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent audioflinger->closeOutputInternal_l(patch->mPlaybackThread); 49983b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent } 500a0169a073d88efefbfb35fa0ea8e94f7b31d7469Eric Laurent } 501a0169a073d88efefbfb35fa0ea8e94f7b31d7469Eric Laurent if (patch->mRecordThread != 0) { 502a0169a073d88efefbfb35fa0ea8e94f7b31d7469Eric Laurent if (patch->mPatchRecord != 0) { 503a0169a073d88efefbfb35fa0ea8e94f7b31d7469Eric Laurent patch->mPatchRecord.clear(); 504a0169a073d88efefbfb35fa0ea8e94f7b31d7469Eric Laurent } 505a0169a073d88efefbfb35fa0ea8e94f7b31d7469Eric Laurent patch->mRecordThread.clear(); 506a0169a073d88efefbfb35fa0ea8e94f7b31d7469Eric Laurent } 507a0169a073d88efefbfb35fa0ea8e94f7b31d7469Eric Laurent if (patch->mPlaybackThread != 0) { 508a0169a073d88efefbfb35fa0ea8e94f7b31d7469Eric Laurent if (patch->mPatchTrack != 0) { 509a0169a073d88efefbfb35fa0ea8e94f7b31d7469Eric Laurent patch->mPatchTrack.clear(); 510a0169a073d88efefbfb35fa0ea8e94f7b31d7469Eric Laurent } 51183b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent patch->mPlaybackThread.clear(); 51283b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent } 513a0169a073d88efefbfb35fa0ea8e94f7b31d7469Eric Laurent 51483b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent} 51583b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent 516951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent/* Disconnect a patch */ 517951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurentstatus_t AudioFlinger::PatchPanel::releaseAudioPatch(audio_patch_handle_t handle) 518951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent{ 519951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent ALOGV("releaseAudioPatch handle %d", handle); 520951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent status_t status = NO_ERROR; 521951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent size_t index; 522951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent 523951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent sp<AudioFlinger> audioflinger = mAudioFlinger.promote(); 524951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent if (audioflinger == 0) { 525951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent return NO_INIT; 526951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } 527951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent 528951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent for (index = 0; index < mPatches.size(); index++) { 529951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent if (handle == mPatches[index]->mHandle) { 530951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent break; 531951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } 532951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } 533951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent if (index == mPatches.size()) { 534951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent return BAD_VALUE; 535951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } 53683b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent Patch *removedPatch = mPatches[index]; 53783b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent mPatches.removeAt(index); 538951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent 53983b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent struct audio_patch *patch = &removedPatch->mAudioPatch; 540951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent 541951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent switch (patch->sources[0].type) { 542951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent case AUDIO_PORT_TYPE_DEVICE: { 543874c4287a4e49c59ac88767751dce00fcd3edb73Eric Laurent audio_module_handle_t srcModule = patch->sources[0].ext.device.hw_module; 544874c4287a4e49c59ac88767751dce00fcd3edb73Eric Laurent ssize_t index = audioflinger->mAudioHwDevs.indexOfKey(srcModule); 545951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent if (index < 0) { 546874c4287a4e49c59ac88767751dce00fcd3edb73Eric Laurent ALOGW("releaseAudioPatch() bad src hw module %d", srcModule); 547951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent status = BAD_VALUE; 548951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent break; 549951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } 55083b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent 5513bcf8597189c592713675ec58326ecbef0ac4ae9Eric Laurent if (removedPatch->mRecordPatchHandle != AUDIO_PATCH_HANDLE_NONE || 5523bcf8597189c592713675ec58326ecbef0ac4ae9Eric Laurent removedPatch->mPlaybackPatchHandle != AUDIO_PATCH_HANDLE_NONE) { 55383b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent clearPatchConnections(removedPatch); 55483b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent break; 55583b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent } 55683b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent 557054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent if (patch->sinks[0].type == AUDIO_PORT_TYPE_MIX) { 558951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent sp<ThreadBase> thread = audioflinger->checkRecordThread_l( 559054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent patch->sinks[0].ext.mix.handle); 560951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent if (thread == 0) { 561951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent ALOGW("releaseAudioPatch() bad capture I/O handle %d", 562054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent patch->sinks[0].ext.mix.handle); 563951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent status = BAD_VALUE; 564951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent break; 565951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } 566054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent status = thread->sendReleaseAudioPatchConfigEvent(removedPatch->mHalHandle); 567054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent } else { 568054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent AudioHwDevice *audioHwDevice = audioflinger->mAudioHwDevs.valueAt(index); 569054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent if (audioHwDevice->version() < AUDIO_DEVICE_API_VERSION_3_0) { 570054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent status = INVALID_OPERATION; 571054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent break; 572054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent } 573054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent audio_hw_device_t *hwDevice = audioHwDevice->hwDevice(); 574054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent status = hwDevice->release_audio_patch(hwDevice, removedPatch->mHalHandle); 575951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } 576951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } break; 577951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent case AUDIO_PORT_TYPE_MIX: { 578874c4287a4e49c59ac88767751dce00fcd3edb73Eric Laurent audio_module_handle_t srcModule = patch->sources[0].ext.mix.hw_module; 579874c4287a4e49c59ac88767751dce00fcd3edb73Eric Laurent ssize_t index = audioflinger->mAudioHwDevs.indexOfKey(srcModule); 580951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent if (index < 0) { 581874c4287a4e49c59ac88767751dce00fcd3edb73Eric Laurent ALOGW("releaseAudioPatch() bad src hw module %d", srcModule); 582951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent status = BAD_VALUE; 583951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent break; 584951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } 585951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent sp<ThreadBase> thread = 586951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent audioflinger->checkPlaybackThread_l(patch->sources[0].ext.mix.handle); 587951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent if (thread == 0) { 588951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent ALOGW("releaseAudioPatch() bad playback I/O handle %d", 589951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent patch->sources[0].ext.mix.handle); 590951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent status = BAD_VALUE; 591951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent break; 592951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } 593054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent status = thread->sendReleaseAudioPatchConfigEvent(removedPatch->mHalHandle); 594951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } break; 595951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent default: 596951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent status = BAD_VALUE; 597951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent break; 598951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } 599951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent 60083b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent delete removedPatch; 601951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent return status; 602951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent} 603951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent 604951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent 605951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent/* List connected audio ports and they attributes */ 606951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurentstatus_t AudioFlinger::PatchPanel::listAudioPatches(unsigned int *num_patches __unused, 607951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent struct audio_patch *patches __unused) 608951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent{ 609951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent ALOGV("listAudioPatches"); 610951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent return NO_ERROR; 611951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent} 612951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent 613951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent/* Set audio port configuration */ 614e1715a465a29db625da9d0ea365edf371e39e201Eric Laurentstatus_t AudioFlinger::PatchPanel::setAudioPortConfig(const struct audio_port_config *config) 615951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent{ 616951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent ALOGV("setAudioPortConfig"); 617e1715a465a29db625da9d0ea365edf371e39e201Eric Laurent status_t status = NO_ERROR; 618e1715a465a29db625da9d0ea365edf371e39e201Eric Laurent 619e1715a465a29db625da9d0ea365edf371e39e201Eric Laurent sp<AudioFlinger> audioflinger = mAudioFlinger.promote(); 620e1715a465a29db625da9d0ea365edf371e39e201Eric Laurent if (audioflinger == 0) { 621e1715a465a29db625da9d0ea365edf371e39e201Eric Laurent return NO_INIT; 622e1715a465a29db625da9d0ea365edf371e39e201Eric Laurent } 623e1715a465a29db625da9d0ea365edf371e39e201Eric Laurent 624e1715a465a29db625da9d0ea365edf371e39e201Eric Laurent audio_module_handle_t module; 625e1715a465a29db625da9d0ea365edf371e39e201Eric Laurent if (config->type == AUDIO_PORT_TYPE_DEVICE) { 626e1715a465a29db625da9d0ea365edf371e39e201Eric Laurent module = config->ext.device.hw_module; 627e1715a465a29db625da9d0ea365edf371e39e201Eric Laurent } else { 628e1715a465a29db625da9d0ea365edf371e39e201Eric Laurent module = config->ext.mix.hw_module; 629e1715a465a29db625da9d0ea365edf371e39e201Eric Laurent } 630e1715a465a29db625da9d0ea365edf371e39e201Eric Laurent 631e1715a465a29db625da9d0ea365edf371e39e201Eric Laurent ssize_t index = audioflinger->mAudioHwDevs.indexOfKey(module); 632e1715a465a29db625da9d0ea365edf371e39e201Eric Laurent if (index < 0) { 633e1715a465a29db625da9d0ea365edf371e39e201Eric Laurent ALOGW("setAudioPortConfig() bad hw module %d", module); 634e1715a465a29db625da9d0ea365edf371e39e201Eric Laurent return BAD_VALUE; 635e1715a465a29db625da9d0ea365edf371e39e201Eric Laurent } 636e1715a465a29db625da9d0ea365edf371e39e201Eric Laurent 637e1715a465a29db625da9d0ea365edf371e39e201Eric Laurent AudioHwDevice *audioHwDevice = audioflinger->mAudioHwDevs.valueAt(index); 638e1715a465a29db625da9d0ea365edf371e39e201Eric Laurent if (audioHwDevice->version() >= AUDIO_DEVICE_API_VERSION_3_0) { 639e1715a465a29db625da9d0ea365edf371e39e201Eric Laurent audio_hw_device_t *hwDevice = audioHwDevice->hwDevice(); 640e1715a465a29db625da9d0ea365edf371e39e201Eric Laurent return hwDevice->set_audio_port_config(hwDevice, config); 641e1715a465a29db625da9d0ea365edf371e39e201Eric Laurent } else { 642e1715a465a29db625da9d0ea365edf371e39e201Eric Laurent return INVALID_OPERATION; 643e1715a465a29db625da9d0ea365edf371e39e201Eric Laurent } 644951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent return NO_ERROR; 645951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent} 646951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent 64763238efb0d674758902918e3cdaac322126484b7Glenn Kasten} // namespace android 648