2 * Copyright (C) 2017 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 #define LOG_TAG "AAudioService"
19 //#define LOG_NDEBUG 0
20 #include <utils/Log.h>
23 #include <binder/IPCThreadState.h>
26 #include <utils/Singleton.h>
28 #include "utility/AAudioUtilities.h"
29 #include "AAudioEndpointManager.h"
30 #include "AAudioServiceEndpoint.h"
31 #include "AAudioClientTracker.h"
33 using namespace android;
34 using namespace aaudio;
36 ANDROID_SINGLETON_STATIC_INSTANCE(AAudioClientTracker);
38 AAudioClientTracker::AAudioClientTracker()
39 : Singleton<AAudioClientTracker>() {
43 std::string AAudioClientTracker::dump() const {
44 std::stringstream result;
45 const bool isLocked = AAudio_tryUntilTrue(
46 [this]()->bool { return mLock.try_lock(); } /* f */,
50 result << "AAudioClientTracker may be deadlocked\n";
53 result << "AAudioClientTracker:\n";
54 for (const auto& it : mNotificationClients) {
55 result << it.second->dump();
64 // Create a tracker for the client.
65 aaudio_result_t AAudioClientTracker::registerClient(pid_t pid,
66 const sp<IAAudioClient>& client) {
67 ALOGV("AAudioClientTracker::registerClient(), calling pid = %d, getpid() = %d\n",
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;
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);
81 ALOGW("AAudioClientTracker::registerClient(%d) already registered!", pid);
82 return AAUDIO_OK; // TODO should this be considered an error
86 void AAudioClientTracker::unregisterClient(pid_t pid) {
87 ALOGV("AAudioClientTracker::unregisterClient(), calling pid = %d, getpid() = %d\n",
89 std::lock_guard<std::mutex> lock(mLock);
90 mNotificationClients.erase(pid);
93 int32_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();
99 return 0; // no existing client
104 AAudioClientTracker::registerClientStream(pid_t pid, sp<AAudioServiceStreamBase> serviceStream) {
105 aaudio_result_t result = AAUDIO_OK;
106 ALOGV("AAudioClientTracker::registerClientStream(%d, %p)\n", pid, serviceStream.get());
107 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.
111 ALOGV("AAudioClientTracker::registerClientStream(%d,) unrecognized pid\n", pid);
112 notificationClient = new NotificationClient(pid);
113 mNotificationClients[pid] = notificationClient;
115 notificationClient->registerClientStream(serviceStream);
119 // Find the tracker for this process and remove it.
121 AAudioClientTracker::unregisterClientStream(pid_t pid,
122 sp<AAudioServiceStreamBase> serviceStream) {
123 ALOGV("AAudioClientTracker::unregisterClientStream(%d, %p)\n", pid, serviceStream.get());
124 std::lock_guard<std::mutex> lock(mLock);
125 auto it = mNotificationClients.find(pid);
126 if (it != mNotificationClients.end()) {
127 ALOGV("AAudioClientTracker::unregisterClientStream(%d, %p) found NotificationClient\n",
128 pid, serviceStream.get());
129 it->second->unregisterClientStream(serviceStream);
131 ALOGE("AAudioClientTracker::unregisterClientStream(%d, %p) missing NotificationClient\n",
132 pid, serviceStream.get());
137 AAudioClientTracker::NotificationClient::NotificationClient(pid_t pid)
139 //ALOGD("AAudioClientTracker::NotificationClient(%d) created %p\n", pid, this);
142 AAudioClientTracker::NotificationClient::~NotificationClient() {
143 //ALOGD("AAudioClientTracker::~NotificationClient() destroyed %p\n", this);
146 int32_t AAudioClientTracker::NotificationClient::getStreamCount() {
147 std::lock_guard<std::mutex> lock(mLock);
148 return mStreams.size();
151 aaudio_result_t AAudioClientTracker::NotificationClient::registerClientStream(
152 sp<AAudioServiceStreamBase> serviceStream) {
153 std::lock_guard<std::mutex> lock(mLock);
154 mStreams.insert(serviceStream);
158 aaudio_result_t AAudioClientTracker::NotificationClient::unregisterClientStream(
159 sp<AAudioServiceStreamBase> serviceStream) {
160 std::lock_guard<std::mutex> lock(mLock);
161 mStreams.erase(serviceStream);
165 // Close any open streams for the client.
166 void 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.
171 std::set<sp<AAudioServiceStreamBase>> streamsToClose;
174 std::lock_guard<std::mutex> lock(mLock);
175 for (auto serviceStream : mStreams) {
176 streamsToClose.insert(serviceStream);
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);
185 // mStreams should be empty now
187 sp<NotificationClient> keep(this);
188 AAudioClientTracker::getInstance().unregisterClient(mProcessId);
192 std::string AAudioClientTracker::NotificationClient::dump() const {
193 std::stringstream result;
194 const bool isLocked = AAudio_tryUntilTrue(
195 [this]()->bool { return mLock.try_lock(); } /* f */,
199 result << "AAudioClientTracker::NotificationClient may be deadlocked\n";
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";