OSDN Git Service

aaudio: use weak pointer to prevent UAF
[android-x86/frameworks-av.git] / services / oboeservice / AAudioClientTracker.cpp
1 /*
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
33 using namespace android;
34 using namespace aaudio;
35
36 ANDROID_SINGLETON_STATIC_INSTANCE(AAudioClientTracker);
37
38 AAudioClientTracker::AAudioClientTracker()
39         : Singleton<AAudioClientTracker>() {
40 }
41
42
43 std::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
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",
68           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
86 void AAudioClientTracker::unregisterClient(pid_t pid) {
87     ALOGV("AAudioClientTracker::unregisterClient(), calling pid = %d, getpid() = %d\n",
88           pid, getpid());
89     std::lock_guard<std::mutex> lock(mLock);
90     mNotificationClients.erase(pid);
91 }
92
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();
98     } else {
99         return 0; // no existing client
100     }
101 }
102
103 aaudio_result_t
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;
114     }
115     notificationClient->registerClientStream(serviceStream);
116     return result;
117 }
118
119 // Find the tracker for this process and remove it.
120 aaudio_result_t
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);
130     } else {
131         ALOGE("AAudioClientTracker::unregisterClientStream(%d, %p) missing NotificationClient\n",
132               pid, serviceStream.get());
133     }
134     return AAUDIO_OK;
135 }
136
137 AAudioClientTracker::NotificationClient::NotificationClient(pid_t pid)
138         : mProcessId(pid) {
139     //ALOGD("AAudioClientTracker::NotificationClient(%d) created %p\n", pid, this);
140 }
141
142 AAudioClientTracker::NotificationClient::~NotificationClient() {
143     //ALOGD("AAudioClientTracker::~NotificationClient() destroyed %p\n", this);
144 }
145
146 int32_t AAudioClientTracker::NotificationClient::getStreamCount() {
147     std::lock_guard<std::mutex> lock(mLock);
148     return mStreams.size();
149 }
150
151 aaudio_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
158 aaudio_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.
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;
172
173         {
174             std::lock_guard<std::mutex> lock(mLock);
175             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 }
190
191
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 */,
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 }