• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2016 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 #define LOG_TAG "AAudioService"
18 //#define LOG_NDEBUG 0
19 #include <utils/Log.h>
20 
21 #include <iomanip>
22 #include <iostream>
23 #include <sstream>
24 
25 #include <aaudio/AAudio.h>
26 #include <mediautils/SchedulingPolicyService.h>
27 #include <mediautils/ServiceUtilities.h>
28 #include <utils/String16.h>
29 
30 #include "binding/AAudioServiceMessage.h"
31 #include "AAudioClientTracker.h"
32 #include "AAudioEndpointManager.h"
33 #include "AAudioService.h"
34 #include "AAudioServiceStreamMMAP.h"
35 #include "AAudioServiceStreamShared.h"
36 #include "binding/IAAudioService.h"
37 
38 using namespace android;
39 using namespace aaudio;
40 
41 #define MAX_STREAMS_PER_PROCESS   8
42 
43 using android::AAudioService;
44 
AAudioService()45 android::AAudioService::AAudioService()
46     : BnAAudioService() {
47     mAudioClient.clientUid = getuid();   // TODO consider using geteuid()
48     mAudioClient.clientPid = getpid();
49     mAudioClient.packageName = String16("");
50     AAudioClientTracker::getInstance().setAAudioService(this);
51 }
52 
~AAudioService()53 AAudioService::~AAudioService() {
54 }
55 
dump(int fd,const Vector<String16> & args)56 status_t AAudioService::dump(int fd, const Vector<String16>& args) {
57     std::string result;
58 
59     if (!dumpAllowed()) {
60         std::stringstream ss;
61         ss << "Permission Denial: can't dump AAudioService from pid="
62                 << IPCThreadState::self()->getCallingPid() << ", uid="
63                 << IPCThreadState::self()->getCallingUid() << "\n";
64         result = ss.str();
65         ALOGW("%s", result.c_str());
66     } else {
67         result = "------------ AAudio Service ------------\n"
68                  + mStreamTracker.dump()
69                  + AAudioClientTracker::getInstance().dump()
70                  + AAudioEndpointManager::getInstance().dump();
71     }
72     (void)write(fd, result.c_str(), result.size());
73     return NO_ERROR;
74 }
75 
registerClient(const sp<IAAudioClient> & client)76 void AAudioService::registerClient(const sp<IAAudioClient>& client) {
77     pid_t pid = IPCThreadState::self()->getCallingPid();
78     AAudioClientTracker::getInstance().registerClient(pid, client);
79 }
80 
openStream(const aaudio::AAudioStreamRequest & request,aaudio::AAudioStreamConfiguration & configurationOutput)81 aaudio_handle_t AAudioService::openStream(const aaudio::AAudioStreamRequest &request,
82                                           aaudio::AAudioStreamConfiguration &configurationOutput) {
83     aaudio_result_t result = AAUDIO_OK;
84     sp<AAudioServiceStreamBase> serviceStream;
85     const AAudioStreamConfiguration &configurationInput = request.getConstantConfiguration();
86     bool sharingModeMatchRequired = request.isSharingModeMatchRequired();
87     aaudio_sharing_mode_t sharingMode = configurationInput.getSharingMode();
88 
89     // Enforce limit on client processes.
90     pid_t pid = request.getProcessId();
91     if (pid != mAudioClient.clientPid) {
92         int32_t count = AAudioClientTracker::getInstance().getStreamCount(pid);
93         if (count >= MAX_STREAMS_PER_PROCESS) {
94             ALOGE("openStream(): exceeded max streams per process %d >= %d",
95                   count,  MAX_STREAMS_PER_PROCESS);
96             return AAUDIO_ERROR_UNAVAILABLE;
97         }
98     }
99 
100     if (sharingMode != AAUDIO_SHARING_MODE_EXCLUSIVE && sharingMode != AAUDIO_SHARING_MODE_SHARED) {
101         ALOGE("openStream(): unrecognized sharing mode = %d", sharingMode);
102         return AAUDIO_ERROR_ILLEGAL_ARGUMENT;
103     }
104 
105     if (sharingMode == AAUDIO_SHARING_MODE_EXCLUSIVE) {
106         // only trust audioserver for in service indication
107         bool inService = false;
108         if (mAudioClient.clientPid == IPCThreadState::self()->getCallingPid() &&
109                 mAudioClient.clientUid == IPCThreadState::self()->getCallingUid()) {
110             inService = request.isInService();
111         }
112         serviceStream = new AAudioServiceStreamMMAP(*this, inService);
113         result = serviceStream->open(request);
114         if (result != AAUDIO_OK) {
115             // Clear it so we can possibly fall back to using a shared stream.
116             ALOGW("openStream(), could not open in EXCLUSIVE mode");
117             serviceStream.clear();
118         }
119     }
120 
121     // Try SHARED if SHARED requested or if EXCLUSIVE failed.
122     if (sharingMode == AAUDIO_SHARING_MODE_SHARED) {
123         serviceStream =  new AAudioServiceStreamShared(*this);
124         result = serviceStream->open(request);
125     } else if (serviceStream.get() == nullptr && !sharingModeMatchRequired) {
126         aaudio::AAudioStreamRequest modifiedRequest = request;
127         // Overwrite the original EXCLUSIVE mode with SHARED.
128         modifiedRequest.getConfiguration().setSharingMode(AAUDIO_SHARING_MODE_SHARED);
129         serviceStream =  new AAudioServiceStreamShared(*this);
130         result = serviceStream->open(modifiedRequest);
131     }
132 
133     if (result != AAUDIO_OK) {
134         serviceStream.clear();
135         return result;
136     } else {
137         aaudio_handle_t handle = mStreamTracker.addStreamForHandle(serviceStream.get());
138         ALOGV("openStream(): handle = 0x%08X", handle);
139         serviceStream->setHandle(handle);
140         pid_t pid = request.getProcessId();
141         AAudioClientTracker::getInstance().registerClientStream(pid, serviceStream);
142         configurationOutput.copyFrom(*serviceStream);
143         return handle;
144     }
145 }
146 
147 // If a close request is pending then close the stream
releaseStream(const sp<AAudioServiceStreamBase> & serviceStream)148 bool AAudioService::releaseStream(const sp<AAudioServiceStreamBase> &serviceStream) {
149     bool closed = false;
150     // decrementAndRemoveStreamByHandle() uses a lock so that if there are two simultaneous closes
151     // then only one will get the pointer and do the close.
152     sp<AAudioServiceStreamBase> foundStream = mStreamTracker.decrementAndRemoveStreamByHandle(
153             serviceStream->getHandle());
154     if (foundStream.get() != nullptr) {
155         foundStream->close();
156         pid_t pid = foundStream->getOwnerProcessId();
157         AAudioClientTracker::getInstance().unregisterClientStream(pid, foundStream);
158         closed = true;
159     }
160     return closed;
161 }
162 
checkForPendingClose(const sp<AAudioServiceStreamBase> & serviceStream,aaudio_result_t defaultResult)163 aaudio_result_t AAudioService::checkForPendingClose(
164         const sp<AAudioServiceStreamBase> &serviceStream,
165         aaudio_result_t defaultResult) {
166     return releaseStream(serviceStream) ? AAUDIO_ERROR_INVALID_STATE : defaultResult;
167 }
168 
closeStream(aaudio_handle_t streamHandle)169 aaudio_result_t AAudioService::closeStream(aaudio_handle_t streamHandle) {
170     // Check permission and ownership first.
171     sp<AAudioServiceStreamBase> serviceStream = convertHandleToServiceStream(streamHandle);
172     if (serviceStream.get() == nullptr) {
173         ALOGE("closeStream(0x%0x), illegal stream handle", streamHandle);
174         return AAUDIO_ERROR_INVALID_HANDLE;
175     }
176 
177     pid_t pid = serviceStream->getOwnerProcessId();
178     AAudioClientTracker::getInstance().unregisterClientStream(pid, serviceStream);
179 
180     serviceStream->markCloseNeeded();
181     (void) releaseStream(serviceStream);
182     return AAUDIO_OK;
183 }
184 
convertHandleToServiceStream(aaudio_handle_t streamHandle)185 sp<AAudioServiceStreamBase> AAudioService::convertHandleToServiceStream(
186         aaudio_handle_t streamHandle) {
187     sp<AAudioServiceStreamBase> serviceStream = mStreamTracker.getStreamByHandleAndIncrement(
188             streamHandle);
189     if (serviceStream.get() != nullptr) {
190         // Only allow owner or the aaudio service to access the stream.
191         const uid_t callingUserId = IPCThreadState::self()->getCallingUid();
192         const uid_t ownerUserId = serviceStream->getOwnerUserId();
193         bool callerOwnsIt = callingUserId == ownerUserId;
194         bool serverCalling = callingUserId == mAudioClient.clientUid;
195         bool serverOwnsIt = ownerUserId == mAudioClient.clientUid;
196         bool allowed = callerOwnsIt || serverCalling || serverOwnsIt;
197         if (!allowed) {
198             ALOGE("AAudioService: calling uid %d cannot access stream 0x%08X owned by %d",
199                   callingUserId, streamHandle, ownerUserId);
200             // We incremented the reference count so we must check if it needs to be closed.
201             checkForPendingClose(serviceStream, AAUDIO_OK);
202             serviceStream.clear();
203         }
204     }
205     return serviceStream;
206 }
207 
getStreamDescription(aaudio_handle_t streamHandle,aaudio::AudioEndpointParcelable & parcelable)208 aaudio_result_t AAudioService::getStreamDescription(
209                 aaudio_handle_t streamHandle,
210                 aaudio::AudioEndpointParcelable &parcelable) {
211     sp<AAudioServiceStreamBase> serviceStream = convertHandleToServiceStream(streamHandle);
212     if (serviceStream.get() == nullptr) {
213         ALOGE("getStreamDescription(), illegal stream handle = 0x%0x", streamHandle);
214         return AAUDIO_ERROR_INVALID_HANDLE;
215     }
216 
217     aaudio_result_t result = serviceStream->getDescription(parcelable);
218     // parcelable.dump();
219     return checkForPendingClose(serviceStream, result);
220 }
221 
startStream(aaudio_handle_t streamHandle)222 aaudio_result_t AAudioService::startStream(aaudio_handle_t streamHandle) {
223     sp<AAudioServiceStreamBase> serviceStream = convertHandleToServiceStream(streamHandle);
224     if (serviceStream.get() == nullptr) {
225         ALOGE("startStream(), illegal stream handle = 0x%0x", streamHandle);
226         return AAUDIO_ERROR_INVALID_HANDLE;
227     }
228 
229     aaudio_result_t result = serviceStream->start();
230     return checkForPendingClose(serviceStream, result);
231 }
232 
pauseStream(aaudio_handle_t streamHandle)233 aaudio_result_t AAudioService::pauseStream(aaudio_handle_t streamHandle) {
234     sp<AAudioServiceStreamBase> serviceStream = convertHandleToServiceStream(streamHandle);
235     if (serviceStream.get() == nullptr) {
236         ALOGE("pauseStream(), illegal stream handle = 0x%0x", streamHandle);
237         return AAUDIO_ERROR_INVALID_HANDLE;
238     }
239     aaudio_result_t result = serviceStream->pause();
240     return checkForPendingClose(serviceStream, result);
241 }
242 
stopStream(aaudio_handle_t streamHandle)243 aaudio_result_t AAudioService::stopStream(aaudio_handle_t streamHandle) {
244     sp<AAudioServiceStreamBase> serviceStream = convertHandleToServiceStream(streamHandle);
245     if (serviceStream.get() == nullptr) {
246         ALOGE("stopStream(), illegal stream handle = 0x%0x", streamHandle);
247         return AAUDIO_ERROR_INVALID_HANDLE;
248     }
249     aaudio_result_t result = serviceStream->stop();
250     return checkForPendingClose(serviceStream, result);
251 }
252 
flushStream(aaudio_handle_t streamHandle)253 aaudio_result_t AAudioService::flushStream(aaudio_handle_t streamHandle) {
254     sp<AAudioServiceStreamBase> serviceStream = convertHandleToServiceStream(streamHandle);
255     if (serviceStream.get() == nullptr) {
256         ALOGE("flushStream(), illegal stream handle = 0x%0x", streamHandle);
257         return AAUDIO_ERROR_INVALID_HANDLE;
258     }
259     aaudio_result_t result = serviceStream->flush();
260     return checkForPendingClose(serviceStream, result);
261 }
262 
registerAudioThread(aaudio_handle_t streamHandle,pid_t clientThreadId,int64_t periodNanoseconds)263 aaudio_result_t AAudioService::registerAudioThread(aaudio_handle_t streamHandle,
264                                                    pid_t clientThreadId,
265                                                    int64_t periodNanoseconds) {
266     aaudio_result_t result = AAUDIO_OK;
267     sp<AAudioServiceStreamBase> serviceStream = convertHandleToServiceStream(streamHandle);
268     if (serviceStream.get() == nullptr) {
269         ALOGE("registerAudioThread(), illegal stream handle = 0x%0x", streamHandle);
270         return AAUDIO_ERROR_INVALID_HANDLE;
271     }
272     if (serviceStream->getRegisteredThread() != AAudioServiceStreamBase::ILLEGAL_THREAD_ID) {
273         ALOGE("AAudioService::registerAudioThread(), thread already registered");
274         result = AAUDIO_ERROR_INVALID_STATE;
275     } else {
276         const pid_t ownerPid = IPCThreadState::self()->getCallingPid(); // TODO review
277         serviceStream->setRegisteredThread(clientThreadId);
278         int err = android::requestPriority(ownerPid, clientThreadId,
279                                            DEFAULT_AUDIO_PRIORITY, true /* isForApp */);
280         if (err != 0) {
281             ALOGE("AAudioService::registerAudioThread(%d) failed, errno = %d, priority = %d",
282                   clientThreadId, errno, DEFAULT_AUDIO_PRIORITY);
283             result = AAUDIO_ERROR_INTERNAL;
284         }
285     }
286     return checkForPendingClose(serviceStream, result);
287 }
288 
unregisterAudioThread(aaudio_handle_t streamHandle,pid_t clientThreadId)289 aaudio_result_t AAudioService::unregisterAudioThread(aaudio_handle_t streamHandle,
290                                                      pid_t clientThreadId) {
291     aaudio_result_t result = AAUDIO_OK;
292     sp<AAudioServiceStreamBase> serviceStream = convertHandleToServiceStream(streamHandle);
293     if (serviceStream.get() == nullptr) {
294         ALOGE("%s(), illegal stream handle = 0x%0x", __func__, streamHandle);
295         return AAUDIO_ERROR_INVALID_HANDLE;
296     }
297     if (serviceStream->getRegisteredThread() != clientThreadId) {
298         ALOGE("%s(), wrong thread", __func__);
299         result = AAUDIO_ERROR_ILLEGAL_ARGUMENT;
300     } else {
301         serviceStream->setRegisteredThread(0);
302     }
303     return checkForPendingClose(serviceStream, result);
304 }
305 
startClient(aaudio_handle_t streamHandle,const android::AudioClient & client,audio_port_handle_t * clientHandle)306 aaudio_result_t AAudioService::startClient(aaudio_handle_t streamHandle,
307                                   const android::AudioClient& client,
308                                   audio_port_handle_t *clientHandle) {
309     sp<AAudioServiceStreamBase> serviceStream = convertHandleToServiceStream(streamHandle);
310     if (serviceStream.get() == nullptr) {
311         ALOGE("%s(), illegal stream handle = 0x%0x", __func__, streamHandle);
312         return AAUDIO_ERROR_INVALID_HANDLE;
313     }
314     aaudio_result_t result = serviceStream->startClient(client, clientHandle);
315     return checkForPendingClose(serviceStream, result);
316 }
317 
stopClient(aaudio_handle_t streamHandle,audio_port_handle_t portHandle)318 aaudio_result_t AAudioService::stopClient(aaudio_handle_t streamHandle,
319                                           audio_port_handle_t portHandle) {
320     sp<AAudioServiceStreamBase> serviceStream = convertHandleToServiceStream(streamHandle);
321     if (serviceStream.get() == nullptr) {
322         ALOGE("%s(), illegal stream handle = 0x%0x", __func__, streamHandle);
323         return AAUDIO_ERROR_INVALID_HANDLE;
324     }
325     aaudio_result_t result = serviceStream->stopClient(portHandle);
326     return checkForPendingClose(serviceStream, result);
327 }
328 
329 // This is only called internally when AudioFlinger wants to tear down a stream.
330 // So we do not have to check permissions.
disconnectStreamByPortHandle(audio_port_handle_t portHandle)331 aaudio_result_t AAudioService::disconnectStreamByPortHandle(audio_port_handle_t portHandle) {
332     ALOGD("%s(%d) called", __func__, portHandle);
333     sp<AAudioServiceStreamBase> serviceStream =
334             mStreamTracker.findStreamByPortHandleAndIncrement(portHandle);
335     if (serviceStream.get() == nullptr) {
336         ALOGE("%s(), could not find stream with portHandle = %d", __func__, portHandle);
337         return AAUDIO_ERROR_INVALID_HANDLE;
338     }
339     aaudio_result_t result = serviceStream->stop();
340     serviceStream->disconnect();
341     return checkForPendingClose(serviceStream, result);
342 }
343