blob: 494b18ecb5374579bd89a43b3ee4bcd316789e90 [file] [log] [blame]
Phil Burkc0c70e32017-02-09 13:18:38 -08001/*
2 * Copyright (C) 2017 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 <mutex>
22
23#include <aaudio/AAudio.h>
24
25#include "binding/IAAudioService.h"
26
27#include "binding/AAudioServiceMessage.h"
28#include "AAudioServiceStreamBase.h"
29#include "AAudioServiceStreamShared.h"
30#include "AAudioEndpointManager.h"
31#include "AAudioService.h"
32#include "AAudioServiceEndpoint.h"
33
34using namespace android;
35using namespace aaudio;
36
37#define MIN_BURSTS_PER_BUFFER 2
38#define MAX_BURSTS_PER_BUFFER 32
39
40AAudioServiceStreamShared::AAudioServiceStreamShared(AAudioService &audioService)
41 : mAudioService(audioService)
42 {
43}
44
45AAudioServiceStreamShared::~AAudioServiceStreamShared() {
46 close();
47}
48
49aaudio_result_t AAudioServiceStreamShared::open(const aaudio::AAudioStreamRequest &request,
50 aaudio::AAudioStreamConfiguration &configurationOutput) {
51
52 aaudio_result_t result = AAudioServiceStreamBase::open(request, configurationOutput);
53 if (result != AAUDIO_OK) {
54 ALOGE("AAudioServiceStreamBase open returned %d", result);
55 return result;
56 }
57
58 const AAudioStreamConfiguration &configurationInput = request.getConstantConfiguration();
59 int32_t deviceId = configurationInput.getDeviceId();
60 aaudio_direction_t direction = request.getDirection();
61
Phil Burkc0c70e32017-02-09 13:18:38 -080062 AAudioEndpointManager &mEndpointManager = AAudioEndpointManager::getInstance();
Phil Burk71f35bb2017-04-13 16:05:07 -070063 mServiceEndpoint = mEndpointManager.openEndpoint(mAudioService, deviceId, direction);
Phil Burkc0c70e32017-02-09 13:18:38 -080064 if (mServiceEndpoint == nullptr) {
Phil Burk87c9f642017-05-17 07:22:39 -070065 ALOGE("AAudioServiceStreamShared::open(), mServiceEndPoint = %p", mServiceEndpoint);
Phil Burkc0c70e32017-02-09 13:18:38 -080066 return AAUDIO_ERROR_UNAVAILABLE;
67 }
68
69 // Is the request compatible with the shared endpoint?
70 mAudioFormat = configurationInput.getAudioFormat();
71 if (mAudioFormat == AAUDIO_FORMAT_UNSPECIFIED) {
72 mAudioFormat = AAUDIO_FORMAT_PCM_FLOAT;
73 } else if (mAudioFormat != AAUDIO_FORMAT_PCM_FLOAT) {
Phil Burk71f35bb2017-04-13 16:05:07 -070074 ALOGE("AAudioServiceStreamShared::open(), mAudioFormat = %d, need FLOAT", mAudioFormat);
Phil Burkc0c70e32017-02-09 13:18:38 -080075 return AAUDIO_ERROR_INVALID_FORMAT;
76 }
77
78 mSampleRate = configurationInput.getSampleRate();
Glenn Kasten37a466a2017-05-30 15:53:14 -070079 if (mSampleRate == AAUDIO_UNSPECIFIED) {
Phil Burkc0c70e32017-02-09 13:18:38 -080080 mSampleRate = mServiceEndpoint->getSampleRate();
81 } else if (mSampleRate != mServiceEndpoint->getSampleRate()) {
Phil Burk71f35bb2017-04-13 16:05:07 -070082 ALOGE("AAudioServiceStreamShared::open(), mAudioFormat = %d, need %d",
83 mSampleRate, mServiceEndpoint->getSampleRate());
Phil Burkc0c70e32017-02-09 13:18:38 -080084 return AAUDIO_ERROR_INVALID_RATE;
85 }
86
87 mSamplesPerFrame = configurationInput.getSamplesPerFrame();
Glenn Kasten37a466a2017-05-30 15:53:14 -070088 if (mSamplesPerFrame == AAUDIO_UNSPECIFIED) {
Phil Burkc0c70e32017-02-09 13:18:38 -080089 mSamplesPerFrame = mServiceEndpoint->getSamplesPerFrame();
90 } else if (mSamplesPerFrame != mServiceEndpoint->getSamplesPerFrame()) {
Phil Burk71f35bb2017-04-13 16:05:07 -070091 ALOGE("AAudioServiceStreamShared::open(), mSamplesPerFrame = %d, need %d",
92 mSamplesPerFrame, mServiceEndpoint->getSamplesPerFrame());
Phil Burkc0c70e32017-02-09 13:18:38 -080093 return AAUDIO_ERROR_OUT_OF_RANGE;
94 }
95
96 // Determine this stream's shared memory buffer capacity.
97 mFramesPerBurst = mServiceEndpoint->getFramesPerBurst();
98 int32_t minCapacityFrames = configurationInput.getBufferCapacity();
Phil Burk71f35bb2017-04-13 16:05:07 -070099 int32_t numBursts = MAX_BURSTS_PER_BUFFER;
100 if (minCapacityFrames != AAUDIO_UNSPECIFIED) {
101 numBursts = (minCapacityFrames + mFramesPerBurst - 1) / mFramesPerBurst;
102 if (numBursts < MIN_BURSTS_PER_BUFFER) {
103 numBursts = MIN_BURSTS_PER_BUFFER;
104 } else if (numBursts > MAX_BURSTS_PER_BUFFER) {
105 numBursts = MAX_BURSTS_PER_BUFFER;
106 }
Phil Burkc0c70e32017-02-09 13:18:38 -0800107 }
108 mCapacityInFrames = numBursts * mFramesPerBurst;
109 ALOGD("AAudioServiceStreamShared::open(), mCapacityInFrames = %d", mCapacityInFrames);
110
111 // Create audio data shared memory buffer for client.
112 mAudioDataQueue = new SharedRingBuffer();
113 mAudioDataQueue->allocate(calculateBytesPerFrame(), mCapacityInFrames);
114
115 // Fill in configuration for client.
116 configurationOutput.setSampleRate(mSampleRate);
117 configurationOutput.setSamplesPerFrame(mSamplesPerFrame);
118 configurationOutput.setAudioFormat(mAudioFormat);
119 configurationOutput.setDeviceId(deviceId);
120
121 mServiceEndpoint->registerStream(this);
122
123 return AAUDIO_OK;
124}
125
126/**
127 * Start the flow of audio data.
128 *
129 * An AAUDIO_SERVICE_EVENT_STARTED will be sent to the client when complete.
130 */
131aaudio_result_t AAudioServiceStreamShared::start() {
Phil Burk71f35bb2017-04-13 16:05:07 -0700132 AAudioServiceEndpoint *endpoint = mServiceEndpoint;
133 if (endpoint == nullptr) {
134 return AAUDIO_ERROR_INVALID_STATE;
135 }
Phil Burk87c9f642017-05-17 07:22:39 -0700136 // For output streams, this will add the stream to the mixer.
Phil Burk71f35bb2017-04-13 16:05:07 -0700137 aaudio_result_t result = endpoint->startStream(this);
Phil Burkc0c70e32017-02-09 13:18:38 -0800138 if (result != AAUDIO_OK) {
139 ALOGE("AAudioServiceStreamShared::start() mServiceEndpoint returned %d", result);
140 processError();
141 } else {
142 result = AAudioServiceStreamBase::start();
143 }
144 return AAUDIO_OK;
145}
146
147/**
148 * Stop the flow of data so that start() can resume without loss of data.
149 *
150 * An AAUDIO_SERVICE_EVENT_PAUSED will be sent to the client when complete.
151*/
152aaudio_result_t AAudioServiceStreamShared::pause() {
Phil Burk71f35bb2017-04-13 16:05:07 -0700153 AAudioServiceEndpoint *endpoint = mServiceEndpoint;
154 if (endpoint == nullptr) {
155 return AAUDIO_ERROR_INVALID_STATE;
156 }
Phil Burkc0c70e32017-02-09 13:18:38 -0800157 // Add this stream to the mixer.
Phil Burk71f35bb2017-04-13 16:05:07 -0700158 aaudio_result_t result = endpoint->stopStream(this);
159 if (result != AAUDIO_OK) {
160 ALOGE("AAudioServiceStreamShared::pause() mServiceEndpoint returned %d", result);
161 processError();
162 }
163 return AAudioServiceStreamBase::pause();
164}
165
166aaudio_result_t AAudioServiceStreamShared::stop() {
167 AAudioServiceEndpoint *endpoint = mServiceEndpoint;
168 if (endpoint == nullptr) {
169 return AAUDIO_ERROR_INVALID_STATE;
170 }
171 // Add this stream to the mixer.
172 aaudio_result_t result = endpoint->stopStream(this);
Phil Burkc0c70e32017-02-09 13:18:38 -0800173 if (result != AAUDIO_OK) {
174 ALOGE("AAudioServiceStreamShared::stop() mServiceEndpoint returned %d", result);
175 processError();
Phil Burkc0c70e32017-02-09 13:18:38 -0800176 }
Phil Burk71f35bb2017-04-13 16:05:07 -0700177 return AAudioServiceStreamBase::stop();
Phil Burkc0c70e32017-02-09 13:18:38 -0800178}
179
180/**
181 * Discard any data held by the underlying HAL or Service.
182 *
183 * An AAUDIO_SERVICE_EVENT_FLUSHED will be sent to the client when complete.
184 */
185aaudio_result_t AAudioServiceStreamShared::flush() {
186 // TODO make sure we are paused
Phil Burk71f35bb2017-04-13 16:05:07 -0700187 // TODO actually flush the data
188 return AAudioServiceStreamBase::flush() ;
Phil Burkc0c70e32017-02-09 13:18:38 -0800189}
190
191aaudio_result_t AAudioServiceStreamShared::close() {
192 pause();
193 // TODO wait for pause() to synchronize
Phil Burk71f35bb2017-04-13 16:05:07 -0700194 AAudioServiceEndpoint *endpoint = mServiceEndpoint;
195 if (endpoint != nullptr) {
196 endpoint->unregisterStream(this);
197
198 AAudioEndpointManager &mEndpointManager = AAudioEndpointManager::getInstance();
199 mEndpointManager.closeEndpoint(endpoint);
200 mServiceEndpoint = nullptr;
201 }
Phil Burk942bdc02017-05-03 11:36:50 -0700202 if (mAudioDataQueue != nullptr) {
203 delete mAudioDataQueue;
204 mAudioDataQueue = nullptr;
205 }
Phil Burkc0c70e32017-02-09 13:18:38 -0800206 return AAudioServiceStreamBase::close();
207}
208
209/**
210 * Get an immutable description of the data queue created by this service.
211 */
212aaudio_result_t AAudioServiceStreamShared::getDownDataDescription(AudioEndpointParcelable &parcelable)
213{
214 // Gather information on the data queue.
215 mAudioDataQueue->fillParcelable(parcelable,
216 parcelable.mDownDataQueueParcelable);
217 parcelable.mDownDataQueueParcelable.setFramesPerBurst(getFramesPerBurst());
218 return AAUDIO_OK;
219}
220
221void AAudioServiceStreamShared::onStop() {
222}
223
224void AAudioServiceStreamShared::onDisconnect() {
225 mServiceEndpoint->close();
226 mServiceEndpoint = nullptr;
227}
228
Phil Burk71f35bb2017-04-13 16:05:07 -0700229void AAudioServiceStreamShared::markTransferTime(int64_t nanoseconds) {
230 mMarkedPosition = mAudioDataQueue->getFifoBuffer()->getReadCounter();
231 mMarkedTime = nanoseconds;
232}
Phil Burkc0c70e32017-02-09 13:18:38 -0800233
234aaudio_result_t AAudioServiceStreamShared::getFreeRunningPosition(int64_t *positionFrames,
235 int64_t *timeNanos) {
Phil Burk71f35bb2017-04-13 16:05:07 -0700236 // TODO get these two numbers as an atomic pair
237 *positionFrames = mMarkedPosition;
238 *timeNanos = mMarkedTime;
Phil Burkc0c70e32017-02-09 13:18:38 -0800239 return AAUDIO_OK;
240}