1*ec779b8eSAndroid Build Coastguard Worker /*
2*ec779b8eSAndroid Build Coastguard Worker * Copyright (C) 2017 The Android Open Source Project
3*ec779b8eSAndroid Build Coastguard Worker *
4*ec779b8eSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*ec779b8eSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*ec779b8eSAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*ec779b8eSAndroid Build Coastguard Worker *
8*ec779b8eSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*ec779b8eSAndroid Build Coastguard Worker *
10*ec779b8eSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*ec779b8eSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*ec779b8eSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*ec779b8eSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*ec779b8eSAndroid Build Coastguard Worker * limitations under the License.
15*ec779b8eSAndroid Build Coastguard Worker */
16*ec779b8eSAndroid Build Coastguard Worker
17*ec779b8eSAndroid Build Coastguard Worker
18*ec779b8eSAndroid Build Coastguard Worker #define LOG_TAG "AAudioClientTracker"
19*ec779b8eSAndroid Build Coastguard Worker //#define LOG_NDEBUG 0
20*ec779b8eSAndroid Build Coastguard Worker #include <utils/Log.h>
21*ec779b8eSAndroid Build Coastguard Worker
22*ec779b8eSAndroid Build Coastguard Worker #include <assert.h>
23*ec779b8eSAndroid Build Coastguard Worker #include <binder/IPCThreadState.h>
24*ec779b8eSAndroid Build Coastguard Worker #include <iomanip>
25*ec779b8eSAndroid Build Coastguard Worker #include <iostream>
26*ec779b8eSAndroid Build Coastguard Worker #include <map>
27*ec779b8eSAndroid Build Coastguard Worker #include <mutex>
28*ec779b8eSAndroid Build Coastguard Worker #include <utils/Singleton.h>
29*ec779b8eSAndroid Build Coastguard Worker
30*ec779b8eSAndroid Build Coastguard Worker #include "utility/AAudioUtilities.h"
31*ec779b8eSAndroid Build Coastguard Worker #include "AAudioEndpointManager.h"
32*ec779b8eSAndroid Build Coastguard Worker #include "AAudioServiceEndpoint.h"
33*ec779b8eSAndroid Build Coastguard Worker #include "AAudioClientTracker.h"
34*ec779b8eSAndroid Build Coastguard Worker
35*ec779b8eSAndroid Build Coastguard Worker using namespace android;
36*ec779b8eSAndroid Build Coastguard Worker using namespace aaudio;
37*ec779b8eSAndroid Build Coastguard Worker
38*ec779b8eSAndroid Build Coastguard Worker ANDROID_SINGLETON_STATIC_INSTANCE(AAudioClientTracker);
39*ec779b8eSAndroid Build Coastguard Worker
AAudioClientTracker()40*ec779b8eSAndroid Build Coastguard Worker AAudioClientTracker::AAudioClientTracker()
41*ec779b8eSAndroid Build Coastguard Worker : Singleton<AAudioClientTracker>() {
42*ec779b8eSAndroid Build Coastguard Worker }
43*ec779b8eSAndroid Build Coastguard Worker
dump() const44*ec779b8eSAndroid Build Coastguard Worker std::string AAudioClientTracker::dump() const NO_THREAD_SAFETY_ANALYSIS {
45*ec779b8eSAndroid Build Coastguard Worker std::stringstream result;
46*ec779b8eSAndroid Build Coastguard Worker const bool isLocked = AAudio_tryUntilTrue(
47*ec779b8eSAndroid Build Coastguard Worker [this]()->bool { return mLock.try_lock(); } /* f */,
48*ec779b8eSAndroid Build Coastguard Worker 50 /* times */,
49*ec779b8eSAndroid Build Coastguard Worker 20 /* sleepMs */);
50*ec779b8eSAndroid Build Coastguard Worker if (!isLocked) {
51*ec779b8eSAndroid Build Coastguard Worker result << "AAudioClientTracker may be deadlocked\n";
52*ec779b8eSAndroid Build Coastguard Worker }
53*ec779b8eSAndroid Build Coastguard Worker
54*ec779b8eSAndroid Build Coastguard Worker result << "AAudioClientTracker:\n";
55*ec779b8eSAndroid Build Coastguard Worker for (const auto& it : mNotificationClients) {
56*ec779b8eSAndroid Build Coastguard Worker result << it.second->dump();
57*ec779b8eSAndroid Build Coastguard Worker }
58*ec779b8eSAndroid Build Coastguard Worker
59*ec779b8eSAndroid Build Coastguard Worker if (isLocked) {
60*ec779b8eSAndroid Build Coastguard Worker mLock.unlock();
61*ec779b8eSAndroid Build Coastguard Worker }
62*ec779b8eSAndroid Build Coastguard Worker return result.str();
63*ec779b8eSAndroid Build Coastguard Worker }
64*ec779b8eSAndroid Build Coastguard Worker
65*ec779b8eSAndroid Build Coastguard Worker // Create a tracker for the client.
registerClient(pid_t pid,const sp<IAAudioClient> & client)66*ec779b8eSAndroid Build Coastguard Worker aaudio_result_t AAudioClientTracker::registerClient(pid_t pid,
67*ec779b8eSAndroid Build Coastguard Worker const sp<IAAudioClient>& client) {
68*ec779b8eSAndroid Build Coastguard Worker ALOGV("registerClient(), calling pid = %d, getpid() = %d\n", pid, getpid());
69*ec779b8eSAndroid Build Coastguard Worker
70*ec779b8eSAndroid Build Coastguard Worker if (client.get() == nullptr) {
71*ec779b8eSAndroid Build Coastguard Worker ALOGE("AAudioClientTracker::%s() client is NULL!", __func__);
72*ec779b8eSAndroid Build Coastguard Worker android_errorWriteLog(0x534e4554, "116230453");
73*ec779b8eSAndroid Build Coastguard Worker return AAUDIO_ERROR_NULL;
74*ec779b8eSAndroid Build Coastguard Worker }
75*ec779b8eSAndroid Build Coastguard Worker
76*ec779b8eSAndroid Build Coastguard Worker const std::lock_guard<std::mutex> lock(mLock);
77*ec779b8eSAndroid Build Coastguard Worker if (mNotificationClients.count(pid) == 0) {
78*ec779b8eSAndroid Build Coastguard Worker const sp<IBinder> binder = IInterface::asBinder(client);
79*ec779b8eSAndroid Build Coastguard Worker const sp<NotificationClient> notificationClient = new NotificationClient(pid, binder);
80*ec779b8eSAndroid Build Coastguard Worker mNotificationClients[pid] = notificationClient;
81*ec779b8eSAndroid Build Coastguard Worker
82*ec779b8eSAndroid Build Coastguard Worker const status_t status = binder->linkToDeath(notificationClient);
83*ec779b8eSAndroid Build Coastguard Worker ALOGW_IF(status != NO_ERROR, "registerClient() linkToDeath = %d\n", status);
84*ec779b8eSAndroid Build Coastguard Worker return AAudioConvert_androidToAAudioResult(status);
85*ec779b8eSAndroid Build Coastguard Worker } else {
86*ec779b8eSAndroid Build Coastguard Worker ALOGW("registerClient(%d) already registered!", pid);
87*ec779b8eSAndroid Build Coastguard Worker return AAUDIO_OK; // TODO should this be considered an error
88*ec779b8eSAndroid Build Coastguard Worker }
89*ec779b8eSAndroid Build Coastguard Worker }
90*ec779b8eSAndroid Build Coastguard Worker
unregisterClient(pid_t pid)91*ec779b8eSAndroid Build Coastguard Worker void AAudioClientTracker::unregisterClient(pid_t pid) {
92*ec779b8eSAndroid Build Coastguard Worker ALOGV("unregisterClient(), calling pid = %d, getpid() = %d\n", pid, getpid());
93*ec779b8eSAndroid Build Coastguard Worker const std::lock_guard<std::mutex> lock(mLock);
94*ec779b8eSAndroid Build Coastguard Worker mNotificationClients.erase(pid);
95*ec779b8eSAndroid Build Coastguard Worker }
96*ec779b8eSAndroid Build Coastguard Worker
getStreamCount(pid_t pid)97*ec779b8eSAndroid Build Coastguard Worker int32_t AAudioClientTracker::getStreamCount(pid_t pid) {
98*ec779b8eSAndroid Build Coastguard Worker const std::lock_guard<std::mutex> lock(mLock);
99*ec779b8eSAndroid Build Coastguard Worker auto it = mNotificationClients.find(pid);
100*ec779b8eSAndroid Build Coastguard Worker if (it != mNotificationClients.end()) {
101*ec779b8eSAndroid Build Coastguard Worker return it->second->getStreamCount();
102*ec779b8eSAndroid Build Coastguard Worker } else {
103*ec779b8eSAndroid Build Coastguard Worker return 0; // no existing client
104*ec779b8eSAndroid Build Coastguard Worker }
105*ec779b8eSAndroid Build Coastguard Worker }
106*ec779b8eSAndroid Build Coastguard Worker
107*ec779b8eSAndroid Build Coastguard Worker aaudio_result_t
registerClientStream(pid_t pid,const sp<AAudioServiceStreamBase> & serviceStream)108*ec779b8eSAndroid Build Coastguard Worker AAudioClientTracker::registerClientStream(
109*ec779b8eSAndroid Build Coastguard Worker pid_t pid, const sp<AAudioServiceStreamBase>& serviceStream) {
110*ec779b8eSAndroid Build Coastguard Worker ALOGV("registerClientStream(%d,)\n", pid);
111*ec779b8eSAndroid Build Coastguard Worker const std::lock_guard<std::mutex> lock(mLock);
112*ec779b8eSAndroid Build Coastguard Worker return getNotificationClient_l(pid)->registerClientStream(serviceStream);
113*ec779b8eSAndroid Build Coastguard Worker }
114*ec779b8eSAndroid Build Coastguard Worker
115*ec779b8eSAndroid Build Coastguard Worker // Find the tracker for this process and remove it.
116*ec779b8eSAndroid Build Coastguard Worker aaudio_result_t
unregisterClientStream(pid_t pid,const sp<AAudioServiceStreamBase> & serviceStream)117*ec779b8eSAndroid Build Coastguard Worker AAudioClientTracker::unregisterClientStream(pid_t pid,
118*ec779b8eSAndroid Build Coastguard Worker const sp<AAudioServiceStreamBase>& serviceStream) {
119*ec779b8eSAndroid Build Coastguard Worker ALOGV("unregisterClientStream(%d,)\n", pid);
120*ec779b8eSAndroid Build Coastguard Worker const std::lock_guard<std::mutex> lock(mLock);
121*ec779b8eSAndroid Build Coastguard Worker auto it = mNotificationClients.find(pid);
122*ec779b8eSAndroid Build Coastguard Worker if (it != mNotificationClients.end()) {
123*ec779b8eSAndroid Build Coastguard Worker ALOGV("unregisterClientStream(%d,) found NotificationClient\n", pid);
124*ec779b8eSAndroid Build Coastguard Worker it->second->unregisterClientStream(serviceStream);
125*ec779b8eSAndroid Build Coastguard Worker } else {
126*ec779b8eSAndroid Build Coastguard Worker ALOGE("unregisterClientStream(%d,) missing NotificationClient\n", pid);
127*ec779b8eSAndroid Build Coastguard Worker }
128*ec779b8eSAndroid Build Coastguard Worker return AAUDIO_OK;
129*ec779b8eSAndroid Build Coastguard Worker }
130*ec779b8eSAndroid Build Coastguard Worker
setExclusiveEnabled(pid_t pid,bool enabled)131*ec779b8eSAndroid Build Coastguard Worker void AAudioClientTracker::setExclusiveEnabled(pid_t pid, bool enabled) {
132*ec779b8eSAndroid Build Coastguard Worker ALOGD("%s(%d, %d)\n", __func__, pid, enabled);
133*ec779b8eSAndroid Build Coastguard Worker const std::lock_guard<std::mutex> lock(mLock);
134*ec779b8eSAndroid Build Coastguard Worker getNotificationClient_l(pid)->setExclusiveEnabled(enabled);
135*ec779b8eSAndroid Build Coastguard Worker }
136*ec779b8eSAndroid Build Coastguard Worker
isExclusiveEnabled(pid_t pid)137*ec779b8eSAndroid Build Coastguard Worker bool AAudioClientTracker::isExclusiveEnabled(pid_t pid) {
138*ec779b8eSAndroid Build Coastguard Worker const std::lock_guard<std::mutex> lock(mLock);
139*ec779b8eSAndroid Build Coastguard Worker return getNotificationClient_l(pid)->isExclusiveEnabled();
140*ec779b8eSAndroid Build Coastguard Worker }
141*ec779b8eSAndroid Build Coastguard Worker
142*ec779b8eSAndroid Build Coastguard Worker sp<AAudioClientTracker::NotificationClient>
getNotificationClient_l(pid_t pid)143*ec779b8eSAndroid Build Coastguard Worker AAudioClientTracker::getNotificationClient_l(pid_t pid) {
144*ec779b8eSAndroid Build Coastguard Worker sp<NotificationClient> notificationClient = mNotificationClients[pid];
145*ec779b8eSAndroid Build Coastguard Worker if (notificationClient == nullptr) {
146*ec779b8eSAndroid Build Coastguard Worker // This will get called the first time the audio server uses this PID.
147*ec779b8eSAndroid Build Coastguard Worker ALOGV("%s(%d,) unrecognized PID\n", __func__, pid);
148*ec779b8eSAndroid Build Coastguard Worker notificationClient = new AAudioClientTracker::NotificationClient(pid, nullptr);
149*ec779b8eSAndroid Build Coastguard Worker mNotificationClients[pid] = notificationClient;
150*ec779b8eSAndroid Build Coastguard Worker }
151*ec779b8eSAndroid Build Coastguard Worker return notificationClient;
152*ec779b8eSAndroid Build Coastguard Worker }
153*ec779b8eSAndroid Build Coastguard Worker
154*ec779b8eSAndroid Build Coastguard Worker // =======================================
155*ec779b8eSAndroid Build Coastguard Worker // AAudioClientTracker::NotificationClient
156*ec779b8eSAndroid Build Coastguard Worker // =======================================
157*ec779b8eSAndroid Build Coastguard Worker
NotificationClient(pid_t pid,const sp<IBinder> & binder)158*ec779b8eSAndroid Build Coastguard Worker AAudioClientTracker::NotificationClient::NotificationClient(pid_t pid, const sp<IBinder>& binder)
159*ec779b8eSAndroid Build Coastguard Worker : mProcessId(pid), mBinder(binder) {
160*ec779b8eSAndroid Build Coastguard Worker }
161*ec779b8eSAndroid Build Coastguard Worker
getStreamCount()162*ec779b8eSAndroid Build Coastguard Worker int32_t AAudioClientTracker::NotificationClient::getStreamCount() {
163*ec779b8eSAndroid Build Coastguard Worker const std::lock_guard<std::mutex> lock(mLock);
164*ec779b8eSAndroid Build Coastguard Worker return mStreams.size();
165*ec779b8eSAndroid Build Coastguard Worker }
166*ec779b8eSAndroid Build Coastguard Worker
registerClientStream(const sp<AAudioServiceStreamBase> & serviceStream)167*ec779b8eSAndroid Build Coastguard Worker aaudio_result_t AAudioClientTracker::NotificationClient::registerClientStream(
168*ec779b8eSAndroid Build Coastguard Worker const sp<AAudioServiceStreamBase>& serviceStream) {
169*ec779b8eSAndroid Build Coastguard Worker const std::lock_guard<std::mutex> lock(mLock);
170*ec779b8eSAndroid Build Coastguard Worker mStreams.insert(serviceStream);
171*ec779b8eSAndroid Build Coastguard Worker return AAUDIO_OK;
172*ec779b8eSAndroid Build Coastguard Worker }
173*ec779b8eSAndroid Build Coastguard Worker
unregisterClientStream(const sp<AAudioServiceStreamBase> & serviceStream)174*ec779b8eSAndroid Build Coastguard Worker aaudio_result_t AAudioClientTracker::NotificationClient::unregisterClientStream(
175*ec779b8eSAndroid Build Coastguard Worker const sp<AAudioServiceStreamBase>& serviceStream) {
176*ec779b8eSAndroid Build Coastguard Worker const std::lock_guard<std::mutex> lock(mLock);
177*ec779b8eSAndroid Build Coastguard Worker mStreams.erase(serviceStream);
178*ec779b8eSAndroid Build Coastguard Worker return AAUDIO_OK;
179*ec779b8eSAndroid Build Coastguard Worker }
180*ec779b8eSAndroid Build Coastguard Worker
181*ec779b8eSAndroid Build Coastguard Worker // Close any open streams for the client.
binderDied(const wp<IBinder> & who __unused)182*ec779b8eSAndroid Build Coastguard Worker void AAudioClientTracker::NotificationClient::binderDied(const wp<IBinder>& who __unused) {
183*ec779b8eSAndroid Build Coastguard Worker AAudioService *aaudioService = AAudioClientTracker::getInstance().getAAudioService();
184*ec779b8eSAndroid Build Coastguard Worker if (aaudioService != nullptr) {
185*ec779b8eSAndroid Build Coastguard Worker // Copy the current list of streams to another vector because closing them below
186*ec779b8eSAndroid Build Coastguard Worker // will cause unregisterClientStream() calls back to this object.
187*ec779b8eSAndroid Build Coastguard Worker std::set<sp<AAudioServiceStreamBase>> streamsToClose;
188*ec779b8eSAndroid Build Coastguard Worker
189*ec779b8eSAndroid Build Coastguard Worker {
190*ec779b8eSAndroid Build Coastguard Worker const std::lock_guard<std::mutex> lock(mLock);
191*ec779b8eSAndroid Build Coastguard Worker for (const auto& serviceStream : mStreams) {
192*ec779b8eSAndroid Build Coastguard Worker streamsToClose.insert(serviceStream);
193*ec779b8eSAndroid Build Coastguard Worker }
194*ec779b8eSAndroid Build Coastguard Worker }
195*ec779b8eSAndroid Build Coastguard Worker
196*ec779b8eSAndroid Build Coastguard Worker for (const auto& serviceStream : streamsToClose) {
197*ec779b8eSAndroid Build Coastguard Worker const aaudio_handle_t handle = serviceStream->getHandle();
198*ec779b8eSAndroid Build Coastguard Worker ALOGW("binderDied() close abandoned stream 0x%08X\n", handle);
199*ec779b8eSAndroid Build Coastguard Worker AAudioHandleInfo handleInfo(DEFAULT_AAUDIO_SERVICE_ID, handle);
200*ec779b8eSAndroid Build Coastguard Worker aaudioService->asAAudioServiceInterface().closeStream(handleInfo);
201*ec779b8eSAndroid Build Coastguard Worker }
202*ec779b8eSAndroid Build Coastguard Worker // mStreams should be empty now
203*ec779b8eSAndroid Build Coastguard Worker }
204*ec779b8eSAndroid Build Coastguard Worker const sp<NotificationClient> keep(this);
205*ec779b8eSAndroid Build Coastguard Worker AAudioClientTracker::getInstance().unregisterClient(mProcessId);
206*ec779b8eSAndroid Build Coastguard Worker }
207*ec779b8eSAndroid Build Coastguard Worker
208*ec779b8eSAndroid Build Coastguard Worker
dump() const209*ec779b8eSAndroid Build Coastguard Worker std::string AAudioClientTracker::NotificationClient::dump() const NO_THREAD_SAFETY_ANALYSIS {
210*ec779b8eSAndroid Build Coastguard Worker std::stringstream result;
211*ec779b8eSAndroid Build Coastguard Worker const bool isLocked = AAudio_tryUntilTrue(
212*ec779b8eSAndroid Build Coastguard Worker [this]()->bool { return mLock.try_lock(); } /* f */,
213*ec779b8eSAndroid Build Coastguard Worker 50 /* times */,
214*ec779b8eSAndroid Build Coastguard Worker 20 /* sleepMs */);
215*ec779b8eSAndroid Build Coastguard Worker if (!isLocked) {
216*ec779b8eSAndroid Build Coastguard Worker result << "AAudioClientTracker::NotificationClient may be deadlocked\n";
217*ec779b8eSAndroid Build Coastguard Worker }
218*ec779b8eSAndroid Build Coastguard Worker
219*ec779b8eSAndroid Build Coastguard Worker result << " client: pid = " << mProcessId << " has " << mStreams.size() << " streams\n";
220*ec779b8eSAndroid Build Coastguard Worker for (const auto& serviceStream : mStreams) {
221*ec779b8eSAndroid Build Coastguard Worker result << " stream: 0x" << std::setfill('0') << std::setw(8) << std::hex
222*ec779b8eSAndroid Build Coastguard Worker << serviceStream->getHandle()
223*ec779b8eSAndroid Build Coastguard Worker << std::dec << std::setfill(' ') << "\n";
224*ec779b8eSAndroid Build Coastguard Worker }
225*ec779b8eSAndroid Build Coastguard Worker
226*ec779b8eSAndroid Build Coastguard Worker if (isLocked) {
227*ec779b8eSAndroid Build Coastguard Worker mLock.unlock();
228*ec779b8eSAndroid Build Coastguard Worker }
229*ec779b8eSAndroid Build Coastguard Worker return result.str();
230*ec779b8eSAndroid Build Coastguard Worker }
231