blob: 243f1f18e86dab18dbf6dc2941e1c5075df5de2b [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>
Philip P. Moltmannbda45752020-07-17 16:41:18 -070027#include <media/AidlConversion.h>
Phil Burkc0c70e32017-02-09 13:18:38 -080028
Phil Burk836f9df2020-05-29 13:20:28 -070029#include "AAudioClientTracker.h"
Phil Burkc0c70e32017-02-09 13:18:38 -080030#include "AAudioEndpointManager.h"
Phil Burk39f02dd2017-08-04 09:13:31 -070031#include "AAudioServiceEndpointShared.h"
32#include "AAudioServiceEndpointMMAP.h"
33#include "AAudioServiceEndpointCapture.h"
34#include "AAudioServiceEndpointPlay.h"
Phil Burkc0c70e32017-02-09 13:18:38 -080035
36using namespace android;
37using namespace aaudio;
38
39ANDROID_SINGLETON_STATIC_INSTANCE(AAudioEndpointManager);
40
41AAudioEndpointManager::AAudioEndpointManager()
Phil Burk71f35bb2017-04-13 16:05:07 -070042 : Singleton<AAudioEndpointManager>()
Phil Burk39f02dd2017-08-04 09:13:31 -070043 , mSharedStreams()
44 , mExclusiveStreams() {
Phil Burkc0c70e32017-02-09 13:18:38 -080045}
46
Phil Burk0bd745e2020-10-17 18:20:01 +000047std::string AAudioEndpointManager::dump() const NO_THREAD_SAFETY_ANALYSIS {
Andy Hung47c5e532017-06-26 18:28:00 -070048 std::stringstream result;
Phil Burk39f02dd2017-08-04 09:13:31 -070049 int index = 0;
Andy Hung47c5e532017-06-26 18:28:00 -070050
Phil Burk4501b352017-06-29 18:12:36 -070051 result << "AAudioEndpointManager:" << "\n";
Phil Burk39f02dd2017-08-04 09:13:31 -070052
53 const bool isSharedLocked = AAudio_tryUntilTrue(
54 [this]()->bool { return mSharedLock.try_lock(); } /* f */,
55 50 /* times */,
56 20 /* sleepMs */);
57 if (!isSharedLocked) {
58 result << "AAudioEndpointManager Shared may be deadlocked\n";
Andy Hung47c5e532017-06-26 18:28:00 -070059 }
60
Phil Burk39f02dd2017-08-04 09:13:31 -070061 {
62 const bool isExclusiveLocked = AAudio_tryUntilTrue(
63 [this]() -> bool { return mExclusiveLock.try_lock(); } /* f */,
64 50 /* times */,
65 20 /* sleepMs */);
66 if (!isExclusiveLocked) {
67 result << "AAudioEndpointManager Exclusive may be deadlocked\n";
68 }
69
70 result << "Exclusive MMAP Endpoints: " << mExclusiveStreams.size() << "\n";
71 index = 0;
Phil Burk55e5eab2018-04-10 15:16:38 -070072 for (const auto &stream : mExclusiveStreams) {
Phil Burk39f02dd2017-08-04 09:13:31 -070073 result << " #" << index++ << ":";
Phil Burk55e5eab2018-04-10 15:16:38 -070074 result << stream->dump() << "\n";
Phil Burk39f02dd2017-08-04 09:13:31 -070075 }
76
Phil Burk55e5eab2018-04-10 15:16:38 -070077 result << " ExclusiveSearchCount: " << mExclusiveSearchCount << "\n";
78 result << " ExclusiveFoundCount: " << mExclusiveFoundCount << "\n";
79 result << " ExclusiveOpenCount: " << mExclusiveOpenCount << "\n";
80 result << " ExclusiveCloseCount: " << mExclusiveCloseCount << "\n";
Phil Burk6e463ce2020-04-13 10:20:20 -070081 result << " ExclusiveStolenCount: " << mExclusiveStolenCount << "\n";
Phil Burk55e5eab2018-04-10 15:16:38 -070082 result << "\n";
83
Phil Burk39f02dd2017-08-04 09:13:31 -070084 if (isExclusiveLocked) {
85 mExclusiveLock.unlock();
86 }
Andy Hung47c5e532017-06-26 18:28:00 -070087 }
88
Phil Burk39f02dd2017-08-04 09:13:31 -070089 result << "Shared Endpoints: " << mSharedStreams.size() << "\n";
90 index = 0;
Phil Burk55e5eab2018-04-10 15:16:38 -070091 for (const auto &stream : mSharedStreams) {
Phil Burk39f02dd2017-08-04 09:13:31 -070092 result << " #" << index++ << ":";
Phil Burk55e5eab2018-04-10 15:16:38 -070093 result << stream->dump() << "\n";
Phil Burk39f02dd2017-08-04 09:13:31 -070094 }
95
Phil Burk55e5eab2018-04-10 15:16:38 -070096 result << " SharedSearchCount: " << mSharedSearchCount << "\n";
97 result << " SharedFoundCount: " << mSharedFoundCount << "\n";
98 result << " SharedOpenCount: " << mSharedOpenCount << "\n";
99 result << " SharedCloseCount: " << mSharedCloseCount << "\n";
100 result << "\n";
101
Phil Burk39f02dd2017-08-04 09:13:31 -0700102 if (isSharedLocked) {
103 mSharedLock.unlock();
Andy Hung47c5e532017-06-26 18:28:00 -0700104 }
105 return result.str();
106}
107
Phil Burk39f02dd2017-08-04 09:13:31 -0700108
109// Try to find an existing endpoint.
110sp<AAudioServiceEndpoint> AAudioEndpointManager::findExclusiveEndpoint_l(
111 const AAudioStreamConfiguration &configuration) {
112 sp<AAudioServiceEndpoint> endpoint;
Phil Burk55e5eab2018-04-10 15:16:38 -0700113 mExclusiveSearchCount++;
Chih-Hung Hsieh3ef324d2018-12-11 11:48:12 -0800114 for (const auto& ep : mExclusiveStreams) {
Phil Burk39f02dd2017-08-04 09:13:31 -0700115 if (ep->matches(configuration)) {
Phil Burk55e5eab2018-04-10 15:16:38 -0700116 mExclusiveFoundCount++;
Phil Burk39f02dd2017-08-04 09:13:31 -0700117 endpoint = ep;
118 break;
119 }
120 }
121
Robert Wub7f8edc2024-11-04 19:54:38 +0000122 ALOGV("findExclusiveEndpoint_l(), found %p for devices = %s, sessionId = %d",
123 endpoint.get(), toString(configuration.getDeviceIds()).c_str(),
124 configuration.getSessionId());
Phil Burk39f02dd2017-08-04 09:13:31 -0700125 return endpoint;
126}
127
128// Try to find an existing endpoint.
129sp<AAudioServiceEndpointShared> AAudioEndpointManager::findSharedEndpoint_l(
130 const AAudioStreamConfiguration &configuration) {
131 sp<AAudioServiceEndpointShared> endpoint;
Phil Burk55e5eab2018-04-10 15:16:38 -0700132 mSharedSearchCount++;
Chih-Hung Hsieh3ef324d2018-12-11 11:48:12 -0800133 for (const auto& ep : mSharedStreams) {
Phil Burk39f02dd2017-08-04 09:13:31 -0700134 if (ep->matches(configuration)) {
Phil Burk55e5eab2018-04-10 15:16:38 -0700135 mSharedFoundCount++;
Phil Burk39f02dd2017-08-04 09:13:31 -0700136 endpoint = ep;
137 break;
138 }
139 }
140
Robert Wub7f8edc2024-11-04 19:54:38 +0000141 ALOGV("findSharedEndpoint_l(), found %p for devices = %s, sessionId = %d",
142 endpoint.get(), toString(configuration.getDeviceIds()).c_str(),
143 configuration.getSessionId());
Phil Burk39f02dd2017-08-04 09:13:31 -0700144 return endpoint;
145}
146
147sp<AAudioServiceEndpoint> AAudioEndpointManager::openEndpoint(AAudioService &audioService,
Phil Burk15f97c92018-09-04 14:06:27 -0700148 const aaudio::AAudioStreamRequest &request) {
149 if (request.getConstantConfiguration().getSharingMode() == AAUDIO_SHARING_MODE_EXCLUSIVE) {
Phil Burk6e463ce2020-04-13 10:20:20 -0700150 sp<AAudioServiceEndpoint> endpointToSteal;
151 sp<AAudioServiceEndpoint> foundEndpoint =
152 openExclusiveEndpoint(audioService, request, endpointToSteal);
153 if (endpointToSteal.get()) {
154 endpointToSteal->releaseRegisteredStreams(); // free the MMAP resource
155 }
156 return foundEndpoint;
Phil Burk39f02dd2017-08-04 09:13:31 -0700157 } else {
158 return openSharedEndpoint(audioService, request);
159 }
160}
161
162sp<AAudioServiceEndpoint> AAudioEndpointManager::openExclusiveEndpoint(
Phil Burkbbd52862018-04-13 11:37:42 -0700163 AAudioService &aaudioService,
Phil Burk6e463ce2020-04-13 10:20:20 -0700164 const aaudio::AAudioStreamRequest &request,
165 sp<AAudioServiceEndpoint> &endpointToSteal) {
Phil Burk39f02dd2017-08-04 09:13:31 -0700166
jiabin613e6ae2022-12-21 20:20:11 +0000167 const std::lock_guard<std::mutex> lock(mExclusiveLock);
Phil Burk39f02dd2017-08-04 09:13:31 -0700168
169 const AAudioStreamConfiguration &configuration = request.getConstantConfiguration();
Phil Burk71f35bb2017-04-13 16:05:07 -0700170
171 // Try to find an existing endpoint.
Phil Burk39f02dd2017-08-04 09:13:31 -0700172 sp<AAudioServiceEndpoint> endpoint = findExclusiveEndpoint_l(configuration);
Eric Laurenta17ae742017-06-29 15:43:55 -0700173
Phil Burk39f02dd2017-08-04 09:13:31 -0700174 // If we find an existing one then this one cannot be exclusive.
175 if (endpoint.get() != nullptr) {
Phil Burk6e463ce2020-04-13 10:20:20 -0700176 if (kStealingEnabled
177 && !endpoint->isForSharing() // not currently SHARED
178 && !request.isSharingModeMatchRequired()) { // app did not request a shared stream
179 ALOGD("%s() endpoint in EXCLUSIVE use. Steal it!", __func__);
180 mExclusiveStolenCount++;
Phil Burk836f9df2020-05-29 13:20:28 -0700181 // Prevent this process from getting another EXCLUSIVE stream.
182 // This will prevent two clients from colliding after a DISCONNECTION
183 // when they both try to open an exclusive stream at the same time.
184 // That can result in a stream getting disconnected between the OPEN
185 // and START calls. This will help preserve app compatibility.
186 // An app can avoid having this happen by closing their streams when
187 // the app is paused.
jiabin613e6ae2022-12-21 20:20:11 +0000188 const pid_t pid = VALUE_OR_FATAL(
Svet Ganov3e5f14f2021-05-13 22:51:08 +0000189 aidl2legacy_int32_t_pid_t(request.getAttributionSource().pid));
Philip P. Moltmannbda45752020-07-17 16:41:18 -0700190 AAudioClientTracker::getInstance().setExclusiveEnabled(pid, false);
Phil Burk836f9df2020-05-29 13:20:28 -0700191 endpointToSteal = endpoint; // return it to caller
Phil Burk6e463ce2020-04-13 10:20:20 -0700192 }
Phil Burk39f02dd2017-08-04 09:13:31 -0700193 return nullptr;
194 } else {
jiabin613e6ae2022-12-21 20:20:11 +0000195 const sp<AAudioServiceEndpointMMAP> endpointMMap =
196 new AAudioServiceEndpointMMAP(aaudioService);
Robert Wub7f8edc2024-11-04 19:54:38 +0000197 ALOGV("%s(), no match so try to open MMAP %p for devices %s",
198 __func__, endpointMMap.get(), toString(configuration.getDeviceIds()).c_str());
Phil Burk39f02dd2017-08-04 09:13:31 -0700199 endpoint = endpointMMap;
Eric Laurenta17ae742017-06-29 15:43:55 -0700200
jiabin613e6ae2022-12-21 20:20:11 +0000201 const aaudio_result_t result = endpoint->open(request);
Phil Burk39f02dd2017-08-04 09:13:31 -0700202 if (result != AAUDIO_OK) {
Phil Burk39f02dd2017-08-04 09:13:31 -0700203 endpoint.clear();
204 } else {
205 mExclusiveStreams.push_back(endpointMMap);
Phil Burk55e5eab2018-04-10 15:16:38 -0700206 mExclusiveOpenCount++;
Phil Burk11e8d332017-05-24 09:59:02 -0700207 }
Phil Burkc0c70e32017-02-09 13:18:38 -0800208 }
Phil Burk71f35bb2017-04-13 16:05:07 -0700209
Phil Burk39f02dd2017-08-04 09:13:31 -0700210 if (endpoint.get() != nullptr) {
Phil Burk71f35bb2017-04-13 16:05:07 -0700211 // Increment the reference count under this lock.
Phil Burk39f02dd2017-08-04 09:13:31 -0700212 endpoint->setOpenCount(endpoint->getOpenCount() + 1);
Phil Burk6e463ce2020-04-13 10:20:20 -0700213 endpoint->setForSharing(request.isSharingModeMatchRequired());
Phil Burk71f35bb2017-04-13 16:05:07 -0700214 }
Phil Burk6e463ce2020-04-13 10:20:20 -0700215
Phil Burkc0c70e32017-02-09 13:18:38 -0800216 return endpoint;
217}
218
Phil Burk39f02dd2017-08-04 09:13:31 -0700219sp<AAudioServiceEndpoint> AAudioEndpointManager::openSharedEndpoint(
220 AAudioService &aaudioService,
221 const aaudio::AAudioStreamRequest &request) {
Phil Burk71f35bb2017-04-13 16:05:07 -0700222
jiabin613e6ae2022-12-21 20:20:11 +0000223 const std::lock_guard<std::mutex> lock(mSharedLock);
Phil Burkec89b2e2017-06-20 15:05:06 -0700224
Phil Burk39f02dd2017-08-04 09:13:31 -0700225 const AAudioStreamConfiguration &configuration = request.getConstantConfiguration();
jiabin613e6ae2022-12-21 20:20:11 +0000226 const aaudio_direction_t direction = configuration.getDirection();
Phil Burk71f35bb2017-04-13 16:05:07 -0700227
Phil Burk39f02dd2017-08-04 09:13:31 -0700228 // Try to find an existing endpoint.
229 sp<AAudioServiceEndpointShared> endpoint = findSharedEndpoint_l(configuration);
230
231 // If we can't find an existing one then open a new one.
232 if (endpoint.get() == nullptr) {
233 // we must call openStream with audioserver identity
jiabin613e6ae2022-12-21 20:20:11 +0000234 const int64_t token = IPCThreadState::self()->clearCallingIdentity();
Phil Burk71f35bb2017-04-13 16:05:07 -0700235 switch (direction) {
236 case AAUDIO_DIRECTION_INPUT:
Phil Burk39f02dd2017-08-04 09:13:31 -0700237 endpoint = new AAudioServiceEndpointCapture(aaudioService);
Phil Burk71f35bb2017-04-13 16:05:07 -0700238 break;
239 case AAUDIO_DIRECTION_OUTPUT:
Phil Burk39f02dd2017-08-04 09:13:31 -0700240 endpoint = new AAudioServiceEndpointPlay(aaudioService);
Phil Burk71f35bb2017-04-13 16:05:07 -0700241 break;
Phil Burk11e8d332017-05-24 09:59:02 -0700242 default:
243 break;
Phil Burk71f35bb2017-04-13 16:05:07 -0700244 }
Phil Burk87c9f642017-05-17 07:22:39 -0700245
Phil Burk39f02dd2017-08-04 09:13:31 -0700246 if (endpoint.get() != nullptr) {
jiabin613e6ae2022-12-21 20:20:11 +0000247 const aaudio_result_t result = endpoint->open(request);
Phil Burk39f02dd2017-08-04 09:13:31 -0700248 if (result != AAUDIO_OK) {
Phil Burk39f02dd2017-08-04 09:13:31 -0700249 endpoint.clear();
250 } else {
251 mSharedStreams.push_back(endpoint);
Phil Burk55e5eab2018-04-10 15:16:38 -0700252 mSharedOpenCount++;
Phil Burk39f02dd2017-08-04 09:13:31 -0700253 }
254 }
Robert Wub7f8edc2024-11-04 19:54:38 +0000255 ALOGV("%s(), created endpoint %p, requested device = %s, dir = %d",
256 __func__, endpoint.get(), android::toString(configuration.getDeviceIds()).c_str(),
257 (int)direction);
Phil Burk39f02dd2017-08-04 09:13:31 -0700258 IPCThreadState::self()->restoreCallingIdentity(token);
259 }
260
261 if (endpoint.get() != nullptr) {
262 // Increment the reference count under this lock.
263 endpoint->setOpenCount(endpoint->getOpenCount() + 1);
264 }
265 return endpoint;
266}
267
jiabin613e6ae2022-12-21 20:20:11 +0000268void AAudioEndpointManager::closeEndpoint(const sp<AAudioServiceEndpoint>& serviceEndpoint) {
Phil Burk39f02dd2017-08-04 09:13:31 -0700269 if (serviceEndpoint->getSharingMode() == AAUDIO_SHARING_MODE_EXCLUSIVE) {
270 return closeExclusiveEndpoint(serviceEndpoint);
271 } else {
272 return closeSharedEndpoint(serviceEndpoint);
273 }
274}
275
jiabin613e6ae2022-12-21 20:20:11 +0000276void AAudioEndpointManager::closeExclusiveEndpoint(
277 const sp<AAudioServiceEndpoint>& serviceEndpoint) {
Phil Burk39f02dd2017-08-04 09:13:31 -0700278 if (serviceEndpoint.get() == nullptr) {
279 return;
280 }
281
282 // Decrement the reference count under this lock.
jiabin613e6ae2022-12-21 20:20:11 +0000283 const std::lock_guard<std::mutex> lock(mExclusiveLock);
284 const int32_t newRefCount = serviceEndpoint->getOpenCount() - 1;
Phil Burk39f02dd2017-08-04 09:13:31 -0700285 serviceEndpoint->setOpenCount(newRefCount);
Phil Burk39f02dd2017-08-04 09:13:31 -0700286
Phil Burkfbf031e2017-10-12 15:58:31 -0700287 // If no longer in use then actually close it.
Phil Burk39f02dd2017-08-04 09:13:31 -0700288 if (newRefCount <= 0) {
289 mExclusiveStreams.erase(
290 std::remove(mExclusiveStreams.begin(), mExclusiveStreams.end(), serviceEndpoint),
291 mExclusiveStreams.end());
292
Phil Burk71f35bb2017-04-13 16:05:07 -0700293 serviceEndpoint->close();
Phil Burk55e5eab2018-04-10 15:16:38 -0700294 mExclusiveCloseCount++;
Robert Wub7f8edc2024-11-04 19:54:38 +0000295 ALOGV("%s() %p for devices %s",
296 __func__, serviceEndpoint.get(),
297 android::toString(serviceEndpoint->getDeviceIds()).c_str());
Phil Burk39f02dd2017-08-04 09:13:31 -0700298 }
299}
300
jiabin613e6ae2022-12-21 20:20:11 +0000301void AAudioEndpointManager::closeSharedEndpoint(const sp<AAudioServiceEndpoint>& serviceEndpoint) {
Phil Burk39f02dd2017-08-04 09:13:31 -0700302 if (serviceEndpoint.get() == nullptr) {
303 return;
304 }
305
306 // Decrement the reference count under this lock.
jiabin613e6ae2022-12-21 20:20:11 +0000307 const std::lock_guard<std::mutex> lock(mSharedLock);
308 const int32_t newRefCount = serviceEndpoint->getOpenCount() - 1;
Phil Burk39f02dd2017-08-04 09:13:31 -0700309 serviceEndpoint->setOpenCount(newRefCount);
Phil Burk39f02dd2017-08-04 09:13:31 -0700310
Phil Burkfbf031e2017-10-12 15:58:31 -0700311 // If no longer in use then actually close it.
Phil Burk39f02dd2017-08-04 09:13:31 -0700312 if (newRefCount <= 0) {
313 mSharedStreams.erase(
314 std::remove(mSharedStreams.begin(), mSharedStreams.end(), serviceEndpoint),
315 mSharedStreams.end());
316
317 serviceEndpoint->close();
Phil Burkdd582922020-10-15 20:29:51 +0000318
Phil Burk55e5eab2018-04-10 15:16:38 -0700319 mSharedCloseCount++;
Robert Wub7f8edc2024-11-04 19:54:38 +0000320 ALOGV("%s(%p) closed for device %s",
321 __func__, serviceEndpoint.get(),
322 android::toString(serviceEndpoint->getDeviceIds()).c_str());
Phil Burk71f35bb2017-04-13 16:05:07 -0700323 }
324}