blob: 11fd9f625195edbaa463118c3cefdbed3b058410 [file] [log] [blame]
Phil Burkc0c70e32017-02-09 13:18:38 -08001/*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Eric Laurenta54f1282017-07-01 19:39:32 -070017#define LOG_TAG "AAudioEndpointManager"
Phil Burk71f35bb2017-04-13 16:05:07 -070018//#define LOG_NDEBUG 0
19#include <utils/Log.h>
20
Phil Burkc0c70e32017-02-09 13:18:38 -080021#include <assert.h>
Andy Hung47c5e532017-06-26 18:28:00 -070022#include <functional>
Phil Burkc0c70e32017-02-09 13:18:38 -080023#include <map>
24#include <mutex>
Andy Hung47c5e532017-06-26 18:28:00 -070025#include <sstream>
26#include <utility/AAudioUtilities.h>
Phil Burkc0c70e32017-02-09 13:18:38 -080027
28#include "AAudioEndpointManager.h"
Phil Burk39f02dd2017-08-04 09:13:31 -070029#include "AAudioServiceEndpointShared.h"
30#include "AAudioServiceEndpointMMAP.h"
31#include "AAudioServiceEndpointCapture.h"
32#include "AAudioServiceEndpointPlay.h"
Phil Burkc0c70e32017-02-09 13:18:38 -080033
34using namespace android;
35using namespace aaudio;
36
37ANDROID_SINGLETON_STATIC_INSTANCE(AAudioEndpointManager);
38
39AAudioEndpointManager::AAudioEndpointManager()
Phil Burk71f35bb2017-04-13 16:05:07 -070040 : Singleton<AAudioEndpointManager>()
Phil Burk39f02dd2017-08-04 09:13:31 -070041 , mSharedStreams()
42 , mExclusiveStreams() {
Phil Burkc0c70e32017-02-09 13:18:38 -080043}
44
Andy Hung47c5e532017-06-26 18:28:00 -070045std::string AAudioEndpointManager::dump() const {
46 std::stringstream result;
Phil Burk39f02dd2017-08-04 09:13:31 -070047 int index = 0;
Andy Hung47c5e532017-06-26 18:28:00 -070048
Phil Burk4501b352017-06-29 18:12:36 -070049 result << "AAudioEndpointManager:" << "\n";
Phil Burk39f02dd2017-08-04 09:13:31 -070050
51 const bool isSharedLocked = AAudio_tryUntilTrue(
52 [this]()->bool { return mSharedLock.try_lock(); } /* f */,
53 50 /* times */,
54 20 /* sleepMs */);
55 if (!isSharedLocked) {
56 result << "AAudioEndpointManager Shared may be deadlocked\n";
Andy Hung47c5e532017-06-26 18:28:00 -070057 }
58
Phil Burk39f02dd2017-08-04 09:13:31 -070059 {
60 const bool isExclusiveLocked = AAudio_tryUntilTrue(
61 [this]() -> bool { return mExclusiveLock.try_lock(); } /* f */,
62 50 /* times */,
63 20 /* sleepMs */);
64 if (!isExclusiveLocked) {
65 result << "AAudioEndpointManager Exclusive may be deadlocked\n";
66 }
67
68 result << "Exclusive MMAP Endpoints: " << mExclusiveStreams.size() << "\n";
69 index = 0;
70 for (const auto &output : mExclusiveStreams) {
71 result << " #" << index++ << ":";
72 result << output->dump() << "\n";
73 }
74
75 if (isExclusiveLocked) {
76 mExclusiveLock.unlock();
77 }
Andy Hung47c5e532017-06-26 18:28:00 -070078 }
79
Phil Burk39f02dd2017-08-04 09:13:31 -070080 result << "Shared Endpoints: " << mSharedStreams.size() << "\n";
81 index = 0;
82 for (const auto &input : mSharedStreams) {
83 result << " #" << index++ << ":";
84 result << input->dump() << "\n";
85 }
86
87 if (isSharedLocked) {
88 mSharedLock.unlock();
Andy Hung47c5e532017-06-26 18:28:00 -070089 }
90 return result.str();
91}
92
Phil Burk39f02dd2017-08-04 09:13:31 -070093
94// Try to find an existing endpoint.
95sp<AAudioServiceEndpoint> AAudioEndpointManager::findExclusiveEndpoint_l(
96 const AAudioStreamConfiguration &configuration) {
97 sp<AAudioServiceEndpoint> endpoint;
98 for (const auto ep : mExclusiveStreams) {
99 if (ep->matches(configuration)) {
100 endpoint = ep;
101 break;
102 }
103 }
104
Phil Burk4e1af9f2018-01-03 15:54:35 -0800105 ALOGV("findExclusiveEndpoint_l(), found %p for device = %d, sessionId = %d",
106 endpoint.get(), configuration.getDeviceId(), configuration.getSessionId());
Phil Burk39f02dd2017-08-04 09:13:31 -0700107 return endpoint;
108}
109
110// Try to find an existing endpoint.
111sp<AAudioServiceEndpointShared> AAudioEndpointManager::findSharedEndpoint_l(
112 const AAudioStreamConfiguration &configuration) {
113 sp<AAudioServiceEndpointShared> endpoint;
114 for (const auto ep : mSharedStreams) {
115 if (ep->matches(configuration)) {
116 endpoint = ep;
117 break;
118 }
119 }
120
Phil Burk4e1af9f2018-01-03 15:54:35 -0800121 ALOGV("findSharedEndpoint_l(), found %p for device = %d, sessionId = %d",
122 endpoint.get(), configuration.getDeviceId(), configuration.getSessionId());
Phil Burk39f02dd2017-08-04 09:13:31 -0700123 return endpoint;
124}
125
126sp<AAudioServiceEndpoint> AAudioEndpointManager::openEndpoint(AAudioService &audioService,
127 const aaudio::AAudioStreamRequest &request,
128 aaudio_sharing_mode_t sharingMode) {
129 if (sharingMode == AAUDIO_SHARING_MODE_EXCLUSIVE) {
130 return openExclusiveEndpoint(audioService, request);
131 } else {
132 return openSharedEndpoint(audioService, request);
133 }
134}
135
136sp<AAudioServiceEndpoint> AAudioEndpointManager::openExclusiveEndpoint(
137 AAudioService &aaudioService __unused,
138 const aaudio::AAudioStreamRequest &request) {
139
140 std::lock_guard<std::mutex> lock(mExclusiveLock);
141
142 const AAudioStreamConfiguration &configuration = request.getConstantConfiguration();
Phil Burk71f35bb2017-04-13 16:05:07 -0700143
144 // Try to find an existing endpoint.
Phil Burk39f02dd2017-08-04 09:13:31 -0700145 sp<AAudioServiceEndpoint> endpoint = findExclusiveEndpoint_l(configuration);
Eric Laurenta17ae742017-06-29 15:43:55 -0700146
Phil Burk39f02dd2017-08-04 09:13:31 -0700147 // If we find an existing one then this one cannot be exclusive.
148 if (endpoint.get() != nullptr) {
Phil Burkfbf031e2017-10-12 15:58:31 -0700149 ALOGE("openExclusiveEndpoint() already in use");
Phil Burk39f02dd2017-08-04 09:13:31 -0700150 // Already open so do not allow a second stream.
151 return nullptr;
152 } else {
153 sp<AAudioServiceEndpointMMAP> endpointMMap = new AAudioServiceEndpointMMAP();
Phil Burk4e1af9f2018-01-03 15:54:35 -0800154 ALOGD("openExclusiveEndpoint(), no match so try to open MMAP %p for dev %d",
155 endpointMMap.get(), configuration.getDeviceId());
Phil Burk39f02dd2017-08-04 09:13:31 -0700156 endpoint = endpointMMap;
Eric Laurenta17ae742017-06-29 15:43:55 -0700157
Phil Burk39f02dd2017-08-04 09:13:31 -0700158 aaudio_result_t result = endpoint->open(request);
159 if (result != AAUDIO_OK) {
Phil Burk4e1af9f2018-01-03 15:54:35 -0800160 ALOGE("openExclusiveEndpoint(), open failed");
Phil Burk39f02dd2017-08-04 09:13:31 -0700161 endpoint.clear();
162 } else {
163 mExclusiveStreams.push_back(endpointMMap);
Phil Burk11e8d332017-05-24 09:59:02 -0700164 }
Phil Burkc0c70e32017-02-09 13:18:38 -0800165 }
Phil Burk71f35bb2017-04-13 16:05:07 -0700166
Phil Burk39f02dd2017-08-04 09:13:31 -0700167 if (endpoint.get() != nullptr) {
Phil Burk71f35bb2017-04-13 16:05:07 -0700168 // Increment the reference count under this lock.
Phil Burk39f02dd2017-08-04 09:13:31 -0700169 endpoint->setOpenCount(endpoint->getOpenCount() + 1);
Phil Burk71f35bb2017-04-13 16:05:07 -0700170 }
Phil Burkc0c70e32017-02-09 13:18:38 -0800171 return endpoint;
172}
173
Phil Burk39f02dd2017-08-04 09:13:31 -0700174sp<AAudioServiceEndpoint> AAudioEndpointManager::openSharedEndpoint(
175 AAudioService &aaudioService,
176 const aaudio::AAudioStreamRequest &request) {
Phil Burk71f35bb2017-04-13 16:05:07 -0700177
Phil Burk39f02dd2017-08-04 09:13:31 -0700178 std::lock_guard<std::mutex> lock(mSharedLock);
Phil Burkec89b2e2017-06-20 15:05:06 -0700179
Phil Burk39f02dd2017-08-04 09:13:31 -0700180 const AAudioStreamConfiguration &configuration = request.getConstantConfiguration();
181 aaudio_direction_t direction = configuration.getDirection();
Phil Burk71f35bb2017-04-13 16:05:07 -0700182
Phil Burk39f02dd2017-08-04 09:13:31 -0700183 // Try to find an existing endpoint.
184 sp<AAudioServiceEndpointShared> endpoint = findSharedEndpoint_l(configuration);
185
186 // If we can't find an existing one then open a new one.
187 if (endpoint.get() == nullptr) {
188 // we must call openStream with audioserver identity
189 int64_t token = IPCThreadState::self()->clearCallingIdentity();
Phil Burk71f35bb2017-04-13 16:05:07 -0700190 switch (direction) {
191 case AAUDIO_DIRECTION_INPUT:
Phil Burk39f02dd2017-08-04 09:13:31 -0700192 endpoint = new AAudioServiceEndpointCapture(aaudioService);
Phil Burk71f35bb2017-04-13 16:05:07 -0700193 break;
194 case AAUDIO_DIRECTION_OUTPUT:
Phil Burk39f02dd2017-08-04 09:13:31 -0700195 endpoint = new AAudioServiceEndpointPlay(aaudioService);
Phil Burk71f35bb2017-04-13 16:05:07 -0700196 break;
Phil Burk11e8d332017-05-24 09:59:02 -0700197 default:
198 break;
Phil Burk71f35bb2017-04-13 16:05:07 -0700199 }
Phil Burk87c9f642017-05-17 07:22:39 -0700200
Phil Burk39f02dd2017-08-04 09:13:31 -0700201 if (endpoint.get() != nullptr) {
202 aaudio_result_t result = endpoint->open(request);
203 if (result != AAUDIO_OK) {
Phil Burk19e990e2018-03-22 13:59:34 -0700204 ALOGE("%s(), open failed", __func__);
Phil Burk39f02dd2017-08-04 09:13:31 -0700205 endpoint.clear();
206 } else {
207 mSharedStreams.push_back(endpoint);
208 }
209 }
Phil Burk19e990e2018-03-22 13:59:34 -0700210 ALOGD("%s(), created endpoint %p, requested device = %d, dir = %d",
211 __func__, endpoint.get(), configuration.getDeviceId(), (int)direction);
Phil Burk39f02dd2017-08-04 09:13:31 -0700212 IPCThreadState::self()->restoreCallingIdentity(token);
213 }
214
215 if (endpoint.get() != nullptr) {
216 // Increment the reference count under this lock.
217 endpoint->setOpenCount(endpoint->getOpenCount() + 1);
218 }
219 return endpoint;
220}
221
222void AAudioEndpointManager::closeEndpoint(sp<AAudioServiceEndpoint>serviceEndpoint) {
223 if (serviceEndpoint->getSharingMode() == AAUDIO_SHARING_MODE_EXCLUSIVE) {
224 return closeExclusiveEndpoint(serviceEndpoint);
225 } else {
226 return closeSharedEndpoint(serviceEndpoint);
227 }
228}
229
230void AAudioEndpointManager::closeExclusiveEndpoint(sp<AAudioServiceEndpoint> serviceEndpoint) {
231 if (serviceEndpoint.get() == nullptr) {
232 return;
233 }
234
235 // Decrement the reference count under this lock.
236 std::lock_guard<std::mutex> lock(mExclusiveLock);
237 int32_t newRefCount = serviceEndpoint->getOpenCount() - 1;
238 serviceEndpoint->setOpenCount(newRefCount);
Phil Burk39f02dd2017-08-04 09:13:31 -0700239
Phil Burkfbf031e2017-10-12 15:58:31 -0700240 // If no longer in use then actually close it.
Phil Burk39f02dd2017-08-04 09:13:31 -0700241 if (newRefCount <= 0) {
242 mExclusiveStreams.erase(
243 std::remove(mExclusiveStreams.begin(), mExclusiveStreams.end(), serviceEndpoint),
244 mExclusiveStreams.end());
245
Phil Burk71f35bb2017-04-13 16:05:07 -0700246 serviceEndpoint->close();
Phil Burk19e990e2018-03-22 13:59:34 -0700247 ALOGD("%s() %p for device %d",
248 __func__, serviceEndpoint.get(), serviceEndpoint->getDeviceId());
Phil Burk39f02dd2017-08-04 09:13:31 -0700249 }
250}
251
252void AAudioEndpointManager::closeSharedEndpoint(sp<AAudioServiceEndpoint> serviceEndpoint) {
253 if (serviceEndpoint.get() == nullptr) {
254 return;
255 }
256
257 // Decrement the reference count under this lock.
258 std::lock_guard<std::mutex> lock(mSharedLock);
259 int32_t newRefCount = serviceEndpoint->getOpenCount() - 1;
260 serviceEndpoint->setOpenCount(newRefCount);
Phil Burk39f02dd2017-08-04 09:13:31 -0700261
Phil Burkfbf031e2017-10-12 15:58:31 -0700262 // If no longer in use then actually close it.
Phil Burk39f02dd2017-08-04 09:13:31 -0700263 if (newRefCount <= 0) {
264 mSharedStreams.erase(
265 std::remove(mSharedStreams.begin(), mSharedStreams.end(), serviceEndpoint),
266 mSharedStreams.end());
267
268 serviceEndpoint->close();
Phil Burk19e990e2018-03-22 13:59:34 -0700269 ALOGD("%s() %p for device %d",
270 __func__, serviceEndpoint.get(), serviceEndpoint->getDeviceId());
Phil Burk71f35bb2017-04-13 16:05:07 -0700271 }
272}