blob: c0dfc545e05ef2519454e9fe51cf6f04e20a3268 [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
42// Create a tracker for the client.
43aaudio_result_t AAudioClientTracker::registerClient(pid_t pid,
44 const sp<IAAudioClient>& client) {
45 ALOGD("AAudioClientTracker::registerClient(), calling pid = %d, getpid() = %d\n",
46 pid, getpid());
47
48 std::lock_guard<std::mutex> lock(mLock);
49 if (mNotificationClients.count(pid) == 0) {
50 sp<NotificationClient> notificationClient = new NotificationClient(pid);
51 mNotificationClients[pid] = notificationClient;
52
53 sp<IBinder> binder = IInterface::asBinder(client);
54 status_t status = binder->linkToDeath(notificationClient);
55 ALOGW_IF(status != NO_ERROR,
56 "AAudioClientTracker::registerClient() linkToDeath = %d\n", status);
57 return AAudioConvert_androidToAAudioResult(status);
58 } else {
59 ALOGW("AAudioClientTracker::registerClient(%d) already registered!", pid);
60 return AAUDIO_OK; // TODO should this be considered an error
61 }
62}
63
64void AAudioClientTracker::unregisterClient(pid_t pid) {
65 ALOGD("AAudioClientTracker::unregisterClient(), calling pid = %d, getpid() = %d\n",
66 pid, getpid());
67 std::lock_guard<std::mutex> lock(mLock);
68 mNotificationClients.erase(pid);
69}
70
Phil Burk91692942017-06-30 12:23:05 -070071int32_t AAudioClientTracker::getStreamCount(pid_t pid) {
72 std::lock_guard<std::mutex> lock(mLock);
73 auto it = mNotificationClients.find(pid);
74 if (it != mNotificationClients.end()) {
75 return it->second->getStreamCount();
76 } else {
77 return 0; // no existing client
78 }
79}
80
Phil Burk11e8d332017-05-24 09:59:02 -070081aaudio_result_t
82AAudioClientTracker::registerClientStream(pid_t pid, sp<AAudioServiceStreamBase> serviceStream) {
83 aaudio_result_t result = AAUDIO_OK;
84 ALOGV("AAudioClientTracker::registerClientStream(%d, %p)\n", pid, serviceStream.get());
85 std::lock_guard<std::mutex> lock(mLock);
86 sp<NotificationClient> notificationClient = mNotificationClients[pid];
87 if (notificationClient == 0) {
88 // This will get called the first time the audio server registers an internal stream.
89 ALOGV("AAudioClientTracker::registerClientStream(%d,) unrecognized pid\n", pid);
90 notificationClient = new NotificationClient(pid);
91 mNotificationClients[pid] = notificationClient;
92 }
93 notificationClient->registerClientStream(serviceStream);
94 return result;
95}
96
97// Find the tracker for this process and remove it.
98aaudio_result_t
99AAudioClientTracker::unregisterClientStream(pid_t pid,
100 sp<AAudioServiceStreamBase> serviceStream) {
101 ALOGV("AAudioClientTracker::unregisterClientStream(%d, %p)\n", pid, serviceStream.get());
102 std::lock_guard<std::mutex> lock(mLock);
Phil Burk91692942017-06-30 12:23:05 -0700103 auto it = mNotificationClients.find(pid);
Phil Burk11e8d332017-05-24 09:59:02 -0700104 if (it != mNotificationClients.end()) {
105 it->second->unregisterClientStream(serviceStream);
106 }
107 return AAUDIO_OK;
108}
109
110AAudioClientTracker::NotificationClient::NotificationClient(pid_t pid)
111 : mProcessId(pid) {
112 //ALOGD("AAudioClientTracker::NotificationClient(%d) created %p\n", pid, this);
113}
114
115AAudioClientTracker::NotificationClient::~NotificationClient() {
116 //ALOGD("AAudioClientTracker::~NotificationClient() destroyed %p\n", this);
117}
118
Phil Burk91692942017-06-30 12:23:05 -0700119int32_t AAudioClientTracker::NotificationClient::getStreamCount() {
120 std::lock_guard<std::mutex> lock(mLock);
121 return mStreams.size();
122}
123
Phil Burk11e8d332017-05-24 09:59:02 -0700124aaudio_result_t AAudioClientTracker::NotificationClient::registerClientStream(
125 sp<AAudioServiceStreamBase> serviceStream) {
126 std::lock_guard<std::mutex> lock(mLock);
127 mStreams.insert(serviceStream);
128 return AAUDIO_OK;
129}
130
131aaudio_result_t AAudioClientTracker::NotificationClient::unregisterClientStream(
132 sp<AAudioServiceStreamBase> serviceStream) {
133 std::lock_guard<std::mutex> lock(mLock);
134 mStreams.erase(serviceStream);
135 return AAUDIO_OK;
136}
137
138// Close any open streams for the client.
139void AAudioClientTracker::NotificationClient::binderDied(const wp<IBinder>& who __unused) {
140 AAudioService *aaudioService = AAudioClientTracker::getInstance().getAAudioService();
141 if (aaudioService != nullptr) {
142 // Copy the current list of streams to another vector because closing them below
143 // will cause unregisterClientStream() calls back to this object.
144 std::set<android::sp<AAudioServiceStreamBase>> streamsToClose;
145
146 {
147 std::lock_guard<std::mutex> lock(mLock);
148 ALOGV("AAudioClientTracker::binderDied() pid = %d, # streams = %d\n",
149 mProcessId, (int) mStreams.size());
150 for (auto serviceStream : mStreams) {
151 streamsToClose.insert(serviceStream);
152 }
153 }
154
155 for (auto serviceStream : streamsToClose) {
156 aaudio_handle_t handle = serviceStream->getHandle();
157 ALOGW("AAudioClientTracker::binderDied() close abandoned stream 0x%08X\n", handle);
158 aaudioService->closeStream(handle);
159 }
160 // mStreams should be empty now
161 }
162 sp<NotificationClient> keep(this);
163 AAudioClientTracker::getInstance().unregisterClient(mProcessId);
164}