PatchPanel.cpp revision d8cd47792bac11a44096ef8233bb5268a6674bec
1951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent/* 2951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent** 3951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent** Copyright 2014, The Android Open Source Project 4951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent** 5951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent** Licensed under the Apache License, Version 2.0 (the "License"); 6951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent** you may not use this file except in compliance with the License. 7951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent** You may obtain a copy of the License at 8951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent** 9951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent** http://www.apache.org/licenses/LICENSE-2.0 10951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent** 11951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent** Unless required by applicable law or agreed to in writing, software 12951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent** distributed under the License is distributed on an "AS IS" BASIS, 13951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent** See the License for the specific language governing permissions and 15951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent** limitations under the License. 16951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent*/ 17951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent 18951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent 19951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent#define LOG_TAG "AudioFlinger::PatchPanel" 20951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent//#define LOG_NDEBUG 0 21951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent 22951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent#include "Configuration.h" 23951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent#include <utils/Log.h> 24951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent#include <audio_utils/primitives.h> 25951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent 26951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent#include "AudioFlinger.h" 27951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent#include "ServiceUtilities.h" 28951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent#include <media/AudioParameter.h> 29951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent 30951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent// ---------------------------------------------------------------------------- 31951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent 32951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent// Note: the following macro is used for extremely verbose logging message. In 33951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent// order to run with ALOG_ASSERT turned on, we need to have LOG_NDEBUG set to 34951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent// 0; but one side effect of this is to turn all LOGV's as well. Some messages 35951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent// are so verbose that we want to suppress them even when we have ALOG_ASSERT 36951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent// turned on. Do not uncomment the #def below unless you really know what you 37951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent// are doing and want to see all of the extremely verbose messages. 38951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent//#define VERY_VERY_VERBOSE_LOGGING 39951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent#ifdef VERY_VERY_VERBOSE_LOGGING 40951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent#define ALOGVV ALOGV 41951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent#else 42951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent#define ALOGVV(a...) do { } while(0) 43951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent#endif 44951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent 45951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurentnamespace android { 46951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent 47951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent/* List connected audio ports and their attributes */ 48951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurentstatus_t AudioFlinger::listAudioPorts(unsigned int *num_ports, 49951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent struct audio_port *ports) 50951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent{ 51951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent Mutex::Autolock _l(mLock); 52951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent if (mPatchPanel != 0) { 53951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent return mPatchPanel->listAudioPorts(num_ports, ports); 54951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } 55951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent return NO_INIT; 56951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent} 57951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent 58951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent/* Get supported attributes for a given audio port */ 59951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurentstatus_t AudioFlinger::getAudioPort(struct audio_port *port) 60951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent{ 61951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent Mutex::Autolock _l(mLock); 62951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent if (mPatchPanel != 0) { 63951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent return mPatchPanel->getAudioPort(port); 64951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } 65951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent return NO_INIT; 66951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent} 67951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent 68951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent 69951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent/* Connect a patch between several source and sink ports */ 70951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurentstatus_t AudioFlinger::createAudioPatch(const struct audio_patch *patch, 71951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent audio_patch_handle_t *handle) 72951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent{ 73951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent Mutex::Autolock _l(mLock); 74951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent if (mPatchPanel != 0) { 75951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent return mPatchPanel->createAudioPatch(patch, handle); 76951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } 77951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent return NO_INIT; 78951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent} 79951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent 80951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent/* Disconnect a patch */ 81951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurentstatus_t AudioFlinger::releaseAudioPatch(audio_patch_handle_t handle) 82951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent{ 83951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent Mutex::Autolock _l(mLock); 84951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent if (mPatchPanel != 0) { 85951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent return mPatchPanel->releaseAudioPatch(handle); 86951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } 87951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent return NO_INIT; 88951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent} 89951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent 90951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent 91951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent/* List connected audio ports and they attributes */ 92951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurentstatus_t AudioFlinger::listAudioPatches(unsigned int *num_patches, 93951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent struct audio_patch *patches) 94951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent{ 95951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent Mutex::Autolock _l(mLock); 96951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent if (mPatchPanel != 0) { 97951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent return mPatchPanel->listAudioPatches(num_patches, patches); 98951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } 99951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent return NO_INIT; 100951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent} 101951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent 102951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent/* Set audio port configuration */ 103951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurentstatus_t AudioFlinger::setAudioPortConfig(const struct audio_port_config *config) 104951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent{ 105951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent Mutex::Autolock _l(mLock); 106951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent if (mPatchPanel != 0) { 107951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent return mPatchPanel->setAudioPortConfig(config); 108951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } 109951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent return NO_INIT; 110951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent} 111951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent 112951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent 113951f455566775e5f01e67c5ee26863d7d19209d7Eric LaurentAudioFlinger::PatchPanel::PatchPanel(const sp<AudioFlinger>& audioFlinger) 114951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent : mAudioFlinger(audioFlinger) 115951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent{ 116951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent} 117951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent 118951f455566775e5f01e67c5ee26863d7d19209d7Eric LaurentAudioFlinger::PatchPanel::~PatchPanel() 119951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent{ 120951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent} 121951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent 122951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent/* List connected audio ports and their attributes */ 123951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurentstatus_t AudioFlinger::PatchPanel::listAudioPorts(unsigned int *num_ports __unused, 124951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent struct audio_port *ports __unused) 125951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent{ 126951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent ALOGV("listAudioPorts"); 127951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent return NO_ERROR; 128951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent} 129951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent 130951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent/* Get supported attributes for a given audio port */ 131951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurentstatus_t AudioFlinger::PatchPanel::getAudioPort(struct audio_port *port __unused) 132951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent{ 133951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent ALOGV("getAudioPort"); 134951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent return NO_ERROR; 135951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent} 136951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent 137951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent 138951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent/* Connect a patch between several source and sink ports */ 139951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurentstatus_t AudioFlinger::PatchPanel::createAudioPatch(const struct audio_patch *patch, 140951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent audio_patch_handle_t *handle) 141951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent{ 142951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent ALOGV("createAudioPatch() num_sources %d num_sinks %d handle %d", 143951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent patch->num_sources, patch->num_sinks, *handle); 144951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent status_t status = NO_ERROR; 145951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent audio_patch_handle_t halHandle = AUDIO_PATCH_HANDLE_NONE; 146951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent sp<AudioFlinger> audioflinger = mAudioFlinger.promote(); 147951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent if (audioflinger == 0) { 148951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent return NO_INIT; 149951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } 15083b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent 151951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent if (handle == NULL || patch == NULL) { 152951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent return BAD_VALUE; 153951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } 154874c4287a4e49c59ac88767751dce00fcd3edb73Eric Laurent if (patch->num_sources == 0 || patch->num_sources > AUDIO_PATCH_PORTS_MAX || 155951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent patch->num_sinks == 0 || patch->num_sinks > AUDIO_PATCH_PORTS_MAX) { 156951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent return BAD_VALUE; 157951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } 158874c4287a4e49c59ac88767751dce00fcd3edb73Eric Laurent // limit number of sources to 1 for now or 2 sources for special cross hw module case. 159874c4287a4e49c59ac88767751dce00fcd3edb73Eric Laurent // only the audio policy manager can request a patch creation with 2 sources. 160874c4287a4e49c59ac88767751dce00fcd3edb73Eric Laurent if (patch->num_sources > 2) { 161874c4287a4e49c59ac88767751dce00fcd3edb73Eric Laurent return INVALID_OPERATION; 162874c4287a4e49c59ac88767751dce00fcd3edb73Eric Laurent } 163951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent 16483b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent if (*handle != AUDIO_PATCH_HANDLE_NONE) { 16583b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent for (size_t index = 0; *handle != 0 && index < mPatches.size(); index++) { 16683b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent if (*handle == mPatches[index]->mHandle) { 16783b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent ALOGV("createAudioPatch() removing patch handle %d", *handle); 16883b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent halHandle = mPatches[index]->mHalHandle; 169d8cd47792bac11a44096ef8233bb5268a6674becsoon Patch *removedPatch = mPatches[index]; 17083b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent mPatches.removeAt(index); 171d8cd47792bac11a44096ef8233bb5268a6674becsoon delete removedPatch; 17283b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent break; 17383b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent } 174951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } 175951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } 176951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent 17783b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent Patch *newPatch = new Patch(patch); 17883b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent 179951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent switch (patch->sources[0].type) { 180951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent case AUDIO_PORT_TYPE_DEVICE: { 181874c4287a4e49c59ac88767751dce00fcd3edb73Eric Laurent audio_module_handle_t srcModule = patch->sources[0].ext.device.hw_module; 182874c4287a4e49c59ac88767751dce00fcd3edb73Eric Laurent ssize_t index = audioflinger->mAudioHwDevs.indexOfKey(srcModule); 183951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent if (index < 0) { 184874c4287a4e49c59ac88767751dce00fcd3edb73Eric Laurent ALOGW("createAudioPatch() bad src hw module %d", srcModule); 18583b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent status = BAD_VALUE; 18683b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent goto exit; 187951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } 1886a94d69dc4f32abb53c466a96f905bb199be6417Eric Laurent AudioHwDevice *audioHwDevice = audioflinger->mAudioHwDevs.valueAt(index); 189951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent for (unsigned int i = 0; i < patch->num_sinks; i++) { 190874c4287a4e49c59ac88767751dce00fcd3edb73Eric Laurent // support only one sink if connection to a mix or across HW modules 191874c4287a4e49c59ac88767751dce00fcd3edb73Eric Laurent if ((patch->sinks[i].type == AUDIO_PORT_TYPE_MIX || 192874c4287a4e49c59ac88767751dce00fcd3edb73Eric Laurent patch->sinks[i].ext.mix.hw_module != srcModule) && 193874c4287a4e49c59ac88767751dce00fcd3edb73Eric Laurent patch->num_sinks > 1) { 194874c4287a4e49c59ac88767751dce00fcd3edb73Eric Laurent status = INVALID_OPERATION; 195874c4287a4e49c59ac88767751dce00fcd3edb73Eric Laurent goto exit; 196874c4287a4e49c59ac88767751dce00fcd3edb73Eric Laurent } 1976a94d69dc4f32abb53c466a96f905bb199be6417Eric Laurent // reject connection to different sink types 1986a94d69dc4f32abb53c466a96f905bb199be6417Eric Laurent if (patch->sinks[i].type != patch->sinks[0].type) { 1996a94d69dc4f32abb53c466a96f905bb199be6417Eric Laurent ALOGW("createAudioPatch() different sink types in same patch not supported"); 20083b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent status = BAD_VALUE; 20183b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent goto exit; 202951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } 20383b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent // limit to connections between devices and input streams for HAL before 3.0 204874c4287a4e49c59ac88767751dce00fcd3edb73Eric Laurent if (patch->sinks[i].ext.mix.hw_module == srcModule && 20583b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent (audioHwDevice->version() < AUDIO_DEVICE_API_VERSION_3_0) && 2066a94d69dc4f32abb53c466a96f905bb199be6417Eric Laurent (patch->sinks[i].type != AUDIO_PORT_TYPE_MIX)) { 2076a94d69dc4f32abb53c466a96f905bb199be6417Eric Laurent ALOGW("createAudioPatch() invalid sink type %d for device source", 2086a94d69dc4f32abb53c466a96f905bb199be6417Eric Laurent patch->sinks[i].type); 20983b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent status = BAD_VALUE; 21083b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent goto exit; 2116a94d69dc4f32abb53c466a96f905bb199be6417Eric Laurent } 212951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } 213951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent 214874c4287a4e49c59ac88767751dce00fcd3edb73Eric Laurent if (patch->sinks[0].ext.device.hw_module != srcModule) { 21583b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent // limit to device to device connection if not on same hw module 21683b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent if (patch->sinks[0].type != AUDIO_PORT_TYPE_DEVICE) { 21783b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent ALOGW("createAudioPatch() invalid sink type for cross hw module"); 21883b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent status = INVALID_OPERATION; 21983b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent goto exit; 22083b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent } 22183b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent // special case num sources == 2 -=> reuse an exiting output mix to connect to the 22283b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent // sink 22383b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent if (patch->num_sources == 2) { 22483b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent if (patch->sources[1].type != AUDIO_PORT_TYPE_MIX || 22583b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent patch->sinks[0].ext.device.hw_module != 22683b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent patch->sources[1].ext.mix.hw_module) { 22783b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent ALOGW("createAudioPatch() invalid source combination"); 22883b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent status = INVALID_OPERATION; 22983b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent goto exit; 23083b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent } 23183b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent 23283b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent sp<ThreadBase> thread = 23383b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent audioflinger->checkPlaybackThread_l(patch->sources[1].ext.mix.handle); 23483b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent newPatch->mPlaybackThread = (MixerThread *)thread.get(); 235951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent if (thread == 0) { 23683b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent ALOGW("createAudioPatch() cannot get playback thread"); 23783b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent status = INVALID_OPERATION; 23883b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent goto exit; 239951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } 240951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } else { 241cf2c0210c8afbe7d0661ccbbae3835b5ce73c0bfEric Laurent audio_config_t config = AUDIO_CONFIG_INITIALIZER; 242cf2c0210c8afbe7d0661ccbbae3835b5ce73c0bfEric Laurent audio_devices_t device = patch->sinks[0].ext.device.type; 243cf2c0210c8afbe7d0661ccbbae3835b5ce73c0bfEric Laurent String8 address = String8(patch->sinks[0].ext.device.address); 244cf2c0210c8afbe7d0661ccbbae3835b5ce73c0bfEric Laurent audio_io_handle_t output = AUDIO_IO_HANDLE_NONE; 24583b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent newPatch->mPlaybackThread = audioflinger->openOutput_l( 24683b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent patch->sinks[0].ext.device.hw_module, 247cf2c0210c8afbe7d0661ccbbae3835b5ce73c0bfEric Laurent &output, 24883b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent &config, 249cf2c0210c8afbe7d0661ccbbae3835b5ce73c0bfEric Laurent device, 250cf2c0210c8afbe7d0661ccbbae3835b5ce73c0bfEric Laurent address, 25183b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent AUDIO_OUTPUT_FLAG_NONE); 25283b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent ALOGV("audioflinger->openOutput_l() returned %p", 25383b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent newPatch->mPlaybackThread.get()); 25483b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent if (newPatch->mPlaybackThread == 0) { 25583b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent status = NO_MEMORY; 25683b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent goto exit; 25783b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent } 25883b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent } 25983b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent uint32_t channelCount = newPatch->mPlaybackThread->channelCount(); 26083b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent audio_devices_t device = patch->sources[0].ext.device.type; 261cf2c0210c8afbe7d0661ccbbae3835b5ce73c0bfEric Laurent String8 address = String8(patch->sources[0].ext.device.address); 262cf2c0210c8afbe7d0661ccbbae3835b5ce73c0bfEric Laurent audio_config_t config = AUDIO_CONFIG_INITIALIZER; 26383b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent audio_channel_mask_t inChannelMask = audio_channel_in_mask_from_count(channelCount); 26483b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent config.sample_rate = newPatch->mPlaybackThread->sampleRate(); 26583b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent config.channel_mask = inChannelMask; 26683b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent config.format = newPatch->mPlaybackThread->format(); 267cf2c0210c8afbe7d0661ccbbae3835b5ce73c0bfEric Laurent audio_io_handle_t input = AUDIO_IO_HANDLE_NONE; 268874c4287a4e49c59ac88767751dce00fcd3edb73Eric Laurent newPatch->mRecordThread = audioflinger->openInput_l(srcModule, 269cf2c0210c8afbe7d0661ccbbae3835b5ce73c0bfEric Laurent &input, 27083b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent &config, 271cf2c0210c8afbe7d0661ccbbae3835b5ce73c0bfEric Laurent device, 272cf2c0210c8afbe7d0661ccbbae3835b5ce73c0bfEric Laurent address, 273cf2c0210c8afbe7d0661ccbbae3835b5ce73c0bfEric Laurent AUDIO_SOURCE_MIC, 27483b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent AUDIO_INPUT_FLAG_NONE); 27583b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent ALOGV("audioflinger->openInput_l() returned %p inChannelMask %08x", 27683b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent newPatch->mRecordThread.get(), inChannelMask); 27783b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent if (newPatch->mRecordThread == 0) { 27883b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent status = NO_MEMORY; 27983b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent goto exit; 28083b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent } 28183b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent status = createPatchConnections(newPatch, patch); 28283b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent if (status != NO_ERROR) { 28383b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent goto exit; 284951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } 285951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } else { 28683b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent if (audioHwDevice->version() >= AUDIO_DEVICE_API_VERSION_3_0) { 28783b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent if (patch->sinks[0].type == AUDIO_PORT_TYPE_MIX) { 28883b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent sp<ThreadBase> thread = audioflinger->checkRecordThread_l( 289874c4287a4e49c59ac88767751dce00fcd3edb73Eric Laurent patch->sinks[0].ext.mix.handle); 29083b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent if (thread == 0) { 29183b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent ALOGW("createAudioPatch() bad capture I/O handle %d", 292874c4287a4e49c59ac88767751dce00fcd3edb73Eric Laurent patch->sinks[0].ext.mix.handle); 29383b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent status = BAD_VALUE; 29483b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent goto exit; 29583b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent } 29683b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent status = thread->sendCreateAudioPatchConfigEvent(patch, &halHandle); 29783b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent } else { 29883b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent audio_hw_device_t *hwDevice = audioHwDevice->hwDevice(); 29983b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent status = hwDevice->create_audio_patch(hwDevice, 30083b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent patch->num_sources, 30183b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent patch->sources, 30283b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent patch->num_sinks, 30383b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent patch->sinks, 30483b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent &halHandle); 30583b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent } 30683b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent } else { 30783b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent sp<ThreadBase> thread = audioflinger->checkRecordThread_l( 308874c4287a4e49c59ac88767751dce00fcd3edb73Eric Laurent patch->sinks[0].ext.mix.handle); 30983b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent if (thread == 0) { 31083b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent ALOGW("createAudioPatch() bad capture I/O handle %d", 311874c4287a4e49c59ac88767751dce00fcd3edb73Eric Laurent patch->sinks[0].ext.mix.handle); 31283b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent status = BAD_VALUE; 31383b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent goto exit; 31483b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent } 315cf2c0210c8afbe7d0661ccbbae3835b5ce73c0bfEric Laurent char *address; 316cf2c0210c8afbe7d0661ccbbae3835b5ce73c0bfEric Laurent if (strcmp(patch->sources[0].ext.device.address, "") != 0) { 317cf2c0210c8afbe7d0661ccbbae3835b5ce73c0bfEric Laurent address = audio_device_address_to_parameter( 318cf2c0210c8afbe7d0661ccbbae3835b5ce73c0bfEric Laurent patch->sources[0].ext.device.type, 319cf2c0210c8afbe7d0661ccbbae3835b5ce73c0bfEric Laurent patch->sources[0].ext.device.address); 320cf2c0210c8afbe7d0661ccbbae3835b5ce73c0bfEric Laurent } else { 321cf2c0210c8afbe7d0661ccbbae3835b5ce73c0bfEric Laurent address = (char *)calloc(1, 1); 322cf2c0210c8afbe7d0661ccbbae3835b5ce73c0bfEric Laurent } 323cf2c0210c8afbe7d0661ccbbae3835b5ce73c0bfEric Laurent AudioParameter param = AudioParameter(String8(address)); 324cf2c0210c8afbe7d0661ccbbae3835b5ce73c0bfEric Laurent free(address); 325cf2c0210c8afbe7d0661ccbbae3835b5ce73c0bfEric Laurent param.addInt(String8(AUDIO_PARAMETER_STREAM_ROUTING), 32683b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent (int)patch->sources[0].ext.device.type); 327cf2c0210c8afbe7d0661ccbbae3835b5ce73c0bfEric Laurent param.addInt(String8(AUDIO_PARAMETER_STREAM_INPUT_SOURCE), 328cf2c0210c8afbe7d0661ccbbae3835b5ce73c0bfEric Laurent (int)patch->sinks[0].ext.mix.usecase.source); 32983b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent ALOGV("createAudioPatch() AUDIO_PORT_TYPE_DEVICE setParameters %s", 330cf2c0210c8afbe7d0661ccbbae3835b5ce73c0bfEric Laurent param.toString().string()); 33183b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent status = thread->setParameters(param.toString()); 332951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } 333951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } 334951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } break; 335951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent case AUDIO_PORT_TYPE_MIX: { 336874c4287a4e49c59ac88767751dce00fcd3edb73Eric Laurent audio_module_handle_t srcModule = patch->sources[0].ext.mix.hw_module; 337874c4287a4e49c59ac88767751dce00fcd3edb73Eric Laurent ssize_t index = audioflinger->mAudioHwDevs.indexOfKey(srcModule); 338951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent if (index < 0) { 339874c4287a4e49c59ac88767751dce00fcd3edb73Eric Laurent ALOGW("createAudioPatch() bad src hw module %d", srcModule); 34083b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent status = BAD_VALUE; 34183b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent goto exit; 342951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } 343951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent // limit to connections between devices and output streams 344951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent for (unsigned int i = 0; i < patch->num_sinks; i++) { 345951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent if (patch->sinks[i].type != AUDIO_PORT_TYPE_DEVICE) { 34683b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent ALOGW("createAudioPatch() invalid sink type %d for mix source", 347951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent patch->sinks[i].type); 34883b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent status = BAD_VALUE; 34983b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent goto exit; 350951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } 351951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent // limit to connections between sinks and sources on same HW module 352874c4287a4e49c59ac88767751dce00fcd3edb73Eric Laurent if (patch->sinks[i].ext.device.hw_module != srcModule) { 35383b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent status = BAD_VALUE; 35483b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent goto exit; 355951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } 356951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } 357951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent AudioHwDevice *audioHwDevice = audioflinger->mAudioHwDevs.valueAt(index); 358951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent sp<ThreadBase> thread = 359951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent audioflinger->checkPlaybackThread_l(patch->sources[0].ext.mix.handle); 360951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent if (thread == 0) { 361951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent ALOGW("createAudioPatch() bad playback I/O handle %d", 362951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent patch->sources[0].ext.mix.handle); 36383b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent status = BAD_VALUE; 36483b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent goto exit; 365951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } 366951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent if (audioHwDevice->version() >= AUDIO_DEVICE_API_VERSION_3_0) { 367951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent status = thread->sendCreateAudioPatchConfigEvent(patch, &halHandle); 368951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } else { 369951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent audio_devices_t type = AUDIO_DEVICE_NONE; 370951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent for (unsigned int i = 0; i < patch->num_sinks; i++) { 371951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent type |= patch->sinks[i].ext.device.type; 372951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } 373cf2c0210c8afbe7d0661ccbbae3835b5ce73c0bfEric Laurent char *address; 374cf2c0210c8afbe7d0661ccbbae3835b5ce73c0bfEric Laurent if (strcmp(patch->sinks[0].ext.device.address, "") != 0) { 375874c4287a4e49c59ac88767751dce00fcd3edb73Eric Laurent //FIXME: we only support address on first sink with HAL version < 3.0 376cf2c0210c8afbe7d0661ccbbae3835b5ce73c0bfEric Laurent address = audio_device_address_to_parameter( 377cf2c0210c8afbe7d0661ccbbae3835b5ce73c0bfEric Laurent patch->sinks[0].ext.device.type, 378cf2c0210c8afbe7d0661ccbbae3835b5ce73c0bfEric Laurent patch->sinks[0].ext.device.address); 379cf2c0210c8afbe7d0661ccbbae3835b5ce73c0bfEric Laurent } else { 380cf2c0210c8afbe7d0661ccbbae3835b5ce73c0bfEric Laurent address = (char *)calloc(1, 1); 381cf2c0210c8afbe7d0661ccbbae3835b5ce73c0bfEric Laurent } 382cf2c0210c8afbe7d0661ccbbae3835b5ce73c0bfEric Laurent AudioParameter param = AudioParameter(String8(address)); 383cf2c0210c8afbe7d0661ccbbae3835b5ce73c0bfEric Laurent free(address); 384cf2c0210c8afbe7d0661ccbbae3835b5ce73c0bfEric Laurent param.addInt(String8(AUDIO_PARAMETER_STREAM_ROUTING), (int)type); 385951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent status = thread->setParameters(param.toString()); 386951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } 387951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent 388951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } break; 389951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent default: 39083b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent status = BAD_VALUE; 39183b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent goto exit; 392951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } 39383b8808faad1e91690c64d7007348be8d9ebde73Eric Laurentexit: 394951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent ALOGV("createAudioPatch() status %d", status); 395951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent if (status == NO_ERROR) { 396951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent *handle = audioflinger->nextUniqueId(); 397951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent newPatch->mHandle = *handle; 398951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent newPatch->mHalHandle = halHandle; 399951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent mPatches.add(newPatch); 400951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent ALOGV("createAudioPatch() added new patch handle %d halHandle %d", *handle, halHandle); 40183b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent } else { 40283b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent clearPatchConnections(newPatch); 40383b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent delete newPatch; 40483b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent } 40583b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent return status; 40683b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent} 40783b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent 40883b8808faad1e91690c64d7007348be8d9ebde73Eric Laurentstatus_t AudioFlinger::PatchPanel::createPatchConnections(Patch *patch, 40983b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent const struct audio_patch *audioPatch) 41083b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent{ 41183b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent // create patch from source device to record thread input 41283b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent struct audio_patch subPatch; 41383b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent subPatch.num_sources = 1; 41483b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent subPatch.sources[0] = audioPatch->sources[0]; 41583b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent subPatch.num_sinks = 1; 41683b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent 41783b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent patch->mRecordThread->getAudioPortConfig(&subPatch.sinks[0]); 41883b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent subPatch.sinks[0].ext.mix.usecase.source = AUDIO_SOURCE_MIC; 41983b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent 42083b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent status_t status = createAudioPatch(&subPatch, &patch->mRecordPatchHandle); 42183b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent if (status != NO_ERROR) { 42283b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent patch->mRecordPatchHandle = AUDIO_PATCH_HANDLE_NONE; 42383b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent return status; 42483b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent } 42583b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent 42683b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent // create patch from playback thread output to sink device 42783b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent patch->mPlaybackThread->getAudioPortConfig(&subPatch.sources[0]); 42883b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent subPatch.sinks[0] = audioPatch->sinks[0]; 42983b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent status = createAudioPatch(&subPatch, &patch->mPlaybackPatchHandle); 43083b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent if (status != NO_ERROR) { 43183b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent patch->mPlaybackPatchHandle = AUDIO_PATCH_HANDLE_NONE; 43283b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent return status; 43383b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent } 43483b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent 43583b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent // use a pseudo LCM between input and output framecount 43683b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent size_t playbackFrameCount = patch->mPlaybackThread->frameCount(); 43783b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent int playbackShift = __builtin_ctz(playbackFrameCount); 43883b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent size_t recordFramecount = patch->mRecordThread->frameCount(); 43983b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent int shift = __builtin_ctz(recordFramecount); 44083b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent if (playbackShift < shift) { 44183b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent shift = playbackShift; 44283b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent } 44383b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent size_t frameCount = (playbackFrameCount * recordFramecount) >> shift; 44483b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent ALOGV("createPatchConnections() playframeCount %d recordFramecount %d frameCount %d ", 44583b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent playbackFrameCount, recordFramecount, frameCount); 44683b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent 44783b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent // create a special record track to capture from record thread 44883b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent uint32_t channelCount = patch->mPlaybackThread->channelCount(); 44983b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent audio_channel_mask_t inChannelMask = audio_channel_in_mask_from_count(channelCount); 45083b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent audio_channel_mask_t outChannelMask = patch->mPlaybackThread->channelMask(); 45183b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent uint32_t sampleRate = patch->mPlaybackThread->sampleRate(); 45283b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent audio_format_t format = patch->mPlaybackThread->format(); 45383b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent 45483b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent patch->mPatchRecord = new RecordThread::PatchRecord( 45583b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent patch->mRecordThread.get(), 45683b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent sampleRate, 45783b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent inChannelMask, 45883b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent format, 45983b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent frameCount, 46083b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent NULL, 46183b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent IAudioFlinger::TRACK_DEFAULT); 46283b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent if (patch->mPatchRecord == 0) { 46383b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent return NO_MEMORY; 46483b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent } 46583b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent status = patch->mPatchRecord->initCheck(); 46683b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent if (status != NO_ERROR) { 46783b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent return status; 468951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } 46983b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent patch->mRecordThread->addPatchRecord(patch->mPatchRecord); 47083b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent 47183b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent // create a special playback track to render to playback thread. 47283b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent // this track is given the same buffer as the PatchRecord buffer 47383b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent patch->mPatchTrack = new PlaybackThread::PatchTrack( 47483b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent patch->mPlaybackThread.get(), 47583b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent sampleRate, 47683b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent outChannelMask, 47783b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent format, 47883b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent frameCount, 47983b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent patch->mPatchRecord->buffer(), 48083b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent IAudioFlinger::TRACK_DEFAULT); 48183b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent if (patch->mPatchTrack == 0) { 48283b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent return NO_MEMORY; 48383b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent } 48483b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent status = patch->mPatchTrack->initCheck(); 48583b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent if (status != NO_ERROR) { 48683b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent return status; 48783b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent } 48883b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent patch->mPlaybackThread->addPatchTrack(patch->mPatchTrack); 48983b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent 49083b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent // tie playback and record tracks together 49183b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent patch->mPatchRecord->setPeerProxy(patch->mPatchTrack.get()); 49283b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent patch->mPatchTrack->setPeerProxy(patch->mPatchRecord.get()); 49383b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent 49483b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent // start capture and playback 49583b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent patch->mPatchRecord->start(AudioSystem::SYNC_EVENT_NONE, 0); 49683b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent patch->mPatchTrack->start(); 49783b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent 498951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent return status; 499951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent} 500951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent 50183b8808faad1e91690c64d7007348be8d9ebde73Eric Laurentvoid AudioFlinger::PatchPanel::clearPatchConnections(Patch *patch) 50283b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent{ 50383b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent sp<AudioFlinger> audioflinger = mAudioFlinger.promote(); 50483b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent if (audioflinger == 0) { 50583b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent return; 50683b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent } 50783b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent 50883b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent ALOGV("clearPatchConnections() patch->mRecordPatchHandle %d patch->mPlaybackPatchHandle %d", 50983b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent patch->mRecordPatchHandle, patch->mPlaybackPatchHandle); 51083b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent 51183b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent if (patch->mPatchRecord != 0) { 51283b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent patch->mPatchRecord->stop(); 51383b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent } 51483b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent if (patch->mPatchTrack != 0) { 51583b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent patch->mPatchTrack->stop(); 51683b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent } 51783b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent if (patch->mRecordPatchHandle != AUDIO_PATCH_HANDLE_NONE) { 51883b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent releaseAudioPatch(patch->mRecordPatchHandle); 51983b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent patch->mRecordPatchHandle = AUDIO_PATCH_HANDLE_NONE; 52083b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent } 52183b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent if (patch->mPlaybackPatchHandle != AUDIO_PATCH_HANDLE_NONE) { 52283b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent releaseAudioPatch(patch->mPlaybackPatchHandle); 52383b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent patch->mPlaybackPatchHandle = AUDIO_PATCH_HANDLE_NONE; 52483b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent } 52583b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent if (patch->mRecordThread != 0) { 52683b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent if (patch->mPatchRecord != 0) { 52783b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent patch->mRecordThread->deletePatchRecord(patch->mPatchRecord); 52883b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent patch->mPatchRecord.clear(); 52983b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent } 53083b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent audioflinger->closeInputInternal_l(patch->mRecordThread); 53183b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent patch->mRecordThread.clear(); 53283b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent } 53383b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent if (patch->mPlaybackThread != 0) { 53483b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent if (patch->mPatchTrack != 0) { 53583b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent patch->mPlaybackThread->deletePatchTrack(patch->mPatchTrack); 53683b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent patch->mPatchTrack.clear(); 53783b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent } 53883b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent // if num sources == 2 we are reusing an existing playback thread so we do not close it 53983b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent if (patch->mAudioPatch.num_sources != 2) { 54083b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent audioflinger->closeOutputInternal_l(patch->mPlaybackThread); 54183b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent } 54283b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent patch->mPlaybackThread.clear(); 54383b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent } 54483b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent} 54583b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent 546951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent/* Disconnect a patch */ 547951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurentstatus_t AudioFlinger::PatchPanel::releaseAudioPatch(audio_patch_handle_t handle) 548951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent{ 549951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent ALOGV("releaseAudioPatch handle %d", handle); 550951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent status_t status = NO_ERROR; 551951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent size_t index; 552951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent 553951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent sp<AudioFlinger> audioflinger = mAudioFlinger.promote(); 554951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent if (audioflinger == 0) { 555951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent return NO_INIT; 556951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } 557951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent 558951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent for (index = 0; index < mPatches.size(); index++) { 559951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent if (handle == mPatches[index]->mHandle) { 560951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent break; 561951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } 562951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } 563951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent if (index == mPatches.size()) { 564951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent return BAD_VALUE; 565951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } 56683b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent Patch *removedPatch = mPatches[index]; 56783b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent mPatches.removeAt(index); 568951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent 56983b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent struct audio_patch *patch = &removedPatch->mAudioPatch; 570951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent 571951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent switch (patch->sources[0].type) { 572951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent case AUDIO_PORT_TYPE_DEVICE: { 573874c4287a4e49c59ac88767751dce00fcd3edb73Eric Laurent audio_module_handle_t srcModule = patch->sources[0].ext.device.hw_module; 574874c4287a4e49c59ac88767751dce00fcd3edb73Eric Laurent ssize_t index = audioflinger->mAudioHwDevs.indexOfKey(srcModule); 575951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent if (index < 0) { 576874c4287a4e49c59ac88767751dce00fcd3edb73Eric Laurent ALOGW("releaseAudioPatch() bad src hw module %d", srcModule); 577951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent status = BAD_VALUE; 578951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent break; 579951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } 58083b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent 58183b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent if (patch->sinks[0].type == AUDIO_PORT_TYPE_DEVICE && 582874c4287a4e49c59ac88767751dce00fcd3edb73Eric Laurent patch->sinks[0].ext.device.hw_module != srcModule) { 58383b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent clearPatchConnections(removedPatch); 58483b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent break; 58583b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent } 58683b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent 587951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent AudioHwDevice *audioHwDevice = audioflinger->mAudioHwDevs.valueAt(index); 588951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent if (audioHwDevice->version() >= AUDIO_DEVICE_API_VERSION_3_0) { 589951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent if (patch->sinks[0].type == AUDIO_PORT_TYPE_MIX) { 590951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent sp<ThreadBase> thread = audioflinger->checkRecordThread_l( 591951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent patch->sinks[0].ext.mix.handle); 592951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent if (thread == 0) { 59383b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent ALOGW("releaseAudioPatch() bad capture I/O handle %d", 594951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent patch->sinks[0].ext.mix.handle); 595951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent status = BAD_VALUE; 596951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent break; 597951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } 598f8fd8d6daab5ced86ce950be68070d27c24d487fEric Laurent status = thread->sendReleaseAudioPatchConfigEvent(removedPatch->mHalHandle); 599951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } else { 600951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent audio_hw_device_t *hwDevice = audioHwDevice->hwDevice(); 601f8fd8d6daab5ced86ce950be68070d27c24d487fEric Laurent status = hwDevice->release_audio_patch(hwDevice, removedPatch->mHalHandle); 602951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } 603951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } else { 604951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent sp<ThreadBase> thread = audioflinger->checkRecordThread_l( 605951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent patch->sinks[0].ext.mix.handle); 606951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent if (thread == 0) { 607951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent ALOGW("releaseAudioPatch() bad capture I/O handle %d", 608951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent patch->sinks[0].ext.mix.handle); 609951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent status = BAD_VALUE; 610951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent break; 611951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } 612951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent AudioParameter param; 613cf2c0210c8afbe7d0661ccbbae3835b5ce73c0bfEric Laurent param.addInt(String8(AUDIO_PARAMETER_STREAM_ROUTING), 0); 61424478d47fc631ab33208f4dd9d034abb6839c992Eric Laurent ALOGV("releaseAudioPatch() AUDIO_PORT_TYPE_DEVICE setParameters %s", 615951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent param.toString().string()); 616951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent status = thread->setParameters(param.toString()); 617951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } 618951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } break; 619951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent case AUDIO_PORT_TYPE_MIX: { 620874c4287a4e49c59ac88767751dce00fcd3edb73Eric Laurent audio_module_handle_t srcModule = patch->sources[0].ext.mix.hw_module; 621874c4287a4e49c59ac88767751dce00fcd3edb73Eric Laurent ssize_t index = audioflinger->mAudioHwDevs.indexOfKey(srcModule); 622951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent if (index < 0) { 623874c4287a4e49c59ac88767751dce00fcd3edb73Eric Laurent ALOGW("releaseAudioPatch() bad src hw module %d", srcModule); 624951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent status = BAD_VALUE; 625951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent break; 626951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } 627951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent sp<ThreadBase> thread = 628951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent audioflinger->checkPlaybackThread_l(patch->sources[0].ext.mix.handle); 629951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent if (thread == 0) { 630951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent ALOGW("releaseAudioPatch() bad playback I/O handle %d", 631951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent patch->sources[0].ext.mix.handle); 632951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent status = BAD_VALUE; 633951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent break; 634951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } 635951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent AudioHwDevice *audioHwDevice = audioflinger->mAudioHwDevs.valueAt(index); 636951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent if (audioHwDevice->version() >= AUDIO_DEVICE_API_VERSION_3_0) { 637f8fd8d6daab5ced86ce950be68070d27c24d487fEric Laurent status = thread->sendReleaseAudioPatchConfigEvent(removedPatch->mHalHandle); 638951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } else { 639951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent AudioParameter param; 640cf2c0210c8afbe7d0661ccbbae3835b5ce73c0bfEric Laurent param.addInt(String8(AUDIO_PARAMETER_STREAM_ROUTING), 0); 641951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent status = thread->setParameters(param.toString()); 642951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } 643951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } break; 644951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent default: 645951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent status = BAD_VALUE; 646951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent break; 647951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent } 648951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent 64983b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent delete removedPatch; 650951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent return status; 651951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent} 652951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent 653951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent 654951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent/* List connected audio ports and they attributes */ 655951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurentstatus_t AudioFlinger::PatchPanel::listAudioPatches(unsigned int *num_patches __unused, 656951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent struct audio_patch *patches __unused) 657951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent{ 658951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent ALOGV("listAudioPatches"); 659951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent return NO_ERROR; 660951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent} 661951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent 662951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent/* Set audio port configuration */ 663e1715a465a29db625da9d0ea365edf371e39e201Eric Laurentstatus_t AudioFlinger::PatchPanel::setAudioPortConfig(const struct audio_port_config *config) 664951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent{ 665951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent ALOGV("setAudioPortConfig"); 666e1715a465a29db625da9d0ea365edf371e39e201Eric Laurent status_t status = NO_ERROR; 667e1715a465a29db625da9d0ea365edf371e39e201Eric Laurent 668e1715a465a29db625da9d0ea365edf371e39e201Eric Laurent sp<AudioFlinger> audioflinger = mAudioFlinger.promote(); 669e1715a465a29db625da9d0ea365edf371e39e201Eric Laurent if (audioflinger == 0) { 670e1715a465a29db625da9d0ea365edf371e39e201Eric Laurent return NO_INIT; 671e1715a465a29db625da9d0ea365edf371e39e201Eric Laurent } 672e1715a465a29db625da9d0ea365edf371e39e201Eric Laurent 673e1715a465a29db625da9d0ea365edf371e39e201Eric Laurent audio_module_handle_t module; 674e1715a465a29db625da9d0ea365edf371e39e201Eric Laurent if (config->type == AUDIO_PORT_TYPE_DEVICE) { 675e1715a465a29db625da9d0ea365edf371e39e201Eric Laurent module = config->ext.device.hw_module; 676e1715a465a29db625da9d0ea365edf371e39e201Eric Laurent } else { 677e1715a465a29db625da9d0ea365edf371e39e201Eric Laurent module = config->ext.mix.hw_module; 678e1715a465a29db625da9d0ea365edf371e39e201Eric Laurent } 679e1715a465a29db625da9d0ea365edf371e39e201Eric Laurent 680e1715a465a29db625da9d0ea365edf371e39e201Eric Laurent ssize_t index = audioflinger->mAudioHwDevs.indexOfKey(module); 681e1715a465a29db625da9d0ea365edf371e39e201Eric Laurent if (index < 0) { 682e1715a465a29db625da9d0ea365edf371e39e201Eric Laurent ALOGW("setAudioPortConfig() bad hw module %d", module); 683e1715a465a29db625da9d0ea365edf371e39e201Eric Laurent return BAD_VALUE; 684e1715a465a29db625da9d0ea365edf371e39e201Eric Laurent } 685e1715a465a29db625da9d0ea365edf371e39e201Eric Laurent 686e1715a465a29db625da9d0ea365edf371e39e201Eric Laurent AudioHwDevice *audioHwDevice = audioflinger->mAudioHwDevs.valueAt(index); 687e1715a465a29db625da9d0ea365edf371e39e201Eric Laurent if (audioHwDevice->version() >= AUDIO_DEVICE_API_VERSION_3_0) { 688e1715a465a29db625da9d0ea365edf371e39e201Eric Laurent audio_hw_device_t *hwDevice = audioHwDevice->hwDevice(); 689e1715a465a29db625da9d0ea365edf371e39e201Eric Laurent return hwDevice->set_audio_port_config(hwDevice, config); 690e1715a465a29db625da9d0ea365edf371e39e201Eric Laurent } else { 691e1715a465a29db625da9d0ea365edf371e39e201Eric Laurent return INVALID_OPERATION; 692e1715a465a29db625da9d0ea365edf371e39e201Eric Laurent } 693951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent return NO_ERROR; 694951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent} 695951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent 696951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent 697951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent}; // namespace android 698