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
38using namespace android;
39using namespace aaudio;
40
41#define MAX_STREAMS_PER_PROCESS   8
42
43using android::AAudioService;
44
45android::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
53AAudioService::~AAudioService() {
54}
55
56status_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
76void AAudioService::registerClient(const sp<IAAudioClient>& client) {
77    pid_t pid = IPCThreadState::self()->getCallingPid();
78    AAudioClientTracker::getInstance().registerClient(pid, client);
79}
80
81aaudio_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
145bool 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
160aaudio_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
166aaudio_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
182sp<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
205aaudio_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
219aaudio_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
230aaudio_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
240aaudio_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
250aaudio_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
260aaudio_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
286aaudio_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
303aaudio_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
315aaudio_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.
328aaudio_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