blob: 549a4e987e5e97c28c3fdda49be23ddd143fb550 [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
Phil Burkfbf031e2017-10-12 15:58:31 -070018#define LOG_TAG "AAudioClientTracker"
Phil Burk11e8d332017-05-24 09:59:02 -070019//#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 Burkfbf031e2017-10-12 15:58:31 -070067 ALOGV("registerClient(), calling pid = %d, getpid() = %d\n", pid, getpid());
Phil Burk11e8d332017-05-24 09:59:02 -070068
69 std::lock_guard<std::mutex> lock(mLock);
70 if (mNotificationClients.count(pid) == 0) {
71 sp<NotificationClient> notificationClient = new NotificationClient(pid);
72 mNotificationClients[pid] = notificationClient;
73
74 sp<IBinder> binder = IInterface::asBinder(client);
75 status_t status = binder->linkToDeath(notificationClient);
Phil Burkfbf031e2017-10-12 15:58:31 -070076 ALOGW_IF(status != NO_ERROR, "registerClient() linkToDeath = %d\n", status);
Phil Burk11e8d332017-05-24 09:59:02 -070077 return AAudioConvert_androidToAAudioResult(status);
78 } else {
Phil Burkfbf031e2017-10-12 15:58:31 -070079 ALOGW("registerClient(%d) already registered!", pid);
Phil Burk11e8d332017-05-24 09:59:02 -070080 return AAUDIO_OK; // TODO should this be considered an error
81 }
82}
83
84void AAudioClientTracker::unregisterClient(pid_t pid) {
Phil Burkfbf031e2017-10-12 15:58:31 -070085 ALOGV("unregisterClient(), calling pid = %d, getpid() = %d\n", pid, getpid());
Phil Burk11e8d332017-05-24 09:59:02 -070086 std::lock_guard<std::mutex> lock(mLock);
87 mNotificationClients.erase(pid);
88}
89
Phil Burk91692942017-06-30 12:23:05 -070090int32_t AAudioClientTracker::getStreamCount(pid_t pid) {
91 std::lock_guard<std::mutex> lock(mLock);
92 auto it = mNotificationClients.find(pid);
93 if (it != mNotificationClients.end()) {
94 return it->second->getStreamCount();
95 } else {
96 return 0; // no existing client
97 }
98}
99
Phil Burk11e8d332017-05-24 09:59:02 -0700100aaudio_result_t
101AAudioClientTracker::registerClientStream(pid_t pid, sp<AAudioServiceStreamBase> serviceStream) {
102 aaudio_result_t result = AAUDIO_OK;
Phil Burkfbf031e2017-10-12 15:58:31 -0700103 ALOGV("registerClientStream(%d, %p)\n", pid, serviceStream.get());
Phil Burk11e8d332017-05-24 09:59:02 -0700104 std::lock_guard<std::mutex> lock(mLock);
105 sp<NotificationClient> notificationClient = mNotificationClients[pid];
106 if (notificationClient == 0) {
107 // This will get called the first time the audio server registers an internal stream.
Phil Burkfbf031e2017-10-12 15:58:31 -0700108 ALOGV("registerClientStream(%d,) unrecognized pid\n", pid);
Phil Burk11e8d332017-05-24 09:59:02 -0700109 notificationClient = new NotificationClient(pid);
110 mNotificationClients[pid] = notificationClient;
111 }
112 notificationClient->registerClientStream(serviceStream);
113 return result;
114}
115
116// Find the tracker for this process and remove it.
117aaudio_result_t
118AAudioClientTracker::unregisterClientStream(pid_t pid,
119 sp<AAudioServiceStreamBase> serviceStream) {
Phil Burkfbf031e2017-10-12 15:58:31 -0700120 ALOGV("unregisterClientStream(%d, %p)\n", pid, serviceStream.get());
Phil Burk11e8d332017-05-24 09:59:02 -0700121 std::lock_guard<std::mutex> lock(mLock);
Phil Burk91692942017-06-30 12:23:05 -0700122 auto it = mNotificationClients.find(pid);
Phil Burk11e8d332017-05-24 09:59:02 -0700123 if (it != mNotificationClients.end()) {
Phil Burkfbf031e2017-10-12 15:58:31 -0700124 ALOGV("unregisterClientStream(%d, %p) found NotificationClient\n",
Phil Burk4501b352017-06-29 18:12:36 -0700125 pid, serviceStream.get());
Phil Burk11e8d332017-05-24 09:59:02 -0700126 it->second->unregisterClientStream(serviceStream);
Phil Burk4501b352017-06-29 18:12:36 -0700127 } else {
Phil Burkfbf031e2017-10-12 15:58:31 -0700128 ALOGE("unregisterClientStream(%d, %p) missing NotificationClient\n",
Phil Burk4501b352017-06-29 18:12:36 -0700129 pid, serviceStream.get());
Phil Burk11e8d332017-05-24 09:59:02 -0700130 }
131 return AAUDIO_OK;
132}
133
134AAudioClientTracker::NotificationClient::NotificationClient(pid_t pid)
135 : mProcessId(pid) {
Phil Burkfbf031e2017-10-12 15:58:31 -0700136 //ALOGD("NotificationClient(%d) created %p\n", pid, this);
Phil Burk11e8d332017-05-24 09:59:02 -0700137}
138
139AAudioClientTracker::NotificationClient::~NotificationClient() {
Phil Burkfbf031e2017-10-12 15:58:31 -0700140 //ALOGD("~NotificationClient() destroyed %p\n", this);
Phil Burk11e8d332017-05-24 09:59:02 -0700141}
142
Phil Burk91692942017-06-30 12:23:05 -0700143int32_t AAudioClientTracker::NotificationClient::getStreamCount() {
144 std::lock_guard<std::mutex> lock(mLock);
145 return mStreams.size();
146}
147
Phil Burk11e8d332017-05-24 09:59:02 -0700148aaudio_result_t AAudioClientTracker::NotificationClient::registerClientStream(
149 sp<AAudioServiceStreamBase> serviceStream) {
150 std::lock_guard<std::mutex> lock(mLock);
151 mStreams.insert(serviceStream);
152 return AAUDIO_OK;
153}
154
155aaudio_result_t AAudioClientTracker::NotificationClient::unregisterClientStream(
156 sp<AAudioServiceStreamBase> serviceStream) {
157 std::lock_guard<std::mutex> lock(mLock);
158 mStreams.erase(serviceStream);
159 return AAUDIO_OK;
160}
161
162// Close any open streams for the client.
163void AAudioClientTracker::NotificationClient::binderDied(const wp<IBinder>& who __unused) {
164 AAudioService *aaudioService = AAudioClientTracker::getInstance().getAAudioService();
165 if (aaudioService != nullptr) {
166 // Copy the current list of streams to another vector because closing them below
167 // will cause unregisterClientStream() calls back to this object.
Phil Burk4501b352017-06-29 18:12:36 -0700168 std::set<sp<AAudioServiceStreamBase>> streamsToClose;
Phil Burk11e8d332017-05-24 09:59:02 -0700169
170 {
171 std::lock_guard<std::mutex> lock(mLock);
Chih-Hung Hsieh48fc6192017-08-04 14:37:31 -0700172 for (const auto& serviceStream : mStreams) {
Phil Burk11e8d332017-05-24 09:59:02 -0700173 streamsToClose.insert(serviceStream);
174 }
175 }
176
Chih-Hung Hsieh48fc6192017-08-04 14:37:31 -0700177 for (const auto& serviceStream : streamsToClose) {
Phil Burk11e8d332017-05-24 09:59:02 -0700178 aaudio_handle_t handle = serviceStream->getHandle();
Phil Burkfbf031e2017-10-12 15:58:31 -0700179 ALOGW("binderDied() close abandoned stream 0x%08X\n", handle);
Phil Burk11e8d332017-05-24 09:59:02 -0700180 aaudioService->closeStream(handle);
181 }
182 // mStreams should be empty now
183 }
184 sp<NotificationClient> keep(this);
185 AAudioClientTracker::getInstance().unregisterClient(mProcessId);
186}
Phil Burk4501b352017-06-29 18:12:36 -0700187
188
189std::string AAudioClientTracker::NotificationClient::dump() const {
190 std::stringstream result;
191 const bool isLocked = AAudio_tryUntilTrue(
192 [this]()->bool { return mLock.try_lock(); } /* f */,
193 50 /* times */,
194 20 /* sleepMs */);
195 if (!isLocked) {
196 result << "AAudioClientTracker::NotificationClient may be deadlocked\n";
197 }
198
199 result << " client: pid = " << mProcessId << " has " << mStreams.size() << " streams\n";
Chih-Hung Hsieh48fc6192017-08-04 14:37:31 -0700200 for (const auto& serviceStream : mStreams) {
Phil Burk4501b352017-06-29 18:12:36 -0700201 result << " stream: 0x" << std::hex << serviceStream->getHandle() << std::dec << "\n";
202 }
203
204 if (isLocked) {
205 mLock.unlock();
206 }
207 return result.str();
208}