blob: da7b80fa56a0bec35994f23de85c3b86dd866d30 [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
71aaudio_result_t
72AAudioClientTracker::registerClientStream(pid_t pid, sp<AAudioServiceStreamBase> serviceStream) {
73 aaudio_result_t result = AAUDIO_OK;
74 ALOGV("AAudioClientTracker::registerClientStream(%d, %p)\n", pid, serviceStream.get());
75 std::lock_guard<std::mutex> lock(mLock);
76 sp<NotificationClient> notificationClient = mNotificationClients[pid];
77 if (notificationClient == 0) {
78 // This will get called the first time the audio server registers an internal stream.
79 ALOGV("AAudioClientTracker::registerClientStream(%d,) unrecognized pid\n", pid);
80 notificationClient = new NotificationClient(pid);
81 mNotificationClients[pid] = notificationClient;
82 }
83 notificationClient->registerClientStream(serviceStream);
84 return result;
85}
86
87// Find the tracker for this process and remove it.
88aaudio_result_t
89AAudioClientTracker::unregisterClientStream(pid_t pid,
90 sp<AAudioServiceStreamBase> serviceStream) {
91 ALOGV("AAudioClientTracker::unregisterClientStream(%d, %p)\n", pid, serviceStream.get());
92 std::lock_guard<std::mutex> lock(mLock);
93 std::map<pid_t, android::sp<NotificationClient>>::iterator it;
94 it = mNotificationClients.find(pid);
95 if (it != mNotificationClients.end()) {
96 it->second->unregisterClientStream(serviceStream);
97 }
98 return AAUDIO_OK;
99}
100
101AAudioClientTracker::NotificationClient::NotificationClient(pid_t pid)
102 : mProcessId(pid) {
103 //ALOGD("AAudioClientTracker::NotificationClient(%d) created %p\n", pid, this);
104}
105
106AAudioClientTracker::NotificationClient::~NotificationClient() {
107 //ALOGD("AAudioClientTracker::~NotificationClient() destroyed %p\n", this);
108}
109
110aaudio_result_t AAudioClientTracker::NotificationClient::registerClientStream(
111 sp<AAudioServiceStreamBase> serviceStream) {
112 std::lock_guard<std::mutex> lock(mLock);
113 mStreams.insert(serviceStream);
114 return AAUDIO_OK;
115}
116
117aaudio_result_t AAudioClientTracker::NotificationClient::unregisterClientStream(
118 sp<AAudioServiceStreamBase> serviceStream) {
119 std::lock_guard<std::mutex> lock(mLock);
120 mStreams.erase(serviceStream);
121 return AAUDIO_OK;
122}
123
124// Close any open streams for the client.
125void AAudioClientTracker::NotificationClient::binderDied(const wp<IBinder>& who __unused) {
126 AAudioService *aaudioService = AAudioClientTracker::getInstance().getAAudioService();
127 if (aaudioService != nullptr) {
128 // Copy the current list of streams to another vector because closing them below
129 // will cause unregisterClientStream() calls back to this object.
130 std::set<android::sp<AAudioServiceStreamBase>> streamsToClose;
131
132 {
133 std::lock_guard<std::mutex> lock(mLock);
134 ALOGV("AAudioClientTracker::binderDied() pid = %d, # streams = %d\n",
135 mProcessId, (int) mStreams.size());
136 for (auto serviceStream : mStreams) {
137 streamsToClose.insert(serviceStream);
138 }
139 }
140
141 for (auto serviceStream : streamsToClose) {
142 aaudio_handle_t handle = serviceStream->getHandle();
143 ALOGW("AAudioClientTracker::binderDied() close abandoned stream 0x%08X\n", handle);
144 aaudioService->closeStream(handle);
145 }
146 // mStreams should be empty now
147 }
148 sp<NotificationClient> keep(this);
149 AAudioClientTracker::getInstance().unregisterClient(mProcessId);
150}