blob: e780f4f96652f51ea6ee6120d026d28a2fc3f1aa [file] [log] [blame]
Phil Burk204a1632017-01-03 17:23:43 -08001/*
2 * Copyright (C) 2016 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
Phil Burkfbf031e2017-10-12 15:58:31 -070017#define LOG_TAG "AudioEndpoint"
Phil Burk204a1632017-01-03 17:23:43 -080018//#define LOG_NDEBUG 0
19#include <utils/Log.h>
20
21#include <cassert>
Phil Burke4d7bb42017-03-28 11:32:39 -070022#include <aaudio/AAudio.h>
Phil Burk204a1632017-01-03 17:23:43 -080023
24#include "AudioEndpointParcelable.h"
25#include "AudioEndpoint.h"
Phil Burk5ed503c2017-02-01 09:38:15 -080026#include "AAudioServiceMessage.h"
Phil Burk204a1632017-01-03 17:23:43 -080027
28using namespace android;
Phil Burk5ed503c2017-02-01 09:38:15 -080029using namespace aaudio;
Phil Burk204a1632017-01-03 17:23:43 -080030
Phil Burk5204d312017-05-04 17:16:13 -070031#define RIDICULOUSLY_LARGE_BUFFER_CAPACITY (256 * 1024)
32#define RIDICULOUSLY_LARGE_FRAME_SIZE 4096
33
Phil Burkfbf031e2017-10-12 15:58:31 -070034// TODO Consider moving to a method in RingBufferDescriptor
Phil Burkc0c70e32017-02-09 13:18:38 -080035static aaudio_result_t AudioEndpoint_validateQueueDescriptor(const char *type,
Phil Burk204a1632017-01-03 17:23:43 -080036 const RingBufferDescriptor *descriptor) {
Phil Burkc0c70e32017-02-09 13:18:38 -080037 if (descriptor == nullptr) {
38 ALOGE("AudioEndpoint_validateQueueDescriptor() NULL descriptor");
39 return AAUDIO_ERROR_NULL;
40 }
Phil Burk5204d312017-05-04 17:16:13 -070041
42 if (descriptor->capacityInFrames < 1
43 || descriptor->capacityInFrames > RIDICULOUSLY_LARGE_BUFFER_CAPACITY) {
Phil Burkc0c70e32017-02-09 13:18:38 -080044 ALOGE("AudioEndpoint_validateQueueDescriptor() bad capacityInFrames = %d",
45 descriptor->capacityInFrames);
46 return AAUDIO_ERROR_OUT_OF_RANGE;
47 }
Phil Burk5204d312017-05-04 17:16:13 -070048
49 // Reject extreme values to catch bugs and prevent numeric overflows.
50 if (descriptor->bytesPerFrame < 1
51 || descriptor->bytesPerFrame > RIDICULOUSLY_LARGE_FRAME_SIZE) {
Phil Burkc0c70e32017-02-09 13:18:38 -080052 ALOGE("AudioEndpoint_validateQueueDescriptor() bad bytesPerFrame = %d",
53 descriptor->bytesPerFrame);
54 return AAUDIO_ERROR_OUT_OF_RANGE;
55 }
Phil Burk5204d312017-05-04 17:16:13 -070056
Phil Burkc0c70e32017-02-09 13:18:38 -080057 if (descriptor->dataAddress == nullptr) {
58 ALOGE("AudioEndpoint_validateQueueDescriptor() NULL dataAddress");
59 return AAUDIO_ERROR_NULL;
60 }
Phil Burk71f35bb2017-04-13 16:05:07 -070061 ALOGV("AudioEndpoint_validateQueueDescriptor %s, dataAddress at %p ====================",
Phil Burk204a1632017-01-03 17:23:43 -080062 type,
63 descriptor->dataAddress);
Phil Burk71f35bb2017-04-13 16:05:07 -070064 ALOGV("AudioEndpoint_validateQueueDescriptor readCounter at %p, writeCounter at %p",
Phil Burk204a1632017-01-03 17:23:43 -080065 descriptor->readCounterAddress,
66 descriptor->writeCounterAddress);
67
68 // Try to READ from the data area.
Phil Burkc0c70e32017-02-09 13:18:38 -080069 // This code will crash if the mmap failed.
Phil Burk204a1632017-01-03 17:23:43 -080070 uint8_t value = descriptor->dataAddress[0];
Phil Burk71f35bb2017-04-13 16:05:07 -070071 ALOGV("AudioEndpoint_validateQueueDescriptor() dataAddress[0] = %d, then try to write",
Phil Burk204a1632017-01-03 17:23:43 -080072 (int) value);
73 // Try to WRITE to the data area.
Phil Burkc0c70e32017-02-09 13:18:38 -080074 descriptor->dataAddress[0] = value * 3;
Phil Burk71f35bb2017-04-13 16:05:07 -070075 ALOGV("AudioEndpoint_validateQueueDescriptor() wrote successfully");
Phil Burk204a1632017-01-03 17:23:43 -080076
77 if (descriptor->readCounterAddress) {
78 fifo_counter_t counter = *descriptor->readCounterAddress;
Phil Burk71f35bb2017-04-13 16:05:07 -070079 ALOGV("AudioEndpoint_validateQueueDescriptor() *readCounterAddress = %d, now write",
Phil Burk204a1632017-01-03 17:23:43 -080080 (int) counter);
81 *descriptor->readCounterAddress = counter;
Phil Burk71f35bb2017-04-13 16:05:07 -070082 ALOGV("AudioEndpoint_validateQueueDescriptor() wrote readCounterAddress successfully");
Phil Burk204a1632017-01-03 17:23:43 -080083 }
Phil Burk5204d312017-05-04 17:16:13 -070084
Phil Burk204a1632017-01-03 17:23:43 -080085 if (descriptor->writeCounterAddress) {
86 fifo_counter_t counter = *descriptor->writeCounterAddress;
Phil Burk71f35bb2017-04-13 16:05:07 -070087 ALOGV("AudioEndpoint_validateQueueDescriptor() *writeCounterAddress = %d, now write",
Phil Burk204a1632017-01-03 17:23:43 -080088 (int) counter);
89 *descriptor->writeCounterAddress = counter;
Phil Burk71f35bb2017-04-13 16:05:07 -070090 ALOGV("AudioEndpoint_validateQueueDescriptor() wrote writeCounterAddress successfully");
Phil Burk204a1632017-01-03 17:23:43 -080091 }
Phil Burk5204d312017-05-04 17:16:13 -070092
Phil Burkc0c70e32017-02-09 13:18:38 -080093 return AAUDIO_OK;
Phil Burk204a1632017-01-03 17:23:43 -080094}
95
Phil Burkc0c70e32017-02-09 13:18:38 -080096aaudio_result_t AudioEndpoint_validateDescriptor(const EndpointDescriptor *pEndpointDescriptor) {
97 aaudio_result_t result = AudioEndpoint_validateQueueDescriptor("messages",
98 &pEndpointDescriptor->upMessageQueueDescriptor);
99 if (result == AAUDIO_OK) {
100 result = AudioEndpoint_validateQueueDescriptor("data",
Phil Burk87c9f642017-05-17 07:22:39 -0700101 &pEndpointDescriptor->dataQueueDescriptor);
Phil Burkc0c70e32017-02-09 13:18:38 -0800102 }
103 return result;
Phil Burk204a1632017-01-03 17:23:43 -0800104}
105
Phil Burkfd34a932017-07-19 07:03:52 -0700106aaudio_result_t AudioEndpoint::configure(const EndpointDescriptor *pEndpointDescriptor,
107 aaudio_direction_t direction)
Phil Burk204a1632017-01-03 17:23:43 -0800108{
Phil Burkc0c70e32017-02-09 13:18:38 -0800109 aaudio_result_t result = AudioEndpoint_validateDescriptor(pEndpointDescriptor);
110 if (result != AAUDIO_OK) {
Phil Burkc0c70e32017-02-09 13:18:38 -0800111 return result;
112 }
Phil Burk204a1632017-01-03 17:23:43 -0800113
Phil Burk5204d312017-05-04 17:16:13 -0700114 // ============================ up message queue =============================
Phil Burk204a1632017-01-03 17:23:43 -0800115 const RingBufferDescriptor *descriptor = &pEndpointDescriptor->upMessageQueueDescriptor;
Phil Burk5204d312017-05-04 17:16:13 -0700116 if(descriptor->bytesPerFrame != sizeof(AAudioServiceMessage)) {
Phil Burkfbf031e2017-10-12 15:58:31 -0700117 ALOGE("configure() bytesPerFrame != sizeof(AAudioServiceMessage) = %d",
Phil Burk5204d312017-05-04 17:16:13 -0700118 descriptor->bytesPerFrame);
119 return AAUDIO_ERROR_INTERNAL;
120 }
121
122 if(descriptor->readCounterAddress == nullptr || descriptor->writeCounterAddress == nullptr) {
Phil Burkfbf031e2017-10-12 15:58:31 -0700123 ALOGE("configure() NULL counter address");
Phil Burk5204d312017-05-04 17:16:13 -0700124 return AAUDIO_ERROR_NULL;
125 }
126
Phil Burk99306c82017-08-14 12:38:58 -0700127 // Prevent memory leak and reuse.
128 if(mUpCommandQueue != nullptr || mDataQueue != nullptr) {
Phil Burkfbf031e2017-10-12 15:58:31 -0700129 ALOGE("configure() endpoint already used");
Phil Burk99306c82017-08-14 12:38:58 -0700130 return AAUDIO_ERROR_INTERNAL;
131 }
132
Phil Burk8f4fe502020-07-15 23:54:50 +0000133 mUpCommandQueue = std::make_unique<FifoBufferIndirect>(
Phil Burk204a1632017-01-03 17:23:43 -0800134 descriptor->bytesPerFrame,
135 descriptor->capacityInFrames,
136 descriptor->readCounterAddress,
137 descriptor->writeCounterAddress,
138 descriptor->dataAddress
139 );
Phil Burk5204d312017-05-04 17:16:13 -0700140
Phil Burkfd34a932017-07-19 07:03:52 -0700141 // ============================ data queue =============================
jiabinf7f06152021-11-22 18:10:14 +0000142 result = configureDataQueue(pEndpointDescriptor->dataQueueDescriptor, direction);
143
144 return result;
145}
146
147aaudio_result_t AudioEndpoint::configureDataQueue(const RingBufferDescriptor& descriptor,
148 aaudio_direction_t direction) {
149 aaudio_result_t result = AudioEndpoint_validateQueueDescriptor("data", &descriptor);
150 if (result != AAUDIO_OK) {
151 return result;
152 }
153
154 ALOGV("configure() data framesPerBurst = %d", descriptor.framesPerBurst);
Phil Burkfbf031e2017-10-12 15:58:31 -0700155 ALOGV("configure() data readCounterAddress = %p",
jiabinf7f06152021-11-22 18:10:14 +0000156 descriptor.readCounterAddress);
Phil Burkfd34a932017-07-19 07:03:52 -0700157
158 // An example of free running is when the other side is read or written by hardware DMA
159 // or a DSP. It does not update its counter so we have to update it.
160 int64_t *remoteCounter = (direction == AAUDIO_DIRECTION_OUTPUT)
jiabinf7f06152021-11-22 18:10:14 +0000161 ? descriptor.readCounterAddress // read by other side
162 : descriptor.writeCounterAddress; // written by other side
Phil Burkfd34a932017-07-19 07:03:52 -0700163 mFreeRunning = (remoteCounter == nullptr);
Phil Burkfbf031e2017-10-12 15:58:31 -0700164 ALOGV("configure() mFreeRunning = %d", mFreeRunning ? 1 : 0);
Phil Burkfd34a932017-07-19 07:03:52 -0700165
jiabinf7f06152021-11-22 18:10:14 +0000166 int64_t *readCounterAddress = (descriptor.readCounterAddress == nullptr)
Phil Burk204a1632017-01-03 17:23:43 -0800167 ? &mDataReadCounter
jiabinf7f06152021-11-22 18:10:14 +0000168 : descriptor.readCounterAddress;
169 int64_t *writeCounterAddress = (descriptor.writeCounterAddress == nullptr)
Phil Burk204a1632017-01-03 17:23:43 -0800170 ? &mDataWriteCounter
jiabinf7f06152021-11-22 18:10:14 +0000171 : descriptor.writeCounterAddress;
Phil Burkc0c70e32017-02-09 13:18:38 -0800172
Phil Burkeddcf362021-05-20 23:22:09 +0000173 // Clear buffer to avoid an initial glitch on some devices.
jiabinf7f06152021-11-22 18:10:14 +0000174 size_t bufferSizeBytes = descriptor.capacityInFrames * descriptor.bytesPerFrame;
175 memset(descriptor.dataAddress, 0, bufferSizeBytes);
Phil Burkeddcf362021-05-20 23:22:09 +0000176
Phil Burk8f4fe502020-07-15 23:54:50 +0000177 mDataQueue = std::make_unique<FifoBufferIndirect>(
jiabinf7f06152021-11-22 18:10:14 +0000178 descriptor.bytesPerFrame,
179 descriptor.capacityInFrames,
Phil Burk204a1632017-01-03 17:23:43 -0800180 readCounterAddress,
181 writeCounterAddress,
jiabinf7f06152021-11-22 18:10:14 +0000182 descriptor.dataAddress
Phil Burk204a1632017-01-03 17:23:43 -0800183 );
jiabinf7f06152021-11-22 18:10:14 +0000184 uint32_t threshold = descriptor.capacityInFrames / 2;
Phil Burk87c9f642017-05-17 07:22:39 -0700185 mDataQueue->setThreshold(threshold);
Phil Burk204a1632017-01-03 17:23:43 -0800186 return result;
187}
188
Phil Burk5ed503c2017-02-01 09:38:15 -0800189aaudio_result_t AudioEndpoint::readUpCommand(AAudioServiceMessage *commandPtr)
Phil Burk204a1632017-01-03 17:23:43 -0800190{
191 return mUpCommandQueue->read(commandPtr, 1);
192}
193
Phil Burkfd34a932017-07-19 07:03:52 -0700194int32_t AudioEndpoint::getEmptyFramesAvailable(WrappingBuffer *wrappingBuffer) {
jiabinf7f06152021-11-22 18:10:14 +0000195 return mDataQueue == nullptr ? 0 : mDataQueue->getEmptyRoomAvailable(wrappingBuffer);
Phil Burkc0c70e32017-02-09 13:18:38 -0800196}
197
Phil Burk5edc4ea2020-04-17 08:15:42 -0700198int32_t AudioEndpoint::getEmptyFramesAvailable() {
jiabinf7f06152021-11-22 18:10:14 +0000199 return mDataQueue == nullptr ? 0 : mDataQueue->getEmptyFramesAvailable();
Phil Burk87c9f642017-05-17 07:22:39 -0700200}
201
Phil Burk5edc4ea2020-04-17 08:15:42 -0700202int32_t AudioEndpoint::getFullFramesAvailable(WrappingBuffer *wrappingBuffer) {
jiabinf7f06152021-11-22 18:10:14 +0000203 return mDataQueue == nullptr ? 0 : mDataQueue->getFullDataAvailable(wrappingBuffer);
Phil Burk4485d412017-05-09 15:55:02 -0700204}
205
Phil Burk5edc4ea2020-04-17 08:15:42 -0700206int32_t AudioEndpoint::getFullFramesAvailable() {
jiabinf7f06152021-11-22 18:10:14 +0000207 return mDataQueue == nullptr ? 0 : mDataQueue->getFullFramesAvailable();
208}
209
210android::fifo_frames_t AudioEndpoint::read(void *buffer, android::fifo_frames_t numFrames) {
211 return mDataQueue == nullptr ? 0 : mDataQueue->read(buffer, numFrames);
212}
213
214android::fifo_frames_t AudioEndpoint::write(void *buffer, android::fifo_frames_t numFrames) {
215 return mDataQueue == nullptr ? 0 : mDataQueue->write(buffer, numFrames);
Phil Burk4485d412017-05-09 15:55:02 -0700216}
217
Phil Burkc0c70e32017-02-09 13:18:38 -0800218void AudioEndpoint::advanceWriteIndex(int32_t deltaFrames) {
jiabinf7f06152021-11-22 18:10:14 +0000219 if (mDataQueue != nullptr) {
220 mDataQueue->advanceWriteIndex(deltaFrames);
221 }
Phil Burkc0c70e32017-02-09 13:18:38 -0800222}
223
Phil Burk87c9f642017-05-17 07:22:39 -0700224void AudioEndpoint::advanceReadIndex(int32_t deltaFrames) {
jiabinf7f06152021-11-22 18:10:14 +0000225 if (mDataQueue != nullptr) {
226 mDataQueue->advanceReadIndex(deltaFrames);
227 }
Phil Burk204a1632017-01-03 17:23:43 -0800228}
229
Phil Burk5edc4ea2020-04-17 08:15:42 -0700230void AudioEndpoint::setDataReadCounter(fifo_counter_t framesRead) {
jiabinf7f06152021-11-22 18:10:14 +0000231 if (mDataQueue != nullptr) {
232 mDataQueue->setReadCounter(framesRead);
233 }
Phil Burk204a1632017-01-03 17:23:43 -0800234}
235
Phil Burk5edc4ea2020-04-17 08:15:42 -0700236fifo_counter_t AudioEndpoint::getDataReadCounter() const {
jiabinf7f06152021-11-22 18:10:14 +0000237 return mDataQueue == nullptr ? 0 : mDataQueue->getReadCounter();
Phil Burk204a1632017-01-03 17:23:43 -0800238}
239
Phil Burk5edc4ea2020-04-17 08:15:42 -0700240void AudioEndpoint::setDataWriteCounter(fifo_counter_t framesRead) {
jiabinf7f06152021-11-22 18:10:14 +0000241 if (mDataQueue != nullptr) {
242 mDataQueue->setWriteCounter(framesRead);
243 }
Phil Burk87c9f642017-05-17 07:22:39 -0700244}
245
Phil Burk5edc4ea2020-04-17 08:15:42 -0700246fifo_counter_t AudioEndpoint::getDataWriteCounter() const {
jiabinf7f06152021-11-22 18:10:14 +0000247 return mDataQueue == nullptr ? 0 : mDataQueue->getWriteCounter();
Phil Burk204a1632017-01-03 17:23:43 -0800248}
249
Phil Burk3316d5e2017-02-15 11:23:01 -0800250int32_t AudioEndpoint::setBufferSizeInFrames(int32_t requestedFrames,
Phil Burk5edc4ea2020-04-17 08:15:42 -0700251 int32_t *actualFrames) {
jiabinf7f06152021-11-22 18:10:14 +0000252 if (mDataQueue == nullptr) {
253 return AAUDIO_ERROR_INVALID_STATE;
254 }
Phil Burk204a1632017-01-03 17:23:43 -0800255 if (requestedFrames < ENDPOINT_DATA_QUEUE_SIZE_MIN) {
256 requestedFrames = ENDPOINT_DATA_QUEUE_SIZE_MIN;
257 }
Phil Burk87c9f642017-05-17 07:22:39 -0700258 mDataQueue->setThreshold(requestedFrames);
259 *actualFrames = mDataQueue->getThreshold();
Phil Burk5ed503c2017-02-01 09:38:15 -0800260 return AAUDIO_OK;
Phil Burk204a1632017-01-03 17:23:43 -0800261}
262
Phil Burk5edc4ea2020-04-17 08:15:42 -0700263int32_t AudioEndpoint::getBufferSizeInFrames() const {
jiabinf7f06152021-11-22 18:10:14 +0000264 return mDataQueue == nullptr ? 0 : mDataQueue->getThreshold();
Phil Burk204a1632017-01-03 17:23:43 -0800265}
266
Phil Burk5edc4ea2020-04-17 08:15:42 -0700267int32_t AudioEndpoint::getBufferCapacityInFrames() const {
jiabinf7f06152021-11-22 18:10:14 +0000268 return mDataQueue == nullptr ? 0 : (int32_t)mDataQueue->getBufferCapacityInFrames();
Phil Burk204a1632017-01-03 17:23:43 -0800269}
270
Phil Burkec89b2e2017-06-20 15:05:06 -0700271void AudioEndpoint::dump() const {
Phil Burk5edc4ea2020-04-17 08:15:42 -0700272 ALOGD("data readCounter = %lld", (long long) getDataReadCounter());
273 ALOGD("data writeCounter = %lld", (long long) getDataWriteCounter());
Phil Burkec89b2e2017-06-20 15:05:06 -0700274}
Phil Burkea04d972017-08-07 12:30:44 -0700275
276void AudioEndpoint::eraseDataMemory() {
jiabinf7f06152021-11-22 18:10:14 +0000277 if (mDataQueue != nullptr) {
278 mDataQueue->eraseMemory();
279 }
Phil Burkea04d972017-08-07 12:30:44 -0700280}