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