blob: 75392bd7915410aa8884ca2780efc2f1d35d7b1d [file] [log] [blame]
Phil Burk11e8d332017-05-24 09:59:02 -07001/*
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
17
18#define LOG_TAG "AAudioService"
19//#define LOG_NDEBUG 0
20#include <utils/Log.h>
21
22#include <assert.h>
23#include <binder/IPCThreadState.h>
24#include <map>
25#include <mutex>
26#include <utils/Singleton.h>
27
28#include "utility/AAudioUtilities.h"
29#include "AAudioEndpointManager.h"
30#include "AAudioServiceEndpoint.h"
31#include "AAudioClientTracker.h"
32
33using namespace android;
34using namespace aaudio;
35
36ANDROID_SINGLETON_STATIC_INSTANCE(AAudioClientTracker);
37
38AAudioClientTracker::AAudioClientTracker()
39 : Singleton<AAudioClientTracker>() {
40}
41
Phil Burk4501b352017-06-29 18:12:36 -070042
43std::string AAudioClientTracker::dump() const {
44 std::stringstream result;
45 const bool isLocked = AAudio_tryUntilTrue(
46 [this]()->bool { return mLock.try_lock(); } /* f */,
47 50 /* times */,
48 20 /* sleepMs */);
49 if (!isLocked) {
50 result << "AAudioClientTracker may be deadlocked\n";
51 }
52
53 result << "AAudioClientTracker:\n";
54 for (const auto& it : mNotificationClients) {
55 result << it.second->dump();
56 }
57
58 if (isLocked) {
59 mLock.unlock();
60 }
61 return result.str();
62}
63
Phil Burk11e8d332017-05-24 09:59:02 -070064// Create a tracker for the client.
65aaudio_result_t AAudioClientTracker::registerClient(pid_t pid,
66 const sp<IAAudioClient>& client) {
Phil Burkc7abac42017-07-17 11:13:37 -070067 ALOGV("AAudioClientTracker::registerClient(), calling pid = %d, getpid() = %d\n",
Phil Burk11e8d332017-05-24 09:59:02 -070068 pid, getpid());
69
70 std::lock_guard<std::mutex> lock(mLock);
71 if (mNotificationClients.count(pid) == 0) {
72 sp<NotificationClient> notificationClient = new NotificationClient(pid);
73 mNotificationClients[pid] = notificationClient;
74
75 sp<IBinder> binder = IInterface::asBinder(client);
76 status_t status = binder->linkToDeath(notificationClient);
77 ALOGW_IF(status != NO_ERROR,
78 "AAudioClientTracker::registerClient() linkToDeath = %d\n", status);
79 return AAudioConvert_androidToAAudioResult(status);
80 } else {
81 ALOGW("AAudioClientTracker::registerClient(%d) already registered!", pid);
82 return AAUDIO_OK; // TODO should this be considered an error
83 }
84}
85
86void AAudioClientTracker::unregisterClient(pid_t pid) {
Phil Burkc7abac42017-07-17 11:13:37 -070087 ALOGV("AAudioClientTracker::unregisterClient(), calling pid = %d, getpid() = %d\n",
Phil Burk11e8d332017-05-24 09:59:02 -070088 pid, getpid());
89 std::lock_guard<std::mutex> lock(mLock);
90 mNotificationClients.erase(pid);
91}
92
Phil Burk91692942017-06-30 12:23:05 -070093int32_t AAudioClientTracker::getStreamCount(pid_t pid) {
94 std::lock_guard<std::mutex> lock(mLock);
95 auto it = mNotificationClients.find(pid);
96 if (it != mNotificationClients.end()) {
97 return it->second->getStreamCount();
98 } else {
99 return 0; // no existing client
100 }
101}
102
Phil Burk11e8d332017-05-24 09:59:02 -0700103aaudio_result_t
104AAudioClientTracker::registerClientStream(pid_t pid, sp<AAudioServiceStreamBase> serviceStream) {
105 aaudio_result_t result = AAUDIO_OK;
Phil Burkc7abac42017-07-17 11:13:37 -0700106 ALOGV("AAudioClientTracker::registerClientStream(%d, %p)\n", pid, serviceStream.get());
Phil Burk11e8d332017-05-24 09:59:02 -0700107 std::lock_guard<std::mutex> lock(mLock);
108 sp<NotificationClient> notificationClient = mNotificationClients[pid];
109 if (notificationClient == 0) {
110 // This will get called the first time the audio server registers an internal stream.
Phil Burkc7abac42017-07-17 11:13:37 -0700111 ALOGV("AAudioClientTracker::registerClientStream(%d,) unrecognized pid\n", pid);
Phil Burk11e8d332017-05-24 09:59:02 -0700112 notificationClient = new NotificationClient(pid);
113 mNotificationClients[pid] = notificationClient;
114 }
115 notificationClient->registerClientStream(serviceStream);
116 return result;
117}
118
119// Find the tracker for this process and remove it.
120aaudio_result_t
121AAudioClientTracker::unregisterClientStream(pid_t pid,
122 sp<AAudioServiceStreamBase> serviceStream) {
Phil Burkc7abac42017-07-17 11:13:37 -0700123 ALOGV("AAudioClientTracker::unregisterClientStream(%d, %p)\n", pid, serviceStream.get());
Phil Burk11e8d332017-05-24 09:59:02 -0700124 std::lock_guard<std::mutex> lock(mLock);
Phil Burk91692942017-06-30 12:23:05 -0700125 auto it = mNotificationClients.find(pid);
Phil Burk11e8d332017-05-24 09:59:02 -0700126 if (it != mNotificationClients.end()) {
Phil Burkc7abac42017-07-17 11:13:37 -0700127 ALOGV("AAudioClientTracker::unregisterClientStream(%d, %p) found NotificationClient\n",
Phil Burk4501b352017-06-29 18:12:36 -0700128 pid, serviceStream.get());
Phil Burk11e8d332017-05-24 09:59:02 -0700129 it->second->unregisterClientStream(serviceStream);
Phil Burk4501b352017-06-29 18:12:36 -0700130 } else {
131 ALOGE("AAudioClientTracker::unregisterClientStream(%d, %p) missing NotificationClient\n",
132 pid, serviceStream.get());
Phil Burk11e8d332017-05-24 09:59:02 -0700133 }
134 return AAUDIO_OK;
135}
136
137AAudioClientTracker::NotificationClient::NotificationClient(pid_t pid)
138 : mProcessId(pid) {
139 //ALOGD("AAudioClientTracker::NotificationClient(%d) created %p\n", pid, this);
140}
141
142AAudioClientTracker::NotificationClient::~NotificationClient() {
143 //ALOGD("AAudioClientTracker::~NotificationClient() destroyed %p\n", this);
144}
145
Phil Burk91692942017-06-30 12:23:05 -0700146int32_t AAudioClientTracker::NotificationClient::getStreamCount() {
147 std::lock_guard<std::mutex> lock(mLock);
148 return mStreams.size();
149}
150
Phil Burk11e8d332017-05-24 09:59:02 -0700151aaudio_result_t AAudioClientTracker::NotificationClient::registerClientStream(
152 sp<AAudioServiceStreamBase> serviceStream) {
153 std::lock_guard<std::mutex> lock(mLock);
154 mStreams.insert(serviceStream);
155 return AAUDIO_OK;
156}
157
158aaudio_result_t AAudioClientTracker::NotificationClient::unregisterClientStream(
159 sp<AAudioServiceStreamBase> serviceStream) {
160 std::lock_guard<std::mutex> lock(mLock);
161 mStreams.erase(serviceStream);
162 return AAUDIO_OK;
163}
164
165// Close any open streams for the client.
166void AAudioClientTracker::NotificationClient::binderDied(const wp<IBinder>& who __unused) {
167 AAudioService *aaudioService = AAudioClientTracker::getInstance().getAAudioService();
168 if (aaudioService != nullptr) {
169 // Copy the current list of streams to another vector because closing them below
170 // will cause unregisterClientStream() calls back to this object.
Phil Burk4501b352017-06-29 18:12:36 -0700171 std::set<sp<AAudioServiceStreamBase>> streamsToClose;
Phil Burk11e8d332017-05-24 09:59:02 -0700172
173 {
174 std::lock_guard<std::mutex> lock(mLock);
Phil Burk11e8d332017-05-24 09:59:02 -0700175 for (auto serviceStream : mStreams) {
176 streamsToClose.insert(serviceStream);
177 }
178 }
179
180 for (auto serviceStream : streamsToClose) {
181 aaudio_handle_t handle = serviceStream->getHandle();
182 ALOGW("AAudioClientTracker::binderDied() close abandoned stream 0x%08X\n", handle);
183 aaudioService->closeStream(handle);
184 }
185 // mStreams should be empty now
186 }
187 sp<NotificationClient> keep(this);
188 AAudioClientTracker::getInstance().unregisterClient(mProcessId);
189}
Phil Burk4501b352017-06-29 18:12:36 -0700190
191
192std::string AAudioClientTracker::NotificationClient::dump() const {
193 std::stringstream result;
194 const bool isLocked = AAudio_tryUntilTrue(
195 [this]()->bool { return mLock.try_lock(); } /* f */,
196 50 /* times */,
197 20 /* sleepMs */);
198 if (!isLocked) {
199 result << "AAudioClientTracker::NotificationClient may be deadlocked\n";
200 }
201
202 result << " client: pid = " << mProcessId << " has " << mStreams.size() << " streams\n";
203 for (auto serviceStream : mStreams) {
204 result << " stream: 0x" << std::hex << serviceStream->getHandle() << std::dec << "\n";
205 }
206
207 if (isLocked) {
208 mLock.unlock();
209 }
210 return result.str();
211}