1c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk/* 2c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk * Copyright (C) 2017 The Android Open Source Project 3c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk * 4c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk * Licensed under the Apache License, Version 2.0 (the "License"); 5c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk * you may not use this file except in compliance with the License. 6c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk * You may obtain a copy of the License at 7c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk * 8c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk * http://www.apache.org/licenses/LICENSE-2.0 9c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk * 10c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk * Unless required by applicable law or agreed to in writing, software 11c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk * distributed under the License is distributed on an "AS IS" BASIS, 12c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk * See the License for the specific language governing permissions and 14c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk * limitations under the License. 15c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk */ 16c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk 1771f35bb687476694882a617ba4a810a0bb56fe23Phil Burk#define LOG_TAG "AAudioService" 1871f35bb687476694882a617ba4a810a0bb56fe23Phil Burk//#define LOG_NDEBUG 0 1971f35bb687476694882a617ba4a810a0bb56fe23Phil Burk#include <utils/Log.h> 2071f35bb687476694882a617ba4a810a0bb56fe23Phil Burk 2171f35bb687476694882a617ba4a810a0bb56fe23Phil Burk#include <assert.h> 2271f35bb687476694882a617ba4a810a0bb56fe23Phil Burk#include <map> 2371f35bb687476694882a617ba4a810a0bb56fe23Phil Burk#include <mutex> 2471f35bb687476694882a617ba4a810a0bb56fe23Phil Burk#include <utils/Singleton.h> 2571f35bb687476694882a617ba4a810a0bb56fe23Phil Burk 2671f35bb687476694882a617ba4a810a0bb56fe23Phil Burk#include "AAudioEndpointManager.h" 2771f35bb687476694882a617ba4a810a0bb56fe23Phil Burk#include "AAudioServiceEndpoint.h" 28c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk#include <algorithm> 29c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk#include <mutex> 30c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk#include <vector> 31c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk 32c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk#include "core/AudioStreamBuilder.h" 33c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk#include "AAudioServiceEndpoint.h" 34c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk#include "AAudioServiceStreamShared.h" 35c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk 36c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burkusing namespace android; // TODO just import names needed 37c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burkusing namespace aaudio; // TODO just import names needed 38c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk 39c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk#define MIN_TIMEOUT_NANOS (1000 * AAUDIO_NANOS_PER_MILLISECOND) 40c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk 41c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk// Wait at least this many times longer than the operation should take. 42c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk#define MIN_TIMEOUT_OPERATIONS 4 43c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk 4471f35bb687476694882a617ba4a810a0bb56fe23Phil Burk// This is the maximum size in frames. The effective size can be tuned smaller at runtime. 4571f35bb687476694882a617ba4a810a0bb56fe23Phil Burk#define DEFAULT_BUFFER_CAPACITY (48 * 8) 4671f35bb687476694882a617ba4a810a0bb56fe23Phil Burk 47c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk// Set up an EXCLUSIVE MMAP stream that will be shared. 4887c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burkaaudio_result_t AAudioServiceEndpoint::open(int32_t deviceId) { 4987c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk mStreamInternal = getStreamInternal(); 5087c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk 51c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk AudioStreamBuilder builder; 52c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk builder.setSharingMode(AAUDIO_SHARING_MODE_EXCLUSIVE); 5371f35bb687476694882a617ba4a810a0bb56fe23Phil Burk // Don't fall back to SHARED because that would cause recursion. 5471f35bb687476694882a617ba4a810a0bb56fe23Phil Burk builder.setSharingModeMatchRequired(true); 55c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk builder.setDeviceId(deviceId); 5687c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk builder.setDirection(getDirection()); 5771f35bb687476694882a617ba4a810a0bb56fe23Phil Burk builder.setBufferCapacity(DEFAULT_BUFFER_CAPACITY); 5871f35bb687476694882a617ba4a810a0bb56fe23Phil Burk 5987c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk return getStreamInternal()->open(builder); 60c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk} 61c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk 62c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burkaaudio_result_t AAudioServiceEndpoint::close() { 6387c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk return getStreamInternal()->close(); 64c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk} 65c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk 66c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk// TODO, maybe use an interface to reduce exposure 67c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burkaaudio_result_t AAudioServiceEndpoint::registerStream(AAudioServiceStreamShared *sharedStream) { 68c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk std::lock_guard<std::mutex> lock(mLockStreams); 69c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk mRegisteredStreams.push_back(sharedStream); 70c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk return AAUDIO_OK; 71c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk} 72c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk 73c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burkaaudio_result_t AAudioServiceEndpoint::unregisterStream(AAudioServiceStreamShared *sharedStream) { 74c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk std::lock_guard<std::mutex> lock(mLockStreams); 75c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk mRegisteredStreams.erase(std::remove(mRegisteredStreams.begin(), mRegisteredStreams.end(), sharedStream), 76c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk mRegisteredStreams.end()); 77c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk return AAUDIO_OK; 78c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk} 79c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk 80c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burkaaudio_result_t AAudioServiceEndpoint::startStream(AAudioServiceStreamShared *sharedStream) { 81c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk // TODO use real-time technique to avoid mutex, eg. atomic command FIFO 82c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk std::lock_guard<std::mutex> lock(mLockStreams); 83c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk mRunningStreams.push_back(sharedStream); 84c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk if (mRunningStreams.size() == 1) { 8587c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk startSharingThread_l(); 86c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk } 87c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk return AAUDIO_OK; 88c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk} 89c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk 90c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burkaaudio_result_t AAudioServiceEndpoint::stopStream(AAudioServiceStreamShared *sharedStream) { 9187c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk int numRunningStreams = 0; 9287c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk { 9387c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk std::lock_guard<std::mutex> lock(mLockStreams); 9487c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk mRunningStreams.erase( 9587c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk std::remove(mRunningStreams.begin(), mRunningStreams.end(), sharedStream), 9687c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk mRunningStreams.end()); 9787c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk numRunningStreams = mRunningStreams.size(); 9887c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk } 9987c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk if (numRunningStreams == 0) { 10087c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk // Don't call this under a lock because the callbackLoop also uses the lock. 10187c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk stopSharingThread(); 102c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk } 103c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk return AAUDIO_OK; 104c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk} 105c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk 10687c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burkstatic void *aaudio_endpoint_thread_proc(void *context) { 10787c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk AAudioServiceEndpoint *endpoint = (AAudioServiceEndpoint *) context; 10887c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk if (endpoint != NULL) { 10987c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk return endpoint->callbackLoop(); 110c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk } else { 111c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk return NULL; 112c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk } 113c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk} 114c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk 11587c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burkaaudio_result_t AAudioServiceEndpoint::startSharingThread_l() { 116c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk // Launch the callback loop thread. 11787c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk int64_t periodNanos = getStreamInternal()->getFramesPerBurst() 118c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk * AAUDIO_NANOS_PER_SECOND 119c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk / getSampleRate(); 120c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk mCallbackEnabled.store(true); 12187c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk return getStreamInternal()->createThread(periodNanos, aaudio_endpoint_thread_proc, this); 122c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk} 123c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk 12487c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burkaaudio_result_t AAudioServiceEndpoint::stopSharingThread() { 125c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk mCallbackEnabled.store(false); 12687c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk aaudio_result_t result = getStreamInternal()->joinThread(NULL); 12787c9f646a94259d7c321c3b3d5947fa1778f5ac2Phil Burk return result; 128c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk} 129c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk 130c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burkvoid AAudioServiceEndpoint::disconnectRegisteredStreams() { 131c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk std::lock_guard<std::mutex> lock(mLockStreams); 132c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk for(AAudioServiceStreamShared *sharedStream : mRunningStreams) { 133c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk sharedStream->onStop(); 134c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk } 135c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk mRunningStreams.clear(); 136c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk for(AAudioServiceStreamShared *sharedStream : mRegisteredStreams) { 137c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk sharedStream->onDisconnect(); 138c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk } 139c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk mRegisteredStreams.clear(); 140c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk} 141