• 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 <utils/String16.h>
28 
29 #include "binding/AAudioServiceMessage.h"
30 #include "AAudioClientTracker.h"
31 #include "AAudioEndpointManager.h"
32 #include "AAudioService.h"
33 #include "AAudioServiceStreamMMAP.h"
34 #include "AAudioServiceStreamShared.h"
35 #include "binding/IAAudioService.h"
36 #include "ServiceUtilities.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     // if SHARED requested or if EXCLUSIVE failed
122     if (sharingMode == AAUDIO_SHARING_MODE_SHARED
123          || (serviceStream.get() == nullptr && !sharingModeMatchRequired)) {
124         serviceStream =  new AAudioServiceStreamShared(*this);
125         result = serviceStream->open(request);
126     }
127 
128     if (result != AAUDIO_OK) {
129         serviceStream.clear();
130         ALOGE("openStream(): failed, return %d = %s",
131               result, AAudio_convertResultToText(result));
132         return result;
133     } else {
134         aaudio_handle_t handle = mStreamTracker.addStreamForHandle(serviceStream.get());
135         ALOGD("openStream(): handle = 0x%08X", handle);
136         serviceStream->setHandle(handle);
137         pid_t pid = request.getProcessId();
138         AAudioClientTracker::getInstance().registerClientStream(pid, serviceStream);
139         configurationOutput.copyFrom(*serviceStream);
140         return handle;
141     }
142 }
143 
144 // If a close request is pending then close the stream
releaseStream(const sp<AAudioServiceStreamBase> & serviceStream)145 bool AAudioService::releaseStream(const sp<AAudioServiceStreamBase> &serviceStream) {
146     bool closed = false;
147     // decrementAndRemoveStreamByHandle() uses a lock so that if there are two simultaneous closes
148     // then only one will get the pointer and do the close.
149     sp<AAudioServiceStreamBase> foundStream = mStreamTracker.decrementAndRemoveStreamByHandle(
150             serviceStream->getHandle());
151     if (foundStream.get() != nullptr) {
152         foundStream->close();
153         pid_t pid = foundStream->getOwnerProcessId();
154         AAudioClientTracker::getInstance().unregisterClientStream(pid, foundStream);
155         closed = true;
156     }
157     return closed;
158 }
159 
checkForPendingClose(const sp<AAudioServiceStreamBase> & serviceStream,aaudio_result_t defaultResult)160 aaudio_result_t AAudioService::checkForPendingClose(
161         const sp<AAudioServiceStreamBase> &serviceStream,
162         aaudio_result_t defaultResult) {
163     return releaseStream(serviceStream) ? AAUDIO_ERROR_INVALID_STATE : defaultResult;
164 }
165 
closeStream(aaudio_handle_t streamHandle)166 aaudio_result_t AAudioService::closeStream(aaudio_handle_t streamHandle) {
167     // Check permission and ownership first.
168     sp<AAudioServiceStreamBase> serviceStream = convertHandleToServiceStream(streamHandle);
169     if (serviceStream.get() == nullptr) {
170         ALOGE("closeStream(0x%0x), illegal stream handle", streamHandle);
171         return AAUDIO_ERROR_INVALID_HANDLE;
172     }
173 
174     pid_t pid = serviceStream->getOwnerProcessId();
175     AAudioClientTracker::getInstance().unregisterClientStream(pid, serviceStream);
176 
177     serviceStream->markCloseNeeded();
178     (void) releaseStream(serviceStream);
179     return AAUDIO_OK;
180 }
181 
convertHandleToServiceStream(aaudio_handle_t streamHandle)182 sp<AAudioServiceStreamBase> AAudioService::convertHandleToServiceStream(
183         aaudio_handle_t streamHandle) {
184     sp<AAudioServiceStreamBase> serviceStream = mStreamTracker.getStreamByHandleAndIncrement(
185             streamHandle);
186     if (serviceStream.get() != nullptr) {
187         // Only allow owner or the aaudio service to access the stream.
188         const uid_t callingUserId = IPCThreadState::self()->getCallingUid();
189         const uid_t ownerUserId = serviceStream->getOwnerUserId();
190         bool callerOwnsIt = callingUserId == ownerUserId;
191         bool serverCalling = callingUserId == mAudioClient.clientUid;
192         bool serverOwnsIt = ownerUserId == mAudioClient.clientUid;
193         bool allowed = callerOwnsIt || serverCalling || serverOwnsIt;
194         if (!allowed) {
195             ALOGE("AAudioService: calling uid %d cannot access stream 0x%08X owned by %d",
196                   callingUserId, streamHandle, ownerUserId);
197             // We incremented the reference count so we must check if it needs to be closed.
198             checkForPendingClose(serviceStream, AAUDIO_OK);
199             serviceStream.clear();
200         }
201     }
202     return serviceStream;
203 }
204 
getStreamDescription(aaudio_handle_t streamHandle,aaudio::AudioEndpointParcelable & parcelable)205 aaudio_result_t AAudioService::getStreamDescription(
206                 aaudio_handle_t streamHandle,
207                 aaudio::AudioEndpointParcelable &parcelable) {
208     sp<AAudioServiceStreamBase> serviceStream = convertHandleToServiceStream(streamHandle);
209     if (serviceStream.get() == nullptr) {
210         ALOGE("getStreamDescription(), illegal stream handle = 0x%0x", streamHandle);
211         return AAUDIO_ERROR_INVALID_HANDLE;
212     }
213 
214     aaudio_result_t result = serviceStream->getDescription(parcelable);
215     // parcelable.dump();
216     return checkForPendingClose(serviceStream, result);
217 }
218 
startStream(aaudio_handle_t streamHandle)219 aaudio_result_t AAudioService::startStream(aaudio_handle_t streamHandle) {
220     sp<AAudioServiceStreamBase> serviceStream = convertHandleToServiceStream(streamHandle);
221     if (serviceStream.get() == nullptr) {
222         ALOGE("startStream(), illegal stream handle = 0x%0x", streamHandle);
223         return AAUDIO_ERROR_INVALID_HANDLE;
224     }
225 
226     aaudio_result_t result = serviceStream->start();
227     return checkForPendingClose(serviceStream, result);
228 }
229 
pauseStream(aaudio_handle_t streamHandle)230 aaudio_result_t AAudioService::pauseStream(aaudio_handle_t streamHandle) {
231     sp<AAudioServiceStreamBase> serviceStream = convertHandleToServiceStream(streamHandle);
232     if (serviceStream.get() == nullptr) {
233         ALOGE("pauseStream(), illegal stream handle = 0x%0x", streamHandle);
234         return AAUDIO_ERROR_INVALID_HANDLE;
235     }
236     aaudio_result_t result = serviceStream->pause();
237     return checkForPendingClose(serviceStream, result);
238 }
239 
stopStream(aaudio_handle_t streamHandle)240 aaudio_result_t AAudioService::stopStream(aaudio_handle_t streamHandle) {
241     sp<AAudioServiceStreamBase> serviceStream = convertHandleToServiceStream(streamHandle);
242     if (serviceStream.get() == nullptr) {
243         ALOGE("stopStream(), illegal stream handle = 0x%0x", streamHandle);
244         return AAUDIO_ERROR_INVALID_HANDLE;
245     }
246     aaudio_result_t result = serviceStream->stop();
247     return checkForPendingClose(serviceStream, result);
248 }
249 
flushStream(aaudio_handle_t streamHandle)250 aaudio_result_t AAudioService::flushStream(aaudio_handle_t streamHandle) {
251     sp<AAudioServiceStreamBase> serviceStream = convertHandleToServiceStream(streamHandle);
252     if (serviceStream.get() == nullptr) {
253         ALOGE("flushStream(), illegal stream handle = 0x%0x", streamHandle);
254         return AAUDIO_ERROR_INVALID_HANDLE;
255     }
256     aaudio_result_t result = serviceStream->flush();
257     return checkForPendingClose(serviceStream, result);
258 }
259 
registerAudioThread(aaudio_handle_t streamHandle,pid_t clientThreadId,int64_t periodNanoseconds)260 aaudio_result_t AAudioService::registerAudioThread(aaudio_handle_t streamHandle,
261                                                    pid_t clientThreadId,
262                                                    int64_t periodNanoseconds) {
263     aaudio_result_t result = AAUDIO_OK;
264     sp<AAudioServiceStreamBase> serviceStream = convertHandleToServiceStream(streamHandle);
265     if (serviceStream.get() == nullptr) {
266         ALOGE("registerAudioThread(), illegal stream handle = 0x%0x", streamHandle);
267         return AAUDIO_ERROR_INVALID_HANDLE;
268     }
269     if (serviceStream->getRegisteredThread() != AAudioServiceStreamBase::ILLEGAL_THREAD_ID) {
270         ALOGE("AAudioService::registerAudioThread(), thread already registered");
271         result = AAUDIO_ERROR_INVALID_STATE;
272     } else {
273         const pid_t ownerPid = IPCThreadState::self()->getCallingPid(); // TODO review
274         serviceStream->setRegisteredThread(clientThreadId);
275         int err = android::requestPriority(ownerPid, clientThreadId,
276                                            DEFAULT_AUDIO_PRIORITY, true /* isForApp */);
277         if (err != 0) {
278             ALOGE("AAudioService::registerAudioThread(%d) failed, errno = %d, priority = %d",
279                   clientThreadId, errno, DEFAULT_AUDIO_PRIORITY);
280             result = AAUDIO_ERROR_INTERNAL;
281         }
282     }
283     return checkForPendingClose(serviceStream, result);
284 }
285 
unregisterAudioThread(aaudio_handle_t streamHandle,pid_t clientThreadId)286 aaudio_result_t AAudioService::unregisterAudioThread(aaudio_handle_t streamHandle,
287                                                      pid_t clientThreadId) {
288     aaudio_result_t result = AAUDIO_OK;
289     sp<AAudioServiceStreamBase> serviceStream = convertHandleToServiceStream(streamHandle);
290     if (serviceStream.get() == nullptr) {
291         ALOGE("%s(), illegal stream handle = 0x%0x", __func__, streamHandle);
292         return AAUDIO_ERROR_INVALID_HANDLE;
293     }
294     if (serviceStream->getRegisteredThread() != clientThreadId) {
295         ALOGE("%s(), wrong thread", __func__);
296         result = AAUDIO_ERROR_ILLEGAL_ARGUMENT;
297     } else {
298         serviceStream->setRegisteredThread(0);
299     }
300     return checkForPendingClose(serviceStream, result);
301 }
302 
startClient(aaudio_handle_t streamHandle,const android::AudioClient & client,audio_port_handle_t * clientHandle)303 aaudio_result_t AAudioService::startClient(aaudio_handle_t streamHandle,
304                                   const android::AudioClient& client,
305                                   audio_port_handle_t *clientHandle) {
306     sp<AAudioServiceStreamBase> serviceStream = convertHandleToServiceStream(streamHandle);
307     if (serviceStream.get() == nullptr) {
308         ALOGE("%s(), illegal stream handle = 0x%0x", __func__, streamHandle);
309         return AAUDIO_ERROR_INVALID_HANDLE;
310     }
311     aaudio_result_t result = serviceStream->startClient(client, clientHandle);
312     return checkForPendingClose(serviceStream, result);
313 }
314 
stopClient(aaudio_handle_t streamHandle,audio_port_handle_t portHandle)315 aaudio_result_t AAudioService::stopClient(aaudio_handle_t streamHandle,
316                                           audio_port_handle_t portHandle) {
317     sp<AAudioServiceStreamBase> serviceStream = convertHandleToServiceStream(streamHandle);
318     if (serviceStream.get() == nullptr) {
319         ALOGE("%s(), illegal stream handle = 0x%0x", __func__, streamHandle);
320         return AAUDIO_ERROR_INVALID_HANDLE;
321     }
322     aaudio_result_t result = serviceStream->stopClient(portHandle);
323     return checkForPendingClose(serviceStream, result);
324 }
325 
326 // This is only called internally when AudioFlinger wants to tear down a stream.
327 // So we do not have to check permissions.
disconnectStreamByPortHandle(audio_port_handle_t portHandle)328 aaudio_result_t AAudioService::disconnectStreamByPortHandle(audio_port_handle_t portHandle) {
329     ALOGD("%s(%d) called", __func__, portHandle);
330     sp<AAudioServiceStreamBase> serviceStream =
331             mStreamTracker.findStreamByPortHandleAndIncrement(portHandle);
332     if (serviceStream.get() == nullptr) {
333         ALOGE("%s(), could not find stream with portHandle = %d", __func__, portHandle);
334         return AAUDIO_ERROR_INVALID_HANDLE;
335     }
336     aaudio_result_t result = serviceStream->stop();
337     serviceStream->disconnect();
338     return checkForPendingClose(serviceStream, result);
339 }
340