xref: /aosp_15_r20/frameworks/av/services/oboeservice/AAudioClientTracker.cpp (revision ec779b8e0859a360c3d303172224686826e6e0e1)
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