15ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk/*
25ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk * Copyright (C) 2016 The Android Open Source Project
35ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk *
45ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk * Licensed under the Apache License, Version 2.0 (the "License");
55ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk * you may not use this file except in compliance with the License.
65ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk * You may obtain a copy of the License at
75ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk *
85ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk *      http://www.apache.org/licenses/LICENSE-2.0
95ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk *
105ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk * Unless required by applicable law or agreed to in writing, software
115ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk * distributed under the License is distributed on an "AS IS" BASIS,
125ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
135ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk * See the License for the specific language governing permissions and
145ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk * limitations under the License.
155ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk */
165ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk
175ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk#define LOG_TAG "AAudioService"
185ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk//#define LOG_NDEBUG 0
195ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk#include <utils/Log.h>
205ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk
21c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk//#include <time.h>
22c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk//#include <pthread.h>
235ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk
24a4eb0d86a29be2763be5fac51727858d5095794bPhil Burk#include <aaudio/AAudio.h>
25c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk#include <mediautils/SchedulingPolicyService.h>
26c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk#include <utils/String16.h>
275ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk
28c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk#include "binding/AAudioServiceMessage.h"
295ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk#include "AAudioService.h"
30c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk#include "AAudioServiceStreamMMAP.h"
31c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk#include "AAudioServiceStreamShared.h"
32c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk#include "AAudioServiceStreamMMAP.h"
33c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk#include "binding/IAAudioService.h"
34c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk#include "utility/HandleTracker.h"
355ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk
365ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkusing namespace android;
375ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkusing namespace aaudio;
385ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk
395ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burktypedef enum
405ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk{
41c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk    AAUDIO_HANDLE_TYPE_STREAM
425ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk} aaudio_service_handle_type_t;
43c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burkstatic_assert(AAUDIO_HANDLE_TYPE_STREAM < HANDLE_TRACKER_MAX_TYPES, "Too many handle types.");
445ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk
455ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkandroid::AAudioService::AAudioService()
465ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk    : BnAAudioService() {
475ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk}
485ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk
495ed503c7a66c90f93759c90237a9b432dbd93f9fPhil BurkAAudioService::~AAudioService() {
505ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk}
515ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk
52c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burkaaudio_handle_t AAudioService::openStream(const aaudio::AAudioStreamRequest &request,
53c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk                                          aaudio::AAudioStreamConfiguration &configurationOutput) {
54c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk    aaudio_result_t result = AAUDIO_OK;
55c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk    AAudioServiceStreamBase *serviceStream = nullptr;
56c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk    const AAudioStreamConfiguration &configurationInput = request.getConstantConfiguration();
5771f35bb687476694882a617ba4a810a0bb56fe23Phil Burk    bool sharingModeMatchRequired = request.isSharingModeMatchRequired();
58c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk    aaudio_sharing_mode_t sharingMode = configurationInput.getSharingMode();
59c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk
60c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk    if (sharingMode != AAUDIO_SHARING_MODE_EXCLUSIVE && sharingMode != AAUDIO_SHARING_MODE_SHARED) {
61c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk        ALOGE("AAudioService::openStream(): unrecognized sharing mode = %d", sharingMode);
62c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk        return AAUDIO_ERROR_ILLEGAL_ARGUMENT;
63c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk    }
64c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk
65c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk    if (sharingMode == AAUDIO_SHARING_MODE_EXCLUSIVE) {
66c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk        serviceStream = new AAudioServiceStreamMMAP();
67c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk        result = serviceStream->open(request, configurationOutput);
68c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk        if (result != AAUDIO_OK) {
69c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk            // fall back to using a shared stream
70c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk            ALOGD("AAudioService::openStream(), EXCLUSIVE mode failed");
71c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk            delete serviceStream;
72c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk            serviceStream = nullptr;
73c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk        } else {
74c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk            configurationOutput.setSharingMode(AAUDIO_SHARING_MODE_EXCLUSIVE);
75c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk        }
76c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk    }
77c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk
78c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk    // if SHARED requested or if EXCLUSIVE failed
7971f35bb687476694882a617ba4a810a0bb56fe23Phil Burk    if (sharingMode == AAUDIO_SHARING_MODE_SHARED
8071f35bb687476694882a617ba4a810a0bb56fe23Phil Burk         || (serviceStream == nullptr && !sharingModeMatchRequired)) {
81c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk        serviceStream =  new AAudioServiceStreamShared(*this);
82c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk        result = serviceStream->open(request, configurationOutput);
83c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk        configurationOutput.setSharingMode(AAUDIO_SHARING_MODE_SHARED);
84c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk    }
85c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk
86c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk    if (result != AAUDIO_OK) {
87c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk        delete serviceStream;
88c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk        ALOGE("AAudioService::openStream(): failed, return %d", result);
895ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk        return result;
905ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk    } else {
913316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk        aaudio_handle_t handle = mHandleTracker.put(AAUDIO_HANDLE_TYPE_STREAM, serviceStream);
92cf5f6d2825d9a8430a291042ca9c6f68e5b666d0Phil Burk        ALOGV("AAudioService::openStream(): handle = 0x%08X", handle);
935ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk        if (handle < 0) {
94c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk            ALOGE("AAudioService::openStream(): handle table full");
955ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk            delete serviceStream;
965ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk        }
975ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk        return handle;
985ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk    }
995ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk}
1005ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk
1015ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkaaudio_result_t AAudioService::closeStream(aaudio_handle_t streamHandle) {
1025ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk    AAudioServiceStreamBase *serviceStream = (AAudioServiceStreamBase *)
1035ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk            mHandleTracker.remove(AAUDIO_HANDLE_TYPE_STREAM,
1045ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk                                  streamHandle);
105cf5f6d2825d9a8430a291042ca9c6f68e5b666d0Phil Burk    ALOGV("AAudioService.closeStream(0x%08X)", streamHandle);
1065ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk    if (serviceStream != nullptr) {
107c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk        serviceStream->close();
1085ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk        delete serviceStream;
1095ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk        return AAUDIO_OK;
1105ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk    }
1115ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk    return AAUDIO_ERROR_INVALID_HANDLE;
1125ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk}
1135ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk
1145ed503c7a66c90f93759c90237a9b432dbd93f9fPhil BurkAAudioServiceStreamBase *AAudioService::convertHandleToServiceStream(
1155ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk        aaudio_handle_t streamHandle) const {
1165ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk    return (AAudioServiceStreamBase *) mHandleTracker.get(AAUDIO_HANDLE_TYPE_STREAM,
1175ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk                              (aaudio_handle_t)streamHandle);
1185ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk}
1195ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk
1205ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkaaudio_result_t AAudioService::getStreamDescription(
1215ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk                aaudio_handle_t streamHandle,
1225ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk                aaudio::AudioEndpointParcelable &parcelable) {
1235ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk    AAudioServiceStreamBase *serviceStream = convertHandleToServiceStream(streamHandle);
1245ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk    if (serviceStream == nullptr) {
125c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk        ALOGE("AAudioService::getStreamDescription(), illegal stream handle = 0x%0x", streamHandle);
1265ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk        return AAUDIO_ERROR_INVALID_HANDLE;
1275ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk    }
128c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk    aaudio_result_t result = serviceStream->getDescription(parcelable);
129c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk    // parcelable.dump();
130c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk    return result;
1315ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk}
1325ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk
1335ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkaaudio_result_t AAudioService::startStream(aaudio_handle_t streamHandle) {
1345ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk    AAudioServiceStreamBase *serviceStream = convertHandleToServiceStream(streamHandle);
1355ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk    if (serviceStream == nullptr) {
136c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk        ALOGE("AAudioService::startStream(), illegal stream handle = 0x%0x", streamHandle);
1375ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk        return AAUDIO_ERROR_INVALID_HANDLE;
1385ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk    }
1395ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk    aaudio_result_t result = serviceStream->start();
1405ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk    return result;
1415ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk}
1425ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk
1435ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkaaudio_result_t AAudioService::pauseStream(aaudio_handle_t streamHandle) {
1445ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk    AAudioServiceStreamBase *serviceStream = convertHandleToServiceStream(streamHandle);
1455ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk    if (serviceStream == nullptr) {
146c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk        ALOGE("AAudioService::pauseStream(), illegal stream handle = 0x%0x", streamHandle);
1475ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk        return AAUDIO_ERROR_INVALID_HANDLE;
1485ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk    }
1495ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk    aaudio_result_t result = serviceStream->pause();
1505ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk    return result;
1515ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk}
1525ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk
15371f35bb687476694882a617ba4a810a0bb56fe23Phil Burkaaudio_result_t AAudioService::stopStream(aaudio_handle_t streamHandle) {
15471f35bb687476694882a617ba4a810a0bb56fe23Phil Burk    AAudioServiceStreamBase *serviceStream = convertHandleToServiceStream(streamHandle);
15571f35bb687476694882a617ba4a810a0bb56fe23Phil Burk    if (serviceStream == nullptr) {
15671f35bb687476694882a617ba4a810a0bb56fe23Phil Burk        ALOGE("AAudioService::pauseStream(), illegal stream handle = 0x%0x", streamHandle);
15771f35bb687476694882a617ba4a810a0bb56fe23Phil Burk        return AAUDIO_ERROR_INVALID_HANDLE;
15871f35bb687476694882a617ba4a810a0bb56fe23Phil Burk    }
15971f35bb687476694882a617ba4a810a0bb56fe23Phil Burk    aaudio_result_t result = serviceStream->stop();
16071f35bb687476694882a617ba4a810a0bb56fe23Phil Burk    return result;
16171f35bb687476694882a617ba4a810a0bb56fe23Phil Burk}
16271f35bb687476694882a617ba4a810a0bb56fe23Phil Burk
1635ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkaaudio_result_t AAudioService::flushStream(aaudio_handle_t streamHandle) {
1645ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk    AAudioServiceStreamBase *serviceStream = convertHandleToServiceStream(streamHandle);
1655ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk    if (serviceStream == nullptr) {
166c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk        ALOGE("AAudioService::flushStream(), illegal stream handle = 0x%0x", streamHandle);
1675ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk        return AAUDIO_ERROR_INVALID_HANDLE;
1685ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk    }
1695ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk    return serviceStream->flush();
1705ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk}
1715ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk
1725ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkaaudio_result_t AAudioService::registerAudioThread(aaudio_handle_t streamHandle,
173c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk                                                         pid_t clientProcessId,
1745ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk                                                         pid_t clientThreadId,
1753316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk                                                         int64_t periodNanoseconds) {
1765ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk    AAudioServiceStreamBase *serviceStream = convertHandleToServiceStream(streamHandle);
1775ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk    if (serviceStream == nullptr) {
178c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk        ALOGE("AAudioService::registerAudioThread(), illegal stream handle = 0x%0x", streamHandle);
1795ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk        return AAUDIO_ERROR_INVALID_HANDLE;
1805ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk    }
1815ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk    if (serviceStream->getRegisteredThread() != AAudioServiceStreamBase::ILLEGAL_THREAD_ID) {
1825ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk        ALOGE("AAudioService::registerAudioThread(), thread already registered");
183c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk        return AAUDIO_ERROR_INVALID_STATE;
1845ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk    }
1855ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk    serviceStream->setRegisteredThread(clientThreadId);
186c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk    int err = android::requestPriority(clientProcessId, clientThreadId,
187c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk                                       DEFAULT_AUDIO_PRIORITY, true /* isForApp */);
1885ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk    if (err != 0){
189c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk        ALOGE("AAudioService::registerAudioThread() failed, errno = %d, priority = %d",
190c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk              errno, DEFAULT_AUDIO_PRIORITY);
1915ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk        return AAUDIO_ERROR_INTERNAL;
1925ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk    } else {
1935ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk        return AAUDIO_OK;
1945ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk    }
1955ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk}
1965ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk
1975ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkaaudio_result_t AAudioService::unregisterAudioThread(aaudio_handle_t streamHandle,
198c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk                                                     pid_t clientProcessId,
199c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk                                                     pid_t clientThreadId) {
2005ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk    AAudioServiceStreamBase *serviceStream = convertHandleToServiceStream(streamHandle);
2015ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk    if (serviceStream == nullptr) {
202c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk        ALOGE("AAudioService::unregisterAudioThread(), illegal stream handle = 0x%0x",
203c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk              streamHandle);
2045ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk        return AAUDIO_ERROR_INVALID_HANDLE;
2055ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk    }
2065ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk    if (serviceStream->getRegisteredThread() != clientThreadId) {
2075ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk        ALOGE("AAudioService::unregisterAudioThread(), wrong thread");
2085ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk        return AAUDIO_ERROR_ILLEGAL_ARGUMENT;
2095ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk    }
2105ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk    serviceStream->setRegisteredThread(0);
2115ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk    return AAUDIO_OK;
2125ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk}
213