1951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent/*
2951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent**
3951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent** Copyright 2014, The Android Open Source Project
4951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent**
5951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent** Licensed under the Apache License, Version 2.0 (the "License");
6951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent** you may not use this file except in compliance with the License.
7951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent** You may obtain a copy of the License at
8951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent**
9951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent**     http://www.apache.org/licenses/LICENSE-2.0
10951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent**
11951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent** Unless required by applicable law or agreed to in writing, software
12951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent** distributed under the License is distributed on an "AS IS" BASIS,
13951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent** See the License for the specific language governing permissions and
15951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent** limitations under the License.
16951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent*/
17951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent
18951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent
19951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent#define LOG_TAG "AudioFlinger::PatchPanel"
20951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent//#define LOG_NDEBUG 0
21951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent
22951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent#include "Configuration.h"
23951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent#include <utils/Log.h>
24951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent#include <audio_utils/primitives.h>
25951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent
26951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent#include "AudioFlinger.h"
27951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent#include "ServiceUtilities.h"
28951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent#include <media/AudioParameter.h>
29951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent
30951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent// ----------------------------------------------------------------------------
31951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent
32951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent// Note: the following macro is used for extremely verbose logging message.  In
33951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent// order to run with ALOG_ASSERT turned on, we need to have LOG_NDEBUG set to
34951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent// 0; but one side effect of this is to turn all LOGV's as well.  Some messages
35951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent// are so verbose that we want to suppress them even when we have ALOG_ASSERT
36951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent// turned on.  Do not uncomment the #def below unless you really know what you
37951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent// are doing and want to see all of the extremely verbose messages.
38951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent//#define VERY_VERY_VERBOSE_LOGGING
39951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent#ifdef VERY_VERY_VERBOSE_LOGGING
40951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent#define ALOGVV ALOGV
41951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent#else
42951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent#define ALOGVV(a...) do { } while(0)
43951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent#endif
44951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent
45951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurentnamespace android {
46951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent
47951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent/* List connected audio ports and their attributes */
48951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurentstatus_t AudioFlinger::listAudioPorts(unsigned int *num_ports,
49951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent                                struct audio_port *ports)
50951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent{
51951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent    Mutex::Autolock _l(mLock);
52951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent    if (mPatchPanel != 0) {
53951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent        return mPatchPanel->listAudioPorts(num_ports, ports);
54951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent    }
55951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent    return NO_INIT;
56951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent}
57951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent
58951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent/* Get supported attributes for a given audio port */
59951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurentstatus_t AudioFlinger::getAudioPort(struct audio_port *port)
60951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent{
61951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent    Mutex::Autolock _l(mLock);
62951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent    if (mPatchPanel != 0) {
63951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent        return mPatchPanel->getAudioPort(port);
64951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent    }
65951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent    return NO_INIT;
66951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent}
67951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent
68951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent
69951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent/* Connect a patch between several source and sink ports */
70951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurentstatus_t AudioFlinger::createAudioPatch(const struct audio_patch *patch,
71951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent                                   audio_patch_handle_t *handle)
72951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent{
73951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent    Mutex::Autolock _l(mLock);
74951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent    if (mPatchPanel != 0) {
75951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent        return mPatchPanel->createAudioPatch(patch, handle);
76951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent    }
77951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent    return NO_INIT;
78951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent}
79951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent
80951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent/* Disconnect a patch */
81951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurentstatus_t AudioFlinger::releaseAudioPatch(audio_patch_handle_t handle)
82951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent{
83951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent    Mutex::Autolock _l(mLock);
84951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent    if (mPatchPanel != 0) {
85951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent        return mPatchPanel->releaseAudioPatch(handle);
86951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent    }
87951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent    return NO_INIT;
88951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent}
89951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent
90951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent
91951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent/* List connected audio ports and they attributes */
92951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurentstatus_t AudioFlinger::listAudioPatches(unsigned int *num_patches,
93951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent                                  struct audio_patch *patches)
94951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent{
95951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent    Mutex::Autolock _l(mLock);
96951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent    if (mPatchPanel != 0) {
97951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent        return mPatchPanel->listAudioPatches(num_patches, patches);
98951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent    }
99951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent    return NO_INIT;
100951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent}
101951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent
102951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent/* Set audio port configuration */
103951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurentstatus_t AudioFlinger::setAudioPortConfig(const struct audio_port_config *config)
104951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent{
105951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent    Mutex::Autolock _l(mLock);
106951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent    if (mPatchPanel != 0) {
107951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent        return mPatchPanel->setAudioPortConfig(config);
108951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent    }
109951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent    return NO_INIT;
110951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent}
111951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent
112951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent
113951f455566775e5f01e67c5ee26863d7d19209d7Eric LaurentAudioFlinger::PatchPanel::PatchPanel(const sp<AudioFlinger>& audioFlinger)
114951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent                                   : mAudioFlinger(audioFlinger)
115951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent{
116951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent}
117951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent
118951f455566775e5f01e67c5ee26863d7d19209d7Eric LaurentAudioFlinger::PatchPanel::~PatchPanel()
119951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent{
120951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent}
121951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent
122951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent/* List connected audio ports and their attributes */
123951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurentstatus_t AudioFlinger::PatchPanel::listAudioPorts(unsigned int *num_ports __unused,
124951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent                                struct audio_port *ports __unused)
125951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent{
126951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent    ALOGV("listAudioPorts");
127951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent    return NO_ERROR;
128951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent}
129951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent
130951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent/* Get supported attributes for a given audio port */
131951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurentstatus_t AudioFlinger::PatchPanel::getAudioPort(struct audio_port *port __unused)
132951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent{
133951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent    ALOGV("getAudioPort");
134951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent    return NO_ERROR;
135951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent}
136951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent
137951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent
138951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent/* Connect a patch between several source and sink ports */
139951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurentstatus_t AudioFlinger::PatchPanel::createAudioPatch(const struct audio_patch *patch,
140951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent                                   audio_patch_handle_t *handle)
141951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent{
142951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent    status_t status = NO_ERROR;
143951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent    audio_patch_handle_t halHandle = AUDIO_PATCH_HANDLE_NONE;
144951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent    sp<AudioFlinger> audioflinger = mAudioFlinger.promote();
145f27ce4051c81a90f8f937a1b381e9e6ffa2bfa6bGreg Kaiser    if (handle == NULL || patch == NULL) {
146f27ce4051c81a90f8f937a1b381e9e6ffa2bfa6bGreg Kaiser        return BAD_VALUE;
147f27ce4051c81a90f8f937a1b381e9e6ffa2bfa6bGreg Kaiser    }
148f27ce4051c81a90f8f937a1b381e9e6ffa2bfa6bGreg Kaiser    ALOGV("createAudioPatch() num_sources %d num_sinks %d handle %d",
149f27ce4051c81a90f8f937a1b381e9e6ffa2bfa6bGreg Kaiser          patch->num_sources, patch->num_sinks, *handle);
150951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent    if (audioflinger == 0) {
151951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent        return NO_INIT;
152951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent    }
15383b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent
154874c4287a4e49c59ac88767751dce00fcd3edb73Eric Laurent    if (patch->num_sources == 0 || patch->num_sources > AUDIO_PATCH_PORTS_MAX ||
155d60560af7cb559762593161c8202459cc01fb0f5Eric Laurent            (patch->num_sinks == 0 && patch->num_sources != 2) ||
156d60560af7cb559762593161c8202459cc01fb0f5Eric Laurent            patch->num_sinks > AUDIO_PATCH_PORTS_MAX) {
157951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent        return BAD_VALUE;
158951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent    }
159874c4287a4e49c59ac88767751dce00fcd3edb73Eric Laurent    // limit number of sources to 1 for now or 2 sources for special cross hw module case.
160874c4287a4e49c59ac88767751dce00fcd3edb73Eric Laurent    // only the audio policy manager can request a patch creation with 2 sources.
161874c4287a4e49c59ac88767751dce00fcd3edb73Eric Laurent    if (patch->num_sources > 2) {
162874c4287a4e49c59ac88767751dce00fcd3edb73Eric Laurent        return INVALID_OPERATION;
163874c4287a4e49c59ac88767751dce00fcd3edb73Eric Laurent    }
164951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent
16583b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent    if (*handle != AUDIO_PATCH_HANDLE_NONE) {
16683b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent        for (size_t index = 0; *handle != 0 && index < mPatches.size(); index++) {
16783b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent            if (*handle == mPatches[index]->mHandle) {
16883b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent                ALOGV("createAudioPatch() removing patch handle %d", *handle);
16983b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent                halHandle = mPatches[index]->mHalHandle;
170d8cd47792bac11a44096ef8233bb5268a6674becsoon                Patch *removedPatch = mPatches[index];
171b997d3a3d61a86dc9525860e863c7b690356d405Eric Laurent                // free resources owned by the removed patch if applicable
172b997d3a3d61a86dc9525860e863c7b690356d405Eric Laurent                // 1) if a software patch is present, release the playback and capture threads and
173b997d3a3d61a86dc9525860e863c7b690356d405Eric Laurent                // tracks created. This will also release the corresponding audio HAL patches
1740666cc5b6b430cc5a815dab0bcba3dd73da8061aEric Laurent                if ((removedPatch->mRecordPatchHandle
1750666cc5b6b430cc5a815dab0bcba3dd73da8061aEric Laurent                        != AUDIO_PATCH_HANDLE_NONE) ||
1760666cc5b6b430cc5a815dab0bcba3dd73da8061aEric Laurent                        (removedPatch->mPlaybackPatchHandle !=
1770666cc5b6b430cc5a815dab0bcba3dd73da8061aEric Laurent                                AUDIO_PATCH_HANDLE_NONE)) {
1780666cc5b6b430cc5a815dab0bcba3dd73da8061aEric Laurent                    clearPatchConnections(removedPatch);
1790666cc5b6b430cc5a815dab0bcba3dd73da8061aEric Laurent                }
180b997d3a3d61a86dc9525860e863c7b690356d405Eric Laurent                // 2) if the new patch and old patch source or sink are devices from different
181b997d3a3d61a86dc9525860e863c7b690356d405Eric Laurent                // hw modules,  clear the audio HAL patches now because they will not be updated
182b997d3a3d61a86dc9525860e863c7b690356d405Eric Laurent                // by call to create_audio_patch() below which will happen on a different HW module
183b997d3a3d61a86dc9525860e863c7b690356d405Eric Laurent                if (halHandle != AUDIO_PATCH_HANDLE_NONE) {
184b997d3a3d61a86dc9525860e863c7b690356d405Eric Laurent                    audio_module_handle_t hwModule = AUDIO_MODULE_HANDLE_NONE;
185b997d3a3d61a86dc9525860e863c7b690356d405Eric Laurent                    if ((removedPatch->mAudioPatch.sources[0].type == AUDIO_PORT_TYPE_DEVICE) &&
186b997d3a3d61a86dc9525860e863c7b690356d405Eric Laurent                        ((patch->sources[0].type != AUDIO_PORT_TYPE_DEVICE) ||
187b997d3a3d61a86dc9525860e863c7b690356d405Eric Laurent                          (removedPatch->mAudioPatch.sources[0].ext.device.hw_module !=
188b997d3a3d61a86dc9525860e863c7b690356d405Eric Laurent                           patch->sources[0].ext.device.hw_module))) {
189b997d3a3d61a86dc9525860e863c7b690356d405Eric Laurent                        hwModule = removedPatch->mAudioPatch.sources[0].ext.device.hw_module;
190b997d3a3d61a86dc9525860e863c7b690356d405Eric Laurent                    } else if ((patch->num_sinks == 0) ||
191b997d3a3d61a86dc9525860e863c7b690356d405Eric Laurent                            ((removedPatch->mAudioPatch.sinks[0].type == AUDIO_PORT_TYPE_DEVICE) &&
192b997d3a3d61a86dc9525860e863c7b690356d405Eric Laurent                             ((patch->sinks[0].type != AUDIO_PORT_TYPE_DEVICE) ||
193b997d3a3d61a86dc9525860e863c7b690356d405Eric Laurent                              (removedPatch->mAudioPatch.sinks[0].ext.device.hw_module !=
194b997d3a3d61a86dc9525860e863c7b690356d405Eric Laurent                               patch->sinks[0].ext.device.hw_module)))) {
195b997d3a3d61a86dc9525860e863c7b690356d405Eric Laurent                        // Note on (patch->num_sinks == 0): this situation should not happen as
196b997d3a3d61a86dc9525860e863c7b690356d405Eric Laurent                        // these special patches are only created by the policy manager but just
197b997d3a3d61a86dc9525860e863c7b690356d405Eric Laurent                        // in case, systematically clear the HAL patch.
198b997d3a3d61a86dc9525860e863c7b690356d405Eric Laurent                        // Note that removedPatch->mAudioPatch.num_sinks cannot be 0 here because
199b997d3a3d61a86dc9525860e863c7b690356d405Eric Laurent                        // halHandle would be AUDIO_PATCH_HANDLE_NONE in this case.
200b997d3a3d61a86dc9525860e863c7b690356d405Eric Laurent                        hwModule = removedPatch->mAudioPatch.sinks[0].ext.device.hw_module;
201b997d3a3d61a86dc9525860e863c7b690356d405Eric Laurent                    }
202b997d3a3d61a86dc9525860e863c7b690356d405Eric Laurent                    if (hwModule != AUDIO_MODULE_HANDLE_NONE) {
203b997d3a3d61a86dc9525860e863c7b690356d405Eric Laurent                        ssize_t index = audioflinger->mAudioHwDevs.indexOfKey(hwModule);
204b997d3a3d61a86dc9525860e863c7b690356d405Eric Laurent                        if (index >= 0) {
205b997d3a3d61a86dc9525860e863c7b690356d405Eric Laurent                            audio_hw_device_t *hwDevice =
206b997d3a3d61a86dc9525860e863c7b690356d405Eric Laurent                                    audioflinger->mAudioHwDevs.valueAt(index)->hwDevice();
207b997d3a3d61a86dc9525860e863c7b690356d405Eric Laurent                            hwDevice->release_audio_patch(hwDevice, halHandle);
208b997d3a3d61a86dc9525860e863c7b690356d405Eric Laurent                        }
209b997d3a3d61a86dc9525860e863c7b690356d405Eric Laurent                    }
210b997d3a3d61a86dc9525860e863c7b690356d405Eric Laurent                }
21183b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent                mPatches.removeAt(index);
212d8cd47792bac11a44096ef8233bb5268a6674becsoon                delete removedPatch;
21383b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent                break;
21483b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent            }
215951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent        }
216951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent    }
217951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent
21883b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent    Patch *newPatch = new Patch(patch);
21983b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent
220951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent    switch (patch->sources[0].type) {
221951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent        case AUDIO_PORT_TYPE_DEVICE: {
222874c4287a4e49c59ac88767751dce00fcd3edb73Eric Laurent            audio_module_handle_t srcModule = patch->sources[0].ext.device.hw_module;
223874c4287a4e49c59ac88767751dce00fcd3edb73Eric Laurent            ssize_t index = audioflinger->mAudioHwDevs.indexOfKey(srcModule);
224951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent            if (index < 0) {
225874c4287a4e49c59ac88767751dce00fcd3edb73Eric Laurent                ALOGW("createAudioPatch() bad src hw module %d", srcModule);
22683b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent                status = BAD_VALUE;
22783b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent                goto exit;
228951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent            }
2296a94d69dc4f32abb53c466a96f905bb199be6417Eric Laurent            AudioHwDevice *audioHwDevice = audioflinger->mAudioHwDevs.valueAt(index);
230951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent            for (unsigned int i = 0; i < patch->num_sinks; i++) {
231874c4287a4e49c59ac88767751dce00fcd3edb73Eric Laurent                // support only one sink if connection to a mix or across HW modules
232874c4287a4e49c59ac88767751dce00fcd3edb73Eric Laurent                if ((patch->sinks[i].type == AUDIO_PORT_TYPE_MIX ||
233874c4287a4e49c59ac88767751dce00fcd3edb73Eric Laurent                        patch->sinks[i].ext.mix.hw_module != srcModule) &&
234874c4287a4e49c59ac88767751dce00fcd3edb73Eric Laurent                        patch->num_sinks > 1) {
235874c4287a4e49c59ac88767751dce00fcd3edb73Eric Laurent                    status = INVALID_OPERATION;
236874c4287a4e49c59ac88767751dce00fcd3edb73Eric Laurent                    goto exit;
237874c4287a4e49c59ac88767751dce00fcd3edb73Eric Laurent                }
2386a94d69dc4f32abb53c466a96f905bb199be6417Eric Laurent                // reject connection to different sink types
2396a94d69dc4f32abb53c466a96f905bb199be6417Eric Laurent                if (patch->sinks[i].type != patch->sinks[0].type) {
2406a94d69dc4f32abb53c466a96f905bb199be6417Eric Laurent                    ALOGW("createAudioPatch() different sink types in same patch not supported");
24183b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent                    status = BAD_VALUE;
24283b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent                    goto exit;
243951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent                }
244951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent            }
245951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent
2463bcf8597189c592713675ec58326ecbef0ac4ae9Eric Laurent            // manage patches requiring a software bridge
247d60560af7cb559762593161c8202459cc01fb0f5Eric Laurent            // - special patch request with 2 sources (reuse one existing output mix) OR
2483bcf8597189c592713675ec58326ecbef0ac4ae9Eric Laurent            // - Device to device AND
2493bcf8597189c592713675ec58326ecbef0ac4ae9Eric Laurent            //    - source HW module != destination HW module OR
2503bcf8597189c592713675ec58326ecbef0ac4ae9Eric Laurent            //    - audio HAL version < 3.0
251d60560af7cb559762593161c8202459cc01fb0f5Eric Laurent            if ((patch->num_sources == 2) ||
252d60560af7cb559762593161c8202459cc01fb0f5Eric Laurent                ((patch->sinks[0].type == AUDIO_PORT_TYPE_DEVICE) &&
253d60560af7cb559762593161c8202459cc01fb0f5Eric Laurent                 ((patch->sinks[0].ext.device.hw_module != srcModule) ||
254d60560af7cb559762593161c8202459cc01fb0f5Eric Laurent                  (audioHwDevice->version() < AUDIO_DEVICE_API_VERSION_3_0)))) {
25583b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent                if (patch->num_sources == 2) {
25683b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent                    if (patch->sources[1].type != AUDIO_PORT_TYPE_MIX ||
257d60560af7cb559762593161c8202459cc01fb0f5Eric Laurent                            (patch->num_sinks != 0 && patch->sinks[0].ext.device.hw_module !=
258d60560af7cb559762593161c8202459cc01fb0f5Eric Laurent                                    patch->sources[1].ext.mix.hw_module)) {
25983b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent                        ALOGW("createAudioPatch() invalid source combination");
26083b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent                        status = INVALID_OPERATION;
26183b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent                        goto exit;
26283b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent                    }
26383b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent
26483b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent                    sp<ThreadBase> thread =
26583b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent                            audioflinger->checkPlaybackThread_l(patch->sources[1].ext.mix.handle);
26683b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent                    newPatch->mPlaybackThread = (MixerThread *)thread.get();
267951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent                    if (thread == 0) {
26883b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent                        ALOGW("createAudioPatch() cannot get playback thread");
26983b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent                        status = INVALID_OPERATION;
27083b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent                        goto exit;
271951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent                    }
272951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent                } else {
273cf2c0210c8afbe7d0661ccbbae3835b5ce73c0bfEric Laurent                    audio_config_t config = AUDIO_CONFIG_INITIALIZER;
274cf2c0210c8afbe7d0661ccbbae3835b5ce73c0bfEric Laurent                    audio_devices_t device = patch->sinks[0].ext.device.type;
275cf2c0210c8afbe7d0661ccbbae3835b5ce73c0bfEric Laurent                    String8 address = String8(patch->sinks[0].ext.device.address);
276cf2c0210c8afbe7d0661ccbbae3835b5ce73c0bfEric Laurent                    audio_io_handle_t output = AUDIO_IO_HANDLE_NONE;
27783b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent                    newPatch->mPlaybackThread = audioflinger->openOutput_l(
27883b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent                                                             patch->sinks[0].ext.device.hw_module,
279cf2c0210c8afbe7d0661ccbbae3835b5ce73c0bfEric Laurent                                                             &output,
28083b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent                                                             &config,
281cf2c0210c8afbe7d0661ccbbae3835b5ce73c0bfEric Laurent                                                             device,
282cf2c0210c8afbe7d0661ccbbae3835b5ce73c0bfEric Laurent                                                             address,
28383b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent                                                             AUDIO_OUTPUT_FLAG_NONE);
28483b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent                    ALOGV("audioflinger->openOutput_l() returned %p",
28583b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent                                          newPatch->mPlaybackThread.get());
28683b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent                    if (newPatch->mPlaybackThread == 0) {
28783b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent                        status = NO_MEMORY;
28883b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent                        goto exit;
28983b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent                    }
29083b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent                }
29183b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent                audio_devices_t device = patch->sources[0].ext.device.type;
292cf2c0210c8afbe7d0661ccbbae3835b5ce73c0bfEric Laurent                String8 address = String8(patch->sources[0].ext.device.address);
293cf2c0210c8afbe7d0661ccbbae3835b5ce73c0bfEric Laurent                audio_config_t config = AUDIO_CONFIG_INITIALIZER;
2948ae73129e7e79d826b293238c2f037f723d0e6e8Eric Laurent                // open input stream with source device audio properties if provided or
2958ae73129e7e79d826b293238c2f037f723d0e6e8Eric Laurent                // default to peer output stream properties otherwise.
2968ae73129e7e79d826b293238c2f037f723d0e6e8Eric Laurent                if (patch->sources[0].config_mask & AUDIO_PORT_CONFIG_SAMPLE_RATE) {
2978ae73129e7e79d826b293238c2f037f723d0e6e8Eric Laurent                    config.sample_rate = patch->sources[0].sample_rate;
2988ae73129e7e79d826b293238c2f037f723d0e6e8Eric Laurent                } else {
2998ae73129e7e79d826b293238c2f037f723d0e6e8Eric Laurent                    config.sample_rate = newPatch->mPlaybackThread->sampleRate();
3008ae73129e7e79d826b293238c2f037f723d0e6e8Eric Laurent                }
3018ae73129e7e79d826b293238c2f037f723d0e6e8Eric Laurent                if (patch->sources[0].config_mask & AUDIO_PORT_CONFIG_CHANNEL_MASK) {
3028ae73129e7e79d826b293238c2f037f723d0e6e8Eric Laurent                    config.channel_mask = patch->sources[0].channel_mask;
3038ae73129e7e79d826b293238c2f037f723d0e6e8Eric Laurent                } else {
3048ae73129e7e79d826b293238c2f037f723d0e6e8Eric Laurent                    config.channel_mask =
3058ae73129e7e79d826b293238c2f037f723d0e6e8Eric Laurent                        audio_channel_in_mask_from_count(newPatch->mPlaybackThread->channelCount());
3068ae73129e7e79d826b293238c2f037f723d0e6e8Eric Laurent                }
3078ae73129e7e79d826b293238c2f037f723d0e6e8Eric Laurent                if (patch->sources[0].config_mask & AUDIO_PORT_CONFIG_FORMAT) {
3088ae73129e7e79d826b293238c2f037f723d0e6e8Eric Laurent                    config.format = patch->sources[0].format;
3098ae73129e7e79d826b293238c2f037f723d0e6e8Eric Laurent                } else {
3108ae73129e7e79d826b293238c2f037f723d0e6e8Eric Laurent                    config.format = newPatch->mPlaybackThread->format();
3118ae73129e7e79d826b293238c2f037f723d0e6e8Eric Laurent                }
312cf2c0210c8afbe7d0661ccbbae3835b5ce73c0bfEric Laurent                audio_io_handle_t input = AUDIO_IO_HANDLE_NONE;
313874c4287a4e49c59ac88767751dce00fcd3edb73Eric Laurent                newPatch->mRecordThread = audioflinger->openInput_l(srcModule,
314cf2c0210c8afbe7d0661ccbbae3835b5ce73c0bfEric Laurent                                                                    &input,
31583b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent                                                                    &config,
316cf2c0210c8afbe7d0661ccbbae3835b5ce73c0bfEric Laurent                                                                    device,
317cf2c0210c8afbe7d0661ccbbae3835b5ce73c0bfEric Laurent                                                                    address,
318cf2c0210c8afbe7d0661ccbbae3835b5ce73c0bfEric Laurent                                                                    AUDIO_SOURCE_MIC,
31983b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent                                                                    AUDIO_INPUT_FLAG_NONE);
32083b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent                ALOGV("audioflinger->openInput_l() returned %p inChannelMask %08x",
3218ae73129e7e79d826b293238c2f037f723d0e6e8Eric Laurent                      newPatch->mRecordThread.get(), config.channel_mask);
32283b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent                if (newPatch->mRecordThread == 0) {
32383b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent                    status = NO_MEMORY;
32483b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent                    goto exit;
32583b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent                }
32683b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent                status = createPatchConnections(newPatch, patch);
32783b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent                if (status != NO_ERROR) {
32883b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent                    goto exit;
329951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent                }
330951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent            } else {
331054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent                if (patch->sinks[0].type == AUDIO_PORT_TYPE_MIX) {
33283b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent                    sp<ThreadBase> thread = audioflinger->checkRecordThread_l(
333054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent                                                              patch->sinks[0].ext.mix.handle);
33483b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent                    if (thread == 0) {
33583b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent                        ALOGW("createAudioPatch() bad capture I/O handle %d",
336054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent                                                              patch->sinks[0].ext.mix.handle);
33783b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent                        status = BAD_VALUE;
33883b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent                        goto exit;
33983b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent                    }
340054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent                    status = thread->sendCreateAudioPatchConfigEvent(patch, &halHandle);
341054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent                } else {
342054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent                    if (audioHwDevice->version() < AUDIO_DEVICE_API_VERSION_3_0) {
343054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent                        status = INVALID_OPERATION;
344054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent                        goto exit;
345cf2c0210c8afbe7d0661ccbbae3835b5ce73c0bfEric Laurent                    }
346054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent
347054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent                    audio_hw_device_t *hwDevice = audioHwDevice->hwDevice();
348054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent                    status = hwDevice->create_audio_patch(hwDevice,
349054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent                                                           patch->num_sources,
350054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent                                                           patch->sources,
351054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent                                                           patch->num_sinks,
352054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent                                                           patch->sinks,
353054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent                                                           &halHandle);
354951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent                }
355951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent            }
356951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent        } break;
357951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent        case AUDIO_PORT_TYPE_MIX: {
358874c4287a4e49c59ac88767751dce00fcd3edb73Eric Laurent            audio_module_handle_t srcModule =  patch->sources[0].ext.mix.hw_module;
359874c4287a4e49c59ac88767751dce00fcd3edb73Eric Laurent            ssize_t index = audioflinger->mAudioHwDevs.indexOfKey(srcModule);
360951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent            if (index < 0) {
361874c4287a4e49c59ac88767751dce00fcd3edb73Eric Laurent                ALOGW("createAudioPatch() bad src hw module %d", srcModule);
36283b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent                status = BAD_VALUE;
36383b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent                goto exit;
364951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent            }
365951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent            // limit to connections between devices and output streams
366054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent            audio_devices_t type = AUDIO_DEVICE_NONE;
367951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent            for (unsigned int i = 0; i < patch->num_sinks; i++) {
368951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent                if (patch->sinks[i].type != AUDIO_PORT_TYPE_DEVICE) {
36983b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent                    ALOGW("createAudioPatch() invalid sink type %d for mix source",
370951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent                          patch->sinks[i].type);
37183b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent                    status = BAD_VALUE;
37283b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent                    goto exit;
373951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent                }
374951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent                // limit to connections between sinks and sources on same HW module
375874c4287a4e49c59ac88767751dce00fcd3edb73Eric Laurent                if (patch->sinks[i].ext.device.hw_module != srcModule) {
37683b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent                    status = BAD_VALUE;
37783b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent                    goto exit;
378951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent                }
379054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent                type |= patch->sinks[i].ext.device.type;
380951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent            }
381951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent            sp<ThreadBase> thread =
382951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent                            audioflinger->checkPlaybackThread_l(patch->sources[0].ext.mix.handle);
383951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent            if (thread == 0) {
384951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent                ALOGW("createAudioPatch() bad playback I/O handle %d",
385951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent                          patch->sources[0].ext.mix.handle);
38683b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent                status = BAD_VALUE;
38783b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent                goto exit;
388951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent            }
389054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent            if (thread == audioflinger->primaryPlaybackThread_l()) {
390054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent                AudioParameter param = AudioParameter();
391cf2c0210c8afbe7d0661ccbbae3835b5ce73c0bfEric Laurent                param.addInt(String8(AUDIO_PARAMETER_STREAM_ROUTING), (int)type);
392054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent
393054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent                audioflinger->broacastParametersToRecordThreads_l(param.toString());
394951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent            }
395951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent
396054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent            status = thread->sendCreateAudioPatchConfigEvent(patch, &halHandle);
397951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent        } break;
398951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent        default:
39983b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent            status = BAD_VALUE;
40083b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent            goto exit;
401951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent    }
40283b8808faad1e91690c64d7007348be8d9ebde73Eric Laurentexit:
403951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent    ALOGV("createAudioPatch() status %d", status);
404951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent    if (status == NO_ERROR) {
405a13cde98a880341f0a56d91da6364b093fb5d24eGlenn Kasten        *handle = (audio_patch_handle_t) audioflinger->nextUniqueId(AUDIO_UNIQUE_ID_USE_PATCH);
406951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent        newPatch->mHandle = *handle;
407951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent        newPatch->mHalHandle = halHandle;
408951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent        mPatches.add(newPatch);
409951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent        ALOGV("createAudioPatch() added new patch handle %d halHandle %d", *handle, halHandle);
41083b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent    } else {
41183b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent        clearPatchConnections(newPatch);
41283b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent        delete newPatch;
41383b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent    }
41483b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent    return status;
41583b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent}
41683b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent
41783b8808faad1e91690c64d7007348be8d9ebde73Eric Laurentstatus_t AudioFlinger::PatchPanel::createPatchConnections(Patch *patch,
41883b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent                                                          const struct audio_patch *audioPatch)
41983b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent{
42083b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent    // create patch from source device to record thread input
42183b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent    struct audio_patch subPatch;
42283b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent    subPatch.num_sources = 1;
42383b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent    subPatch.sources[0] = audioPatch->sources[0];
42483b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent    subPatch.num_sinks = 1;
42583b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent
42683b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent    patch->mRecordThread->getAudioPortConfig(&subPatch.sinks[0]);
42783b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent    subPatch.sinks[0].ext.mix.usecase.source = AUDIO_SOURCE_MIC;
42883b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent
42983b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent    status_t status = createAudioPatch(&subPatch, &patch->mRecordPatchHandle);
43083b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent    if (status != NO_ERROR) {
43183b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent        patch->mRecordPatchHandle = AUDIO_PATCH_HANDLE_NONE;
43283b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent        return status;
43383b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent    }
43483b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent
43583b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent    // create patch from playback thread output to sink device
436d60560af7cb559762593161c8202459cc01fb0f5Eric Laurent    if (audioPatch->num_sinks != 0) {
437d60560af7cb559762593161c8202459cc01fb0f5Eric Laurent        patch->mPlaybackThread->getAudioPortConfig(&subPatch.sources[0]);
438d60560af7cb559762593161c8202459cc01fb0f5Eric Laurent        subPatch.sinks[0] = audioPatch->sinks[0];
439d60560af7cb559762593161c8202459cc01fb0f5Eric Laurent        status = createAudioPatch(&subPatch, &patch->mPlaybackPatchHandle);
440d60560af7cb559762593161c8202459cc01fb0f5Eric Laurent        if (status != NO_ERROR) {
441d60560af7cb559762593161c8202459cc01fb0f5Eric Laurent            patch->mPlaybackPatchHandle = AUDIO_PATCH_HANDLE_NONE;
442d60560af7cb559762593161c8202459cc01fb0f5Eric Laurent            return status;
443d60560af7cb559762593161c8202459cc01fb0f5Eric Laurent        }
444d60560af7cb559762593161c8202459cc01fb0f5Eric Laurent    } else {
44583b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent        patch->mPlaybackPatchHandle = AUDIO_PATCH_HANDLE_NONE;
44683b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent    }
44783b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent
44883b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent    // use a pseudo LCM between input and output framecount
44983b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent    size_t playbackFrameCount = patch->mPlaybackThread->frameCount();
45083b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent    int playbackShift = __builtin_ctz(playbackFrameCount);
45183b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent    size_t recordFramecount = patch->mRecordThread->frameCount();
45283b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent    int shift = __builtin_ctz(recordFramecount);
45383b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent    if (playbackShift < shift) {
45483b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent        shift = playbackShift;
45583b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent    }
45683b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent    size_t frameCount = (playbackFrameCount * recordFramecount) >> shift;
457c42e9b462661673dff480ee71757a58b0f806370Glenn Kasten    ALOGV("createPatchConnections() playframeCount %zu recordFramecount %zu frameCount %zu",
45883b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent          playbackFrameCount, recordFramecount, frameCount);
45983b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent
46083b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent    // create a special record track to capture from record thread
46183b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent    uint32_t channelCount = patch->mPlaybackThread->channelCount();
46283b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent    audio_channel_mask_t inChannelMask = audio_channel_in_mask_from_count(channelCount);
46383b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent    audio_channel_mask_t outChannelMask = patch->mPlaybackThread->channelMask();
46483b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent    uint32_t sampleRate = patch->mPlaybackThread->sampleRate();
46583b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent    audio_format_t format = patch->mPlaybackThread->format();
46683b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent
46783b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent    patch->mPatchRecord = new RecordThread::PatchRecord(
46883b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent                                             patch->mRecordThread.get(),
46983b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent                                             sampleRate,
47083b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent                                             inChannelMask,
47183b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent                                             format,
47283b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent                                             frameCount,
47383b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent                                             NULL,
474050677873c10d4da308ac222f8533c96cca3207eEric Laurent                                             AUDIO_INPUT_FLAG_NONE);
47583b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent    if (patch->mPatchRecord == 0) {
47683b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent        return NO_MEMORY;
47783b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent    }
47883b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent    status = patch->mPatchRecord->initCheck();
47983b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent    if (status != NO_ERROR) {
48083b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent        return status;
481951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent    }
48283b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent    patch->mRecordThread->addPatchRecord(patch->mPatchRecord);
48383b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent
48483b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent    // create a special playback track to render to playback thread.
48583b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent    // this track is given the same buffer as the PatchRecord buffer
48683b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent    patch->mPatchTrack = new PlaybackThread::PatchTrack(
48783b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent                                           patch->mPlaybackThread.get(),
4883bcf8597189c592713675ec58326ecbef0ac4ae9Eric Laurent                                           audioPatch->sources[1].ext.mix.usecase.stream,
48983b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent                                           sampleRate,
49083b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent                                           outChannelMask,
49183b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent                                           format,
49283b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent                                           frameCount,
49383b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent                                           patch->mPatchRecord->buffer(),
494050677873c10d4da308ac222f8533c96cca3207eEric Laurent                                           AUDIO_OUTPUT_FLAG_NONE);
49583b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent    if (patch->mPatchTrack == 0) {
49683b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent        return NO_MEMORY;
49783b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent    }
49883b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent    status = patch->mPatchTrack->initCheck();
49983b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent    if (status != NO_ERROR) {
50083b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent        return status;
50183b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent    }
50283b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent    patch->mPlaybackThread->addPatchTrack(patch->mPatchTrack);
50383b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent
50483b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent    // tie playback and record tracks together
50583b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent    patch->mPatchRecord->setPeerProxy(patch->mPatchTrack.get());
50683b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent    patch->mPatchTrack->setPeerProxy(patch->mPatchRecord.get());
50783b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent
50883b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent    // start capture and playback
509d848eb48c121c119e8ba7583efc75415fe102570Glenn Kasten    patch->mPatchRecord->start(AudioSystem::SYNC_EVENT_NONE, AUDIO_SESSION_NONE);
51083b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent    patch->mPatchTrack->start();
51183b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent
512951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent    return status;
513951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent}
514951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent
51583b8808faad1e91690c64d7007348be8d9ebde73Eric Laurentvoid AudioFlinger::PatchPanel::clearPatchConnections(Patch *patch)
51683b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent{
51783b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent    sp<AudioFlinger> audioflinger = mAudioFlinger.promote();
51883b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent    if (audioflinger == 0) {
51983b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent        return;
52083b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent    }
52183b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent
52283b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent    ALOGV("clearPatchConnections() patch->mRecordPatchHandle %d patch->mPlaybackPatchHandle %d",
52383b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent          patch->mRecordPatchHandle, patch->mPlaybackPatchHandle);
52483b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent
52583b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent    if (patch->mPatchRecord != 0) {
52683b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent        patch->mPatchRecord->stop();
52783b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent    }
52883b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent    if (patch->mPatchTrack != 0) {
52983b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent        patch->mPatchTrack->stop();
53083b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent    }
53183b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent    if (patch->mRecordPatchHandle != AUDIO_PATCH_HANDLE_NONE) {
53283b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent        releaseAudioPatch(patch->mRecordPatchHandle);
53383b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent        patch->mRecordPatchHandle = AUDIO_PATCH_HANDLE_NONE;
53483b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent    }
53583b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent    if (patch->mPlaybackPatchHandle != AUDIO_PATCH_HANDLE_NONE) {
53683b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent        releaseAudioPatch(patch->mPlaybackPatchHandle);
53783b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent        patch->mPlaybackPatchHandle = AUDIO_PATCH_HANDLE_NONE;
53883b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent    }
53983b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent    if (patch->mRecordThread != 0) {
54083b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent        if (patch->mPatchRecord != 0) {
54183b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent            patch->mRecordThread->deletePatchRecord(patch->mPatchRecord);
54283b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent        }
54383b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent        audioflinger->closeInputInternal_l(patch->mRecordThread);
54483b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent    }
54583b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent    if (patch->mPlaybackThread != 0) {
54683b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent        if (patch->mPatchTrack != 0) {
54783b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent            patch->mPlaybackThread->deletePatchTrack(patch->mPatchTrack);
54883b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent        }
54983b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent        // if num sources == 2 we are reusing an existing playback thread so we do not close it
55083b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent        if (patch->mAudioPatch.num_sources != 2) {
55183b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent            audioflinger->closeOutputInternal_l(patch->mPlaybackThread);
55283b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent        }
553a0169a073d88efefbfb35fa0ea8e94f7b31d7469Eric Laurent    }
554a0169a073d88efefbfb35fa0ea8e94f7b31d7469Eric Laurent    if (patch->mRecordThread != 0) {
555a0169a073d88efefbfb35fa0ea8e94f7b31d7469Eric Laurent        if (patch->mPatchRecord != 0) {
556a0169a073d88efefbfb35fa0ea8e94f7b31d7469Eric Laurent            patch->mPatchRecord.clear();
557a0169a073d88efefbfb35fa0ea8e94f7b31d7469Eric Laurent        }
558a0169a073d88efefbfb35fa0ea8e94f7b31d7469Eric Laurent        patch->mRecordThread.clear();
559a0169a073d88efefbfb35fa0ea8e94f7b31d7469Eric Laurent    }
560a0169a073d88efefbfb35fa0ea8e94f7b31d7469Eric Laurent    if (patch->mPlaybackThread != 0) {
561a0169a073d88efefbfb35fa0ea8e94f7b31d7469Eric Laurent        if (patch->mPatchTrack != 0) {
562a0169a073d88efefbfb35fa0ea8e94f7b31d7469Eric Laurent            patch->mPatchTrack.clear();
563a0169a073d88efefbfb35fa0ea8e94f7b31d7469Eric Laurent        }
56483b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent        patch->mPlaybackThread.clear();
56583b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent    }
566a0169a073d88efefbfb35fa0ea8e94f7b31d7469Eric Laurent
56783b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent}
56883b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent
569951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent/* Disconnect a patch */
570951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurentstatus_t AudioFlinger::PatchPanel::releaseAudioPatch(audio_patch_handle_t handle)
571951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent{
572951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent    ALOGV("releaseAudioPatch handle %d", handle);
573951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent    status_t status = NO_ERROR;
574951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent    size_t index;
575951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent
576951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent    sp<AudioFlinger> audioflinger = mAudioFlinger.promote();
577951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent    if (audioflinger == 0) {
578951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent        return NO_INIT;
579951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent    }
580951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent
581951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent    for (index = 0; index < mPatches.size(); index++) {
582951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent        if (handle == mPatches[index]->mHandle) {
583951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent            break;
584951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent        }
585951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent    }
586951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent    if (index == mPatches.size()) {
587951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent        return BAD_VALUE;
588951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent    }
58983b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent    Patch *removedPatch = mPatches[index];
59083b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent    mPatches.removeAt(index);
591951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent
59283b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent    struct audio_patch *patch = &removedPatch->mAudioPatch;
593951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent
594951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent    switch (patch->sources[0].type) {
595951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent        case AUDIO_PORT_TYPE_DEVICE: {
596874c4287a4e49c59ac88767751dce00fcd3edb73Eric Laurent            audio_module_handle_t srcModule = patch->sources[0].ext.device.hw_module;
597874c4287a4e49c59ac88767751dce00fcd3edb73Eric Laurent            ssize_t index = audioflinger->mAudioHwDevs.indexOfKey(srcModule);
598951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent            if (index < 0) {
599874c4287a4e49c59ac88767751dce00fcd3edb73Eric Laurent                ALOGW("releaseAudioPatch() bad src hw module %d", srcModule);
600951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent                status = BAD_VALUE;
601951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent                break;
602951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent            }
60383b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent
6043bcf8597189c592713675ec58326ecbef0ac4ae9Eric Laurent            if (removedPatch->mRecordPatchHandle != AUDIO_PATCH_HANDLE_NONE ||
6053bcf8597189c592713675ec58326ecbef0ac4ae9Eric Laurent                    removedPatch->mPlaybackPatchHandle != AUDIO_PATCH_HANDLE_NONE) {
60683b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent                clearPatchConnections(removedPatch);
60783b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent                break;
60883b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent            }
60983b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent
610054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent            if (patch->sinks[0].type == AUDIO_PORT_TYPE_MIX) {
611951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent                sp<ThreadBase> thread = audioflinger->checkRecordThread_l(
612054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent                                                                patch->sinks[0].ext.mix.handle);
613951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent                if (thread == 0) {
614951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent                    ALOGW("releaseAudioPatch() bad capture I/O handle %d",
615054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent                                                              patch->sinks[0].ext.mix.handle);
616951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent                    status = BAD_VALUE;
617951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent                    break;
618951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent                }
619054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent                status = thread->sendReleaseAudioPatchConfigEvent(removedPatch->mHalHandle);
620054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent            } else {
621054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent                AudioHwDevice *audioHwDevice = audioflinger->mAudioHwDevs.valueAt(index);
622054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent                if (audioHwDevice->version() < AUDIO_DEVICE_API_VERSION_3_0) {
623054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent                    status = INVALID_OPERATION;
624054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent                    break;
625054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent                }
626054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent                audio_hw_device_t *hwDevice = audioHwDevice->hwDevice();
627054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent                status = hwDevice->release_audio_patch(hwDevice, removedPatch->mHalHandle);
628951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent            }
629951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent        } break;
630951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent        case AUDIO_PORT_TYPE_MIX: {
631874c4287a4e49c59ac88767751dce00fcd3edb73Eric Laurent            audio_module_handle_t srcModule =  patch->sources[0].ext.mix.hw_module;
632874c4287a4e49c59ac88767751dce00fcd3edb73Eric Laurent            ssize_t index = audioflinger->mAudioHwDevs.indexOfKey(srcModule);
633951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent            if (index < 0) {
634874c4287a4e49c59ac88767751dce00fcd3edb73Eric Laurent                ALOGW("releaseAudioPatch() bad src hw module %d", srcModule);
635951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent                status = BAD_VALUE;
636951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent                break;
637951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent            }
638951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent            sp<ThreadBase> thread =
639951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent                            audioflinger->checkPlaybackThread_l(patch->sources[0].ext.mix.handle);
640951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent            if (thread == 0) {
641951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent                ALOGW("releaseAudioPatch() bad playback I/O handle %d",
642951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent                                                              patch->sources[0].ext.mix.handle);
643951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent                status = BAD_VALUE;
644951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent                break;
645951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent            }
646054d9d3dea1390294650ac704acb4aa0a0731217Eric Laurent            status = thread->sendReleaseAudioPatchConfigEvent(removedPatch->mHalHandle);
647951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent        } break;
648951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent        default:
649951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent            status = BAD_VALUE;
650951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent            break;
651951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent    }
652951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent
65383b8808faad1e91690c64d7007348be8d9ebde73Eric Laurent    delete removedPatch;
654951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent    return status;
655951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent}
656951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent
657951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent
658951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent/* List connected audio ports and they attributes */
659951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurentstatus_t AudioFlinger::PatchPanel::listAudioPatches(unsigned int *num_patches __unused,
660951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent                                  struct audio_patch *patches __unused)
661951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent{
662951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent    ALOGV("listAudioPatches");
663951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent    return NO_ERROR;
664951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent}
665951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent
666951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent/* Set audio port configuration */
667e1715a465a29db625da9d0ea365edf371e39e201Eric Laurentstatus_t AudioFlinger::PatchPanel::setAudioPortConfig(const struct audio_port_config *config)
668951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent{
669951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent    ALOGV("setAudioPortConfig");
670e1715a465a29db625da9d0ea365edf371e39e201Eric Laurent
671e1715a465a29db625da9d0ea365edf371e39e201Eric Laurent    sp<AudioFlinger> audioflinger = mAudioFlinger.promote();
672e1715a465a29db625da9d0ea365edf371e39e201Eric Laurent    if (audioflinger == 0) {
673e1715a465a29db625da9d0ea365edf371e39e201Eric Laurent        return NO_INIT;
674e1715a465a29db625da9d0ea365edf371e39e201Eric Laurent    }
675e1715a465a29db625da9d0ea365edf371e39e201Eric Laurent
676e1715a465a29db625da9d0ea365edf371e39e201Eric Laurent    audio_module_handle_t module;
677e1715a465a29db625da9d0ea365edf371e39e201Eric Laurent    if (config->type == AUDIO_PORT_TYPE_DEVICE) {
678e1715a465a29db625da9d0ea365edf371e39e201Eric Laurent        module = config->ext.device.hw_module;
679e1715a465a29db625da9d0ea365edf371e39e201Eric Laurent    } else {
680e1715a465a29db625da9d0ea365edf371e39e201Eric Laurent        module = config->ext.mix.hw_module;
681e1715a465a29db625da9d0ea365edf371e39e201Eric Laurent    }
682e1715a465a29db625da9d0ea365edf371e39e201Eric Laurent
683e1715a465a29db625da9d0ea365edf371e39e201Eric Laurent    ssize_t index = audioflinger->mAudioHwDevs.indexOfKey(module);
684e1715a465a29db625da9d0ea365edf371e39e201Eric Laurent    if (index < 0) {
685e1715a465a29db625da9d0ea365edf371e39e201Eric Laurent        ALOGW("setAudioPortConfig() bad hw module %d", module);
686e1715a465a29db625da9d0ea365edf371e39e201Eric Laurent        return BAD_VALUE;
687e1715a465a29db625da9d0ea365edf371e39e201Eric Laurent    }
688e1715a465a29db625da9d0ea365edf371e39e201Eric Laurent
689e1715a465a29db625da9d0ea365edf371e39e201Eric Laurent    AudioHwDevice *audioHwDevice = audioflinger->mAudioHwDevs.valueAt(index);
690e1715a465a29db625da9d0ea365edf371e39e201Eric Laurent    if (audioHwDevice->version() >= AUDIO_DEVICE_API_VERSION_3_0) {
691e1715a465a29db625da9d0ea365edf371e39e201Eric Laurent        audio_hw_device_t *hwDevice = audioHwDevice->hwDevice();
692e1715a465a29db625da9d0ea365edf371e39e201Eric Laurent        return hwDevice->set_audio_port_config(hwDevice, config);
693e1715a465a29db625da9d0ea365edf371e39e201Eric Laurent    } else {
694e1715a465a29db625da9d0ea365edf371e39e201Eric Laurent        return INVALID_OPERATION;
695e1715a465a29db625da9d0ea365edf371e39e201Eric Laurent    }
696951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent    return NO_ERROR;
697951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent}
698951f455566775e5f01e67c5ee26863d7d19209d7Eric Laurent
69963238efb0d674758902918e3cdaac322126484b7Glenn Kasten} // namespace android
700