blob: c9bf72f1d28faf8da54af41665ad5c4e25a19e30 [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;
Phil Burk55e5eab2018-04-10 15:16:38 -070070 for (const auto &stream : mExclusiveStreams) {
Phil Burk39f02dd2017-08-04 09:13:31 -070071 result << " #" << index++ << ":";
Phil Burk55e5eab2018-04-10 15:16:38 -070072 result << stream->dump() << "\n";
Phil Burk39f02dd2017-08-04 09:13:31 -070073 }
74
Phil Burk55e5eab2018-04-10 15:16:38 -070075 result << " ExclusiveSearchCount: " << mExclusiveSearchCount << "\n";
76 result << " ExclusiveFoundCount: " << mExclusiveFoundCount << "\n";
77 result << " ExclusiveOpenCount: " << mExclusiveOpenCount << "\n";
78 result << " ExclusiveCloseCount: " << mExclusiveCloseCount << "\n";
Phil Burk6e463ce2020-04-13 10:20:20 -070079 result << " ExclusiveStolenCount: " << mExclusiveStolenCount << "\n";
Phil Burk55e5eab2018-04-10 15:16:38 -070080 result << "\n";
81
Phil Burk39f02dd2017-08-04 09:13:31 -070082 if (isExclusiveLocked) {
83 mExclusiveLock.unlock();
84 }
Andy Hung47c5e532017-06-26 18:28:00 -070085 }
86
Phil Burk39f02dd2017-08-04 09:13:31 -070087 result << "Shared Endpoints: " << mSharedStreams.size() << "\n";
88 index = 0;
Phil Burk55e5eab2018-04-10 15:16:38 -070089 for (const auto &stream : mSharedStreams) {
Phil Burk39f02dd2017-08-04 09:13:31 -070090 result << " #" << index++ << ":";
Phil Burk55e5eab2018-04-10 15:16:38 -070091 result << stream->dump() << "\n";
Phil Burk39f02dd2017-08-04 09:13:31 -070092 }
93
Phil Burk55e5eab2018-04-10 15:16:38 -070094 result << " SharedSearchCount: " << mSharedSearchCount << "\n";
95 result << " SharedFoundCount: " << mSharedFoundCount << "\n";
96 result << " SharedOpenCount: " << mSharedOpenCount << "\n";
97 result << " SharedCloseCount: " << mSharedCloseCount << "\n";
98 result << "\n";
99
Phil Burk39f02dd2017-08-04 09:13:31 -0700100 if (isSharedLocked) {
101 mSharedLock.unlock();
Andy Hung47c5e532017-06-26 18:28:00 -0700102 }
103 return result.str();
104}
105
Phil Burk39f02dd2017-08-04 09:13:31 -0700106
107// Try to find an existing endpoint.
108sp<AAudioServiceEndpoint> AAudioEndpointManager::findExclusiveEndpoint_l(
109 const AAudioStreamConfiguration &configuration) {
110 sp<AAudioServiceEndpoint> endpoint;
Phil Burk55e5eab2018-04-10 15:16:38 -0700111 mExclusiveSearchCount++;
Chih-Hung Hsieh3ef324d2018-12-11 11:48:12 -0800112 for (const auto& ep : mExclusiveStreams) {
Phil Burk39f02dd2017-08-04 09:13:31 -0700113 if (ep->matches(configuration)) {
Phil Burk55e5eab2018-04-10 15:16:38 -0700114 mExclusiveFoundCount++;
Phil Burk39f02dd2017-08-04 09:13:31 -0700115 endpoint = ep;
116 break;
117 }
118 }
119
Phil Burk4e1af9f2018-01-03 15:54:35 -0800120 ALOGV("findExclusiveEndpoint_l(), found %p for device = %d, sessionId = %d",
121 endpoint.get(), configuration.getDeviceId(), configuration.getSessionId());
Phil Burk39f02dd2017-08-04 09:13:31 -0700122 return endpoint;
123}
124
125// Try to find an existing endpoint.
126sp<AAudioServiceEndpointShared> AAudioEndpointManager::findSharedEndpoint_l(
127 const AAudioStreamConfiguration &configuration) {
128 sp<AAudioServiceEndpointShared> endpoint;
Phil Burk55e5eab2018-04-10 15:16:38 -0700129 mSharedSearchCount++;
Chih-Hung Hsieh3ef324d2018-12-11 11:48:12 -0800130 for (const auto& ep : mSharedStreams) {
Phil Burk39f02dd2017-08-04 09:13:31 -0700131 if (ep->matches(configuration)) {
Phil Burk55e5eab2018-04-10 15:16:38 -0700132 mSharedFoundCount++;
Phil Burk39f02dd2017-08-04 09:13:31 -0700133 endpoint = ep;
134 break;
135 }
136 }
137
Phil Burk4e1af9f2018-01-03 15:54:35 -0800138 ALOGV("findSharedEndpoint_l(), found %p for device = %d, sessionId = %d",
139 endpoint.get(), configuration.getDeviceId(), configuration.getSessionId());
Phil Burk39f02dd2017-08-04 09:13:31 -0700140 return endpoint;
141}
142
143sp<AAudioServiceEndpoint> AAudioEndpointManager::openEndpoint(AAudioService &audioService,
Phil Burk15f97c92018-09-04 14:06:27 -0700144 const aaudio::AAudioStreamRequest &request) {
145 if (request.getConstantConfiguration().getSharingMode() == AAUDIO_SHARING_MODE_EXCLUSIVE) {
Phil Burk6e463ce2020-04-13 10:20:20 -0700146 sp<AAudioServiceEndpoint> endpointToSteal;
147 sp<AAudioServiceEndpoint> foundEndpoint =
148 openExclusiveEndpoint(audioService, request, endpointToSteal);
149 if (endpointToSteal.get()) {
150 endpointToSteal->releaseRegisteredStreams(); // free the MMAP resource
151 }
152 return foundEndpoint;
Phil Burk39f02dd2017-08-04 09:13:31 -0700153 } else {
154 return openSharedEndpoint(audioService, request);
155 }
156}
157
158sp<AAudioServiceEndpoint> AAudioEndpointManager::openExclusiveEndpoint(
Phil Burkbbd52862018-04-13 11:37:42 -0700159 AAudioService &aaudioService,
Phil Burk6e463ce2020-04-13 10:20:20 -0700160 const aaudio::AAudioStreamRequest &request,
161 sp<AAudioServiceEndpoint> &endpointToSteal) {
Phil Burk39f02dd2017-08-04 09:13:31 -0700162
163 std::lock_guard<std::mutex> lock(mExclusiveLock);
164
165 const AAudioStreamConfiguration &configuration = request.getConstantConfiguration();
Phil Burk71f35bb2017-04-13 16:05:07 -0700166
167 // Try to find an existing endpoint.
Phil Burk39f02dd2017-08-04 09:13:31 -0700168 sp<AAudioServiceEndpoint> endpoint = findExclusiveEndpoint_l(configuration);
Eric Laurenta17ae742017-06-29 15:43:55 -0700169
Phil Burk39f02dd2017-08-04 09:13:31 -0700170 // If we find an existing one then this one cannot be exclusive.
171 if (endpoint.get() != nullptr) {
Phil Burk6e463ce2020-04-13 10:20:20 -0700172 if (kStealingEnabled
173 && !endpoint->isForSharing() // not currently SHARED
174 && !request.isSharingModeMatchRequired()) { // app did not request a shared stream
175 ALOGD("%s() endpoint in EXCLUSIVE use. Steal it!", __func__);
176 mExclusiveStolenCount++;
177 endpointToSteal = endpoint;
178 }
Phil Burk39f02dd2017-08-04 09:13:31 -0700179 return nullptr;
180 } else {
Phil Burkbbd52862018-04-13 11:37:42 -0700181 sp<AAudioServiceEndpointMMAP> endpointMMap = new AAudioServiceEndpointMMAP(aaudioService);
Phil Burk6e463ce2020-04-13 10:20:20 -0700182 ALOGV("%s(), no match so try to open MMAP %p for dev %d",
183 __func__, endpointMMap.get(), configuration.getDeviceId());
Phil Burk39f02dd2017-08-04 09:13:31 -0700184 endpoint = endpointMMap;
Eric Laurenta17ae742017-06-29 15:43:55 -0700185
Phil Burk39f02dd2017-08-04 09:13:31 -0700186 aaudio_result_t result = endpoint->open(request);
187 if (result != AAUDIO_OK) {
Phil Burk39f02dd2017-08-04 09:13:31 -0700188 endpoint.clear();
189 } else {
190 mExclusiveStreams.push_back(endpointMMap);
Phil Burk55e5eab2018-04-10 15:16:38 -0700191 mExclusiveOpenCount++;
Phil Burk11e8d332017-05-24 09:59:02 -0700192 }
Phil Burkc0c70e32017-02-09 13:18:38 -0800193 }
Phil Burk71f35bb2017-04-13 16:05:07 -0700194
Phil Burk39f02dd2017-08-04 09:13:31 -0700195 if (endpoint.get() != nullptr) {
Phil Burk71f35bb2017-04-13 16:05:07 -0700196 // Increment the reference count under this lock.
Phil Burk39f02dd2017-08-04 09:13:31 -0700197 endpoint->setOpenCount(endpoint->getOpenCount() + 1);
Phil Burk6e463ce2020-04-13 10:20:20 -0700198 endpoint->setForSharing(request.isSharingModeMatchRequired());
Phil Burk71f35bb2017-04-13 16:05:07 -0700199 }
Phil Burk6e463ce2020-04-13 10:20:20 -0700200
Phil Burkc0c70e32017-02-09 13:18:38 -0800201 return endpoint;
202}
203
Phil Burk39f02dd2017-08-04 09:13:31 -0700204sp<AAudioServiceEndpoint> AAudioEndpointManager::openSharedEndpoint(
205 AAudioService &aaudioService,
206 const aaudio::AAudioStreamRequest &request) {
Phil Burk71f35bb2017-04-13 16:05:07 -0700207
Phil Burk39f02dd2017-08-04 09:13:31 -0700208 std::lock_guard<std::mutex> lock(mSharedLock);
Phil Burkec89b2e2017-06-20 15:05:06 -0700209
Phil Burk39f02dd2017-08-04 09:13:31 -0700210 const AAudioStreamConfiguration &configuration = request.getConstantConfiguration();
211 aaudio_direction_t direction = configuration.getDirection();
Phil Burk71f35bb2017-04-13 16:05:07 -0700212
Phil Burk39f02dd2017-08-04 09:13:31 -0700213 // Try to find an existing endpoint.
214 sp<AAudioServiceEndpointShared> endpoint = findSharedEndpoint_l(configuration);
215
216 // If we can't find an existing one then open a new one.
217 if (endpoint.get() == nullptr) {
218 // we must call openStream with audioserver identity
219 int64_t token = IPCThreadState::self()->clearCallingIdentity();
Phil Burk71f35bb2017-04-13 16:05:07 -0700220 switch (direction) {
221 case AAUDIO_DIRECTION_INPUT:
Phil Burk39f02dd2017-08-04 09:13:31 -0700222 endpoint = new AAudioServiceEndpointCapture(aaudioService);
Phil Burk71f35bb2017-04-13 16:05:07 -0700223 break;
224 case AAUDIO_DIRECTION_OUTPUT:
Phil Burk39f02dd2017-08-04 09:13:31 -0700225 endpoint = new AAudioServiceEndpointPlay(aaudioService);
Phil Burk71f35bb2017-04-13 16:05:07 -0700226 break;
Phil Burk11e8d332017-05-24 09:59:02 -0700227 default:
228 break;
Phil Burk71f35bb2017-04-13 16:05:07 -0700229 }
Phil Burk87c9f642017-05-17 07:22:39 -0700230
Phil Burk39f02dd2017-08-04 09:13:31 -0700231 if (endpoint.get() != nullptr) {
232 aaudio_result_t result = endpoint->open(request);
233 if (result != AAUDIO_OK) {
Phil Burk39f02dd2017-08-04 09:13:31 -0700234 endpoint.clear();
235 } else {
236 mSharedStreams.push_back(endpoint);
Phil Burk55e5eab2018-04-10 15:16:38 -0700237 mSharedOpenCount++;
Phil Burk39f02dd2017-08-04 09:13:31 -0700238 }
239 }
Phil Burk55e5eab2018-04-10 15:16:38 -0700240 ALOGV("%s(), created endpoint %p, requested device = %d, dir = %d",
Phil Burk19e990e2018-03-22 13:59:34 -0700241 __func__, endpoint.get(), configuration.getDeviceId(), (int)direction);
Phil Burk39f02dd2017-08-04 09:13:31 -0700242 IPCThreadState::self()->restoreCallingIdentity(token);
243 }
244
245 if (endpoint.get() != nullptr) {
246 // Increment the reference count under this lock.
247 endpoint->setOpenCount(endpoint->getOpenCount() + 1);
248 }
249 return endpoint;
250}
251
252void AAudioEndpointManager::closeEndpoint(sp<AAudioServiceEndpoint>serviceEndpoint) {
253 if (serviceEndpoint->getSharingMode() == AAUDIO_SHARING_MODE_EXCLUSIVE) {
254 return closeExclusiveEndpoint(serviceEndpoint);
255 } else {
256 return closeSharedEndpoint(serviceEndpoint);
257 }
258}
259
260void AAudioEndpointManager::closeExclusiveEndpoint(sp<AAudioServiceEndpoint> serviceEndpoint) {
261 if (serviceEndpoint.get() == nullptr) {
262 return;
263 }
264
265 // Decrement the reference count under this lock.
266 std::lock_guard<std::mutex> lock(mExclusiveLock);
267 int32_t newRefCount = serviceEndpoint->getOpenCount() - 1;
268 serviceEndpoint->setOpenCount(newRefCount);
Phil Burk39f02dd2017-08-04 09:13:31 -0700269
Phil Burkfbf031e2017-10-12 15:58:31 -0700270 // If no longer in use then actually close it.
Phil Burk39f02dd2017-08-04 09:13:31 -0700271 if (newRefCount <= 0) {
272 mExclusiveStreams.erase(
273 std::remove(mExclusiveStreams.begin(), mExclusiveStreams.end(), serviceEndpoint),
274 mExclusiveStreams.end());
275
Phil Burk71f35bb2017-04-13 16:05:07 -0700276 serviceEndpoint->close();
Phil Burk55e5eab2018-04-10 15:16:38 -0700277 mExclusiveCloseCount++;
278 ALOGV("%s() %p for device %d",
Phil Burk19e990e2018-03-22 13:59:34 -0700279 __func__, serviceEndpoint.get(), serviceEndpoint->getDeviceId());
Phil Burk39f02dd2017-08-04 09:13:31 -0700280 }
281}
282
283void AAudioEndpointManager::closeSharedEndpoint(sp<AAudioServiceEndpoint> serviceEndpoint) {
284 if (serviceEndpoint.get() == nullptr) {
285 return;
286 }
287
288 // Decrement the reference count under this lock.
289 std::lock_guard<std::mutex> lock(mSharedLock);
290 int32_t newRefCount = serviceEndpoint->getOpenCount() - 1;
291 serviceEndpoint->setOpenCount(newRefCount);
Phil Burk39f02dd2017-08-04 09:13:31 -0700292
Phil Burkfbf031e2017-10-12 15:58:31 -0700293 // If no longer in use then actually close it.
Phil Burk39f02dd2017-08-04 09:13:31 -0700294 if (newRefCount <= 0) {
295 mSharedStreams.erase(
296 std::remove(mSharedStreams.begin(), mSharedStreams.end(), serviceEndpoint),
297 mSharedStreams.end());
298
299 serviceEndpoint->close();
Phil Burk55e5eab2018-04-10 15:16:38 -0700300 mSharedCloseCount++;
Phil Burk8b4e05e2019-12-17 12:12:09 -0800301 ALOGV("%s(%p) closed for device %d",
Phil Burk19e990e2018-03-22 13:59:34 -0700302 __func__, serviceEndpoint.get(), serviceEndpoint->getDeviceId());
Phil Burk71f35bb2017-04-13 16:05:07 -0700303 }
304}