blob: 031468e9b5b2c859ef8d27ceafd4a45da6b75da5 [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
Eric Laurentcb4dae22017-07-01 19:39:32 -070017#define LOG_TAG "AAudioServiceStreamShared"
Phil Burkc0c70e32017-02-09 13:18:38 -080018//#define LOG_NDEBUG 0
19#include <utils/Log.h>
20
Phil Burka5222e22017-07-28 13:31:14 -070021#include <iomanip>
22#include <iostream>
Phil Burkc0c70e32017-02-09 13:18:38 -080023#include <mutex>
24
25#include <aaudio/AAudio.h>
26
Phil Burkc0c70e32017-02-09 13:18:38 -080027#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
Phil Burkec89b2e2017-06-20 15:05:06 -070037#define MIN_BURSTS_PER_BUFFER 2
38#define DEFAULT_BURSTS_PER_BUFFER 16
39// This is an arbitrary range. TODO review.
40#define MAX_FRAMES_PER_BUFFER (32 * 1024)
Phil Burkc0c70e32017-02-09 13:18:38 -080041
42AAudioServiceStreamShared::AAudioServiceStreamShared(AAudioService &audioService)
Phil Burk39f02dd2017-08-04 09:13:31 -070043 : AAudioServiceStreamBase(audioService)
Phil Burk97350f92017-07-21 15:59:44 -070044 , mTimestampPositionOffset(0)
Phil Burk39f02dd2017-08-04 09:13:31 -070045 , mXRunCount(0) {
Phil Burkc0c70e32017-02-09 13:18:38 -080046}
47
Phil Burka5222e22017-07-28 13:31:14 -070048std::string AAudioServiceStreamShared::dumpHeader() {
49 std::stringstream result;
50 result << AAudioServiceStreamBase::dumpHeader();
51 result << " Write# Read# Avail XRuns";
52 return result.str();
53}
54
55std::string AAudioServiceStreamShared::dump() const {
56 std::stringstream result;
Phil Burk39f02dd2017-08-04 09:13:31 -070057
Phil Burka5222e22017-07-28 13:31:14 -070058 result << AAudioServiceStreamBase::dump();
59
Phil Burk8f4fe502020-07-15 23:54:50 +000060 result << mAudioDataQueue->dump();
Phil Burka5222e22017-07-28 13:31:14 -070061 result << std::setw(8) << getXRunCount();
62
63 return result.str();
64}
65
Phil Burkec89b2e2017-06-20 15:05:06 -070066int32_t AAudioServiceStreamShared::calculateBufferCapacity(int32_t requestedCapacityFrames,
67 int32_t framesPerBurst) {
68
69 if (requestedCapacityFrames > MAX_FRAMES_PER_BUFFER) {
Phil Burkfbf031e2017-10-12 15:58:31 -070070 ALOGE("calculateBufferCapacity() requested capacity %d > max %d",
Phil Burkec89b2e2017-06-20 15:05:06 -070071 requestedCapacityFrames, MAX_FRAMES_PER_BUFFER);
72 return AAUDIO_ERROR_OUT_OF_RANGE;
73 }
74
75 // Determine how many bursts will fit in the buffer.
76 int32_t numBursts;
77 if (requestedCapacityFrames == AAUDIO_UNSPECIFIED) {
78 // Use fewer bursts if default is too many.
79 if ((DEFAULT_BURSTS_PER_BUFFER * framesPerBurst) > MAX_FRAMES_PER_BUFFER) {
80 numBursts = MAX_FRAMES_PER_BUFFER / framesPerBurst;
81 } else {
82 numBursts = DEFAULT_BURSTS_PER_BUFFER;
83 }
84 } else {
85 // round up to nearest burst boundary
86 numBursts = (requestedCapacityFrames + framesPerBurst - 1) / framesPerBurst;
87 }
88
89 // Clip to bare minimum.
90 if (numBursts < MIN_BURSTS_PER_BUFFER) {
91 numBursts = MIN_BURSTS_PER_BUFFER;
92 }
93 // Check for numeric overflow.
94 if (numBursts > 0x8000 || framesPerBurst > 0x8000) {
Phil Burkfbf031e2017-10-12 15:58:31 -070095 ALOGE("calculateBufferCapacity() overflow, capacity = %d * %d",
Phil Burkec89b2e2017-06-20 15:05:06 -070096 numBursts, framesPerBurst);
97 return AAUDIO_ERROR_OUT_OF_RANGE;
98 }
99 int32_t capacityInFrames = numBursts * framesPerBurst;
100
Phil Burk18142ae2020-07-28 12:44:37 -0700101 // Final range check.
Phil Burkec89b2e2017-06-20 15:05:06 -0700102 if (capacityInFrames > MAX_FRAMES_PER_BUFFER) {
Phil Burkfbf031e2017-10-12 15:58:31 -0700103 ALOGE("calculateBufferCapacity() calc capacity %d > max %d",
Phil Burkec89b2e2017-06-20 15:05:06 -0700104 capacityInFrames, MAX_FRAMES_PER_BUFFER);
105 return AAUDIO_ERROR_OUT_OF_RANGE;
106 }
Phil Burk7ba46552019-04-15 08:58:08 -0700107 ALOGV("calculateBufferCapacity() requested %d frames, actual = %d",
Phil Burkec89b2e2017-06-20 15:05:06 -0700108 requestedCapacityFrames, capacityInFrames);
109 return capacityInFrames;
110}
111
Phil Burk39f02dd2017-08-04 09:13:31 -0700112aaudio_result_t AAudioServiceStreamShared::open(const aaudio::AAudioStreamRequest &request) {
Phil Burkc0c70e32017-02-09 13:18:38 -0800113
Phil Burk11e8d332017-05-24 09:59:02 -0700114 sp<AAudioServiceStreamShared> keep(this);
115
Phil Burk15f97c92018-09-04 14:06:27 -0700116 if (request.getConstantConfiguration().getSharingMode() != AAUDIO_SHARING_MODE_SHARED) {
117 ALOGE("%s() sharingMode mismatch %d", __func__,
118 request.getConstantConfiguration().getSharingMode());
119 return AAUDIO_ERROR_INTERNAL;
120 }
121
122 aaudio_result_t result = AAudioServiceStreamBase::open(request);
Phil Burkc0c70e32017-02-09 13:18:38 -0800123 if (result != AAUDIO_OK) {
Phil Burkc0c70e32017-02-09 13:18:38 -0800124 return result;
125 }
126
127 const AAudioStreamConfiguration &configurationInput = request.getConstantConfiguration();
Phil Burkc0c70e32017-02-09 13:18:38 -0800128
Phil Burk6e2770e2018-05-01 13:03:52 -0700129 sp<AAudioServiceEndpoint> endpoint = mServiceEndpointWeak.promote();
130 if (endpoint == nullptr) {
131 result = AAUDIO_ERROR_INVALID_STATE;
132 goto error;
133 }
134
Phil Burkc0c70e32017-02-09 13:18:38 -0800135 // Is the request compatible with the shared endpoint?
Phil Burk39f02dd2017-08-04 09:13:31 -0700136 setFormat(configurationInput.getFormat());
Phil Burk0127c1b2018-03-29 13:48:06 -0700137 if (getFormat() == AUDIO_FORMAT_DEFAULT) {
138 setFormat(AUDIO_FORMAT_PCM_FLOAT);
139 } else if (getFormat() != AUDIO_FORMAT_PCM_FLOAT) {
Phil Burk7ba46552019-04-15 08:58:08 -0700140 ALOGD("%s() audio_format_t mAudioFormat = %d, need FLOAT", __func__, getFormat());
Phil Burkec89b2e2017-06-20 15:05:06 -0700141 result = AAUDIO_ERROR_INVALID_FORMAT;
142 goto error;
Phil Burkc0c70e32017-02-09 13:18:38 -0800143 }
144
Phil Burk39f02dd2017-08-04 09:13:31 -0700145 setSampleRate(configurationInput.getSampleRate());
146 if (getSampleRate() == AAUDIO_UNSPECIFIED) {
Phil Burk6e2770e2018-05-01 13:03:52 -0700147 setSampleRate(endpoint->getSampleRate());
148 } else if (getSampleRate() != endpoint->getSampleRate()) {
Phil Burk7ba46552019-04-15 08:58:08 -0700149 ALOGD("%s() mSampleRate = %d, need %d",
Phil Burk6e2770e2018-05-01 13:03:52 -0700150 __func__, getSampleRate(), endpoint->getSampleRate());
Phil Burkec89b2e2017-06-20 15:05:06 -0700151 result = AAUDIO_ERROR_INVALID_RATE;
152 goto error;
Phil Burkc0c70e32017-02-09 13:18:38 -0800153 }
154
Phil Burk39f02dd2017-08-04 09:13:31 -0700155 setSamplesPerFrame(configurationInput.getSamplesPerFrame());
156 if (getSamplesPerFrame() == AAUDIO_UNSPECIFIED) {
Phil Burk6e2770e2018-05-01 13:03:52 -0700157 setSamplesPerFrame(endpoint->getSamplesPerFrame());
158 } else if (getSamplesPerFrame() != endpoint->getSamplesPerFrame()) {
Phil Burk7ba46552019-04-15 08:58:08 -0700159 ALOGD("%s() mSamplesPerFrame = %d, need %d",
Phil Burk6e2770e2018-05-01 13:03:52 -0700160 __func__, getSamplesPerFrame(), endpoint->getSamplesPerFrame());
Phil Burkec89b2e2017-06-20 15:05:06 -0700161 result = AAUDIO_ERROR_OUT_OF_RANGE;
162 goto error;
Phil Burkc0c70e32017-02-09 13:18:38 -0800163 }
164
Phil Burk39f02dd2017-08-04 09:13:31 -0700165 setBufferCapacity(calculateBufferCapacity(configurationInput.getBufferCapacity(),
166 mFramesPerBurst));
167 if (getBufferCapacity() < 0) {
168 result = getBufferCapacity(); // negative error code
169 setBufferCapacity(0);
Phil Burkec89b2e2017-06-20 15:05:06 -0700170 goto error;
Phil Burkc0c70e32017-02-09 13:18:38 -0800171 }
Phil Burkc0c70e32017-02-09 13:18:38 -0800172
Phil Burk523b3042017-09-13 13:03:08 -0700173 {
174 std::lock_guard<std::mutex> lock(mAudioDataQueueLock);
175 // Create audio data shared memory buffer for client.
Phil Burk8f4fe502020-07-15 23:54:50 +0000176 mAudioDataQueue = std::make_shared<SharedRingBuffer>();
Phil Burk523b3042017-09-13 13:03:08 -0700177 result = mAudioDataQueue->allocate(calculateBytesPerFrame(), getBufferCapacity());
178 if (result != AAUDIO_OK) {
Phil Burk55e5eab2018-04-10 15:16:38 -0700179 ALOGE("%s() could not allocate FIFO with %d frames",
180 __func__, getBufferCapacity());
Phil Burk523b3042017-09-13 13:03:08 -0700181 result = AAUDIO_ERROR_NO_MEMORY;
182 goto error;
183 }
Phil Burkec89b2e2017-06-20 15:05:06 -0700184 }
185
Phil Burk6e2770e2018-05-01 13:03:52 -0700186 result = endpoint->registerStream(keep);
Phil Burkec89b2e2017-06-20 15:05:06 -0700187 if (result != AAUDIO_OK) {
188 goto error;
189 }
Phil Burkc0c70e32017-02-09 13:18:38 -0800190
Phil Burk5a26e662017-07-07 12:44:48 -0700191 setState(AAUDIO_STREAM_STATE_OPEN);
Phil Burkc0c70e32017-02-09 13:18:38 -0800192 return AAUDIO_OK;
Phil Burkec89b2e2017-06-20 15:05:06 -0700193
194error:
195 close();
196 return result;
Phil Burkc0c70e32017-02-09 13:18:38 -0800197}
198
Phil Burkc0c70e32017-02-09 13:18:38 -0800199/**
200 * Get an immutable description of the data queue created by this service.
201 */
Phil Burk523b3042017-09-13 13:03:08 -0700202aaudio_result_t AAudioServiceStreamShared::getAudioDataDescription(
203 AudioEndpointParcelable &parcelable)
Phil Burkc0c70e32017-02-09 13:18:38 -0800204{
Phil Burk523b3042017-09-13 13:03:08 -0700205 std::lock_guard<std::mutex> lock(mAudioDataQueueLock);
206 if (mAudioDataQueue == nullptr) {
Phil Burk7ba46552019-04-15 08:58:08 -0700207 ALOGW("%s(): mUpMessageQueue null! - stream not open", __func__);
Phil Burk523b3042017-09-13 13:03:08 -0700208 return AAUDIO_ERROR_NULL;
209 }
Phil Burkc0c70e32017-02-09 13:18:38 -0800210 // Gather information on the data queue.
211 mAudioDataQueue->fillParcelable(parcelable,
212 parcelable.mDownDataQueueParcelable);
213 parcelable.mDownDataQueueParcelable.setFramesPerBurst(getFramesPerBurst());
214 return AAUDIO_OK;
215}
216
Phil Burk97350f92017-07-21 15:59:44 -0700217void AAudioServiceStreamShared::markTransferTime(Timestamp &timestamp) {
Phil Burka53ffa62018-10-10 16:21:37 -0700218 mAtomicStreamTimestamp.write(timestamp);
Phil Burk71f35bb2017-04-13 16:05:07 -0700219}
Phil Burkc0c70e32017-02-09 13:18:38 -0800220
Phil Burk39f02dd2017-08-04 09:13:31 -0700221// Get timestamp that was written by mixer or distributor.
Phil Burkc0c70e32017-02-09 13:18:38 -0800222aaudio_result_t AAudioServiceStreamShared::getFreeRunningPosition(int64_t *positionFrames,
Phil Burk39f02dd2017-08-04 09:13:31 -0700223 int64_t *timeNanos) {
224 // TODO Get presentation timestamp from the HAL
Phil Burka53ffa62018-10-10 16:21:37 -0700225 if (mAtomicStreamTimestamp.isValid()) {
226 Timestamp timestamp = mAtomicStreamTimestamp.read();
Phil Burk97350f92017-07-21 15:59:44 -0700227 *positionFrames = timestamp.getPosition();
228 *timeNanos = timestamp.getNanoseconds();
229 return AAUDIO_OK;
230 } else {
231 return AAUDIO_ERROR_UNAVAILABLE;
232 }
233}
234
235// Get timestamp from lower level service.
236aaudio_result_t AAudioServiceStreamShared::getHardwareTimestamp(int64_t *positionFrames,
Phil Burk39f02dd2017-08-04 09:13:31 -0700237 int64_t *timeNanos) {
Phil Burk97350f92017-07-21 15:59:44 -0700238
Phil Burkbcc36742017-08-31 17:24:51 -0700239 int64_t position = 0;
Phil Burk6e2770e2018-05-01 13:03:52 -0700240 sp<AAudioServiceEndpoint> endpoint = mServiceEndpointWeak.promote();
241 if (endpoint == nullptr) {
Phil Burk7ba46552019-04-15 08:58:08 -0700242 ALOGW("%s() has no endpoint", __func__);
Phil Burk6e2770e2018-05-01 13:03:52 -0700243 return AAUDIO_ERROR_INVALID_STATE;
244 }
245
246 aaudio_result_t result = endpoint->getTimestamp(&position, timeNanos);
Phil Burk97350f92017-07-21 15:59:44 -0700247 if (result == AAUDIO_OK) {
Phil Burkbcc36742017-08-31 17:24:51 -0700248 int64_t offset = mTimestampPositionOffset.load();
249 // TODO, do not go below starting value
250 position -= offset; // Offset from shared MMAP stream
Phil Burk55e5eab2018-04-10 15:16:38 -0700251 ALOGV("%s() %8lld = %8lld - %8lld",
252 __func__, (long long) position, (long long) (position + offset), (long long) offset);
Phil Burk97350f92017-07-21 15:59:44 -0700253 }
Phil Burkbcc36742017-08-31 17:24:51 -0700254 *positionFrames = position;
Phil Burk97350f92017-07-21 15:59:44 -0700255 return result;
Phil Burkc0c70e32017-02-09 13:18:38 -0800256}
Phil Burk8f4fe502020-07-15 23:54:50 +0000257
258void AAudioServiceStreamShared::writeDataIfRoom(int64_t mmapFramesRead,
259 const void *buffer, int32_t numFrames) {
260 int64_t clientFramesWritten = 0;
261
262 // Lock the AudioFifo to protect against close.
263 std::lock_guard <std::mutex> lock(mAudioDataQueueLock);
264
265 if (mAudioDataQueue != nullptr) {
266 std::shared_ptr<FifoBuffer> fifo = mAudioDataQueue->getFifoBuffer();
267 // Determine offset between framePosition in client's stream
268 // vs the underlying MMAP stream.
269 clientFramesWritten = fifo->getWriteCounter();
270 // There are two indices that refer to the same frame.
271 int64_t positionOffset = mmapFramesRead - clientFramesWritten;
272 setTimestampPositionOffset(positionOffset);
273
274 // Is the buffer too full to write a burst?
275 if (fifo->getEmptyFramesAvailable() < getFramesPerBurst()) {
276 incrementXRunCount();
277 } else {
278 fifo->write(buffer, numFrames);
279 }
280 clientFramesWritten = fifo->getWriteCounter();
281 }
282
283 if (clientFramesWritten > 0) {
284 // This timestamp represents the completion of data being written into the
285 // client buffer. It is sent to the client and used in the timing model
286 // to decide when data will be available to read.
287 Timestamp timestamp(clientFramesWritten, AudioClock::getNanoseconds());
288 markTransferTime(timestamp);
289 }
290}