blob: 604eed57abf86bd67135f11dd8066229b785278f [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 Burk5ed503c2017-02-01 09:38:15 -080017#define LOG_TAG "AAudio"
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 Burk204a1632017-01-03 17:23:43 -080034AudioEndpoint::AudioEndpoint()
Phil Burk4a8d2602017-08-09 16:53:35 -070035 : mUpCommandQueue(nullptr)
36 , mDataQueue(nullptr)
37 , mFreeRunning(false)
Phil Burk204a1632017-01-03 17:23:43 -080038 , mDataReadCounter(0)
39 , mDataWriteCounter(0)
40{
41}
42
Phil Burk4a8d2602017-08-09 16:53:35 -070043AudioEndpoint::~AudioEndpoint() {
44 delete mDataQueue;
45 delete mUpCommandQueue;
Phil Burk204a1632017-01-03 17:23:43 -080046}
47
Phil Burkc0c70e32017-02-09 13:18:38 -080048static aaudio_result_t AudioEndpoint_validateQueueDescriptor(const char *type,
Phil Burk204a1632017-01-03 17:23:43 -080049 const RingBufferDescriptor *descriptor) {
Phil Burkc0c70e32017-02-09 13:18:38 -080050 if (descriptor == nullptr) {
51 ALOGE("AudioEndpoint_validateQueueDescriptor() NULL descriptor");
52 return AAUDIO_ERROR_NULL;
53 }
Phil Burk5204d312017-05-04 17:16:13 -070054
55 if (descriptor->capacityInFrames < 1
56 || descriptor->capacityInFrames > RIDICULOUSLY_LARGE_BUFFER_CAPACITY) {
Phil Burkc0c70e32017-02-09 13:18:38 -080057 ALOGE("AudioEndpoint_validateQueueDescriptor() bad capacityInFrames = %d",
58 descriptor->capacityInFrames);
59 return AAUDIO_ERROR_OUT_OF_RANGE;
60 }
Phil Burk5204d312017-05-04 17:16:13 -070061
62 // Reject extreme values to catch bugs and prevent numeric overflows.
63 if (descriptor->bytesPerFrame < 1
64 || descriptor->bytesPerFrame > RIDICULOUSLY_LARGE_FRAME_SIZE) {
Phil Burkc0c70e32017-02-09 13:18:38 -080065 ALOGE("AudioEndpoint_validateQueueDescriptor() bad bytesPerFrame = %d",
66 descriptor->bytesPerFrame);
67 return AAUDIO_ERROR_OUT_OF_RANGE;
68 }
Phil Burk5204d312017-05-04 17:16:13 -070069
Phil Burkc0c70e32017-02-09 13:18:38 -080070 if (descriptor->dataAddress == nullptr) {
71 ALOGE("AudioEndpoint_validateQueueDescriptor() NULL dataAddress");
72 return AAUDIO_ERROR_NULL;
73 }
Phil Burk71f35bb2017-04-13 16:05:07 -070074 ALOGV("AudioEndpoint_validateQueueDescriptor %s, dataAddress at %p ====================",
Phil Burk204a1632017-01-03 17:23:43 -080075 type,
76 descriptor->dataAddress);
Phil Burk71f35bb2017-04-13 16:05:07 -070077 ALOGV("AudioEndpoint_validateQueueDescriptor readCounter at %p, writeCounter at %p",
Phil Burk204a1632017-01-03 17:23:43 -080078 descriptor->readCounterAddress,
79 descriptor->writeCounterAddress);
80
81 // Try to READ from the data area.
Phil Burkc0c70e32017-02-09 13:18:38 -080082 // This code will crash if the mmap failed.
Phil Burk204a1632017-01-03 17:23:43 -080083 uint8_t value = descriptor->dataAddress[0];
Phil Burk71f35bb2017-04-13 16:05:07 -070084 ALOGV("AudioEndpoint_validateQueueDescriptor() dataAddress[0] = %d, then try to write",
Phil Burk204a1632017-01-03 17:23:43 -080085 (int) value);
86 // Try to WRITE to the data area.
Phil Burkc0c70e32017-02-09 13:18:38 -080087 descriptor->dataAddress[0] = value * 3;
Phil Burk71f35bb2017-04-13 16:05:07 -070088 ALOGV("AudioEndpoint_validateQueueDescriptor() wrote successfully");
Phil Burk204a1632017-01-03 17:23:43 -080089
90 if (descriptor->readCounterAddress) {
91 fifo_counter_t counter = *descriptor->readCounterAddress;
Phil Burk71f35bb2017-04-13 16:05:07 -070092 ALOGV("AudioEndpoint_validateQueueDescriptor() *readCounterAddress = %d, now write",
Phil Burk204a1632017-01-03 17:23:43 -080093 (int) counter);
94 *descriptor->readCounterAddress = counter;
Phil Burk71f35bb2017-04-13 16:05:07 -070095 ALOGV("AudioEndpoint_validateQueueDescriptor() wrote readCounterAddress successfully");
Phil Burk204a1632017-01-03 17:23:43 -080096 }
Phil Burk5204d312017-05-04 17:16:13 -070097
Phil Burk204a1632017-01-03 17:23:43 -080098 if (descriptor->writeCounterAddress) {
99 fifo_counter_t counter = *descriptor->writeCounterAddress;
Phil Burk71f35bb2017-04-13 16:05:07 -0700100 ALOGV("AudioEndpoint_validateQueueDescriptor() *writeCounterAddress = %d, now write",
Phil Burk204a1632017-01-03 17:23:43 -0800101 (int) counter);
102 *descriptor->writeCounterAddress = counter;
Phil Burk71f35bb2017-04-13 16:05:07 -0700103 ALOGV("AudioEndpoint_validateQueueDescriptor() wrote writeCounterAddress successfully");
Phil Burk204a1632017-01-03 17:23:43 -0800104 }
Phil Burk5204d312017-05-04 17:16:13 -0700105
Phil Burkc0c70e32017-02-09 13:18:38 -0800106 return AAUDIO_OK;
Phil Burk204a1632017-01-03 17:23:43 -0800107}
108
Phil Burkc0c70e32017-02-09 13:18:38 -0800109aaudio_result_t AudioEndpoint_validateDescriptor(const EndpointDescriptor *pEndpointDescriptor) {
110 aaudio_result_t result = AudioEndpoint_validateQueueDescriptor("messages",
111 &pEndpointDescriptor->upMessageQueueDescriptor);
112 if (result == AAUDIO_OK) {
113 result = AudioEndpoint_validateQueueDescriptor("data",
Phil Burk87c9f642017-05-17 07:22:39 -0700114 &pEndpointDescriptor->dataQueueDescriptor);
Phil Burkc0c70e32017-02-09 13:18:38 -0800115 }
116 return result;
Phil Burk204a1632017-01-03 17:23:43 -0800117}
118
Phil Burkfd34a932017-07-19 07:03:52 -0700119aaudio_result_t AudioEndpoint::configure(const EndpointDescriptor *pEndpointDescriptor,
120 aaudio_direction_t direction)
Phil Burk204a1632017-01-03 17:23:43 -0800121{
Phil Burkc0c70e32017-02-09 13:18:38 -0800122 aaudio_result_t result = AudioEndpoint_validateDescriptor(pEndpointDescriptor);
123 if (result != AAUDIO_OK) {
Phil Burkc0c70e32017-02-09 13:18:38 -0800124 return result;
125 }
Phil Burk204a1632017-01-03 17:23:43 -0800126
Phil Burk5204d312017-05-04 17:16:13 -0700127 // ============================ up message queue =============================
Phil Burk204a1632017-01-03 17:23:43 -0800128 const RingBufferDescriptor *descriptor = &pEndpointDescriptor->upMessageQueueDescriptor;
Phil Burk5204d312017-05-04 17:16:13 -0700129 if(descriptor->bytesPerFrame != sizeof(AAudioServiceMessage)) {
Phil Burk99306c82017-08-14 12:38:58 -0700130 ALOGE("AudioEndpoint.configure() bytesPerFrame != sizeof(AAudioServiceMessage) = %d",
Phil Burk5204d312017-05-04 17:16:13 -0700131 descriptor->bytesPerFrame);
132 return AAUDIO_ERROR_INTERNAL;
133 }
134
135 if(descriptor->readCounterAddress == nullptr || descriptor->writeCounterAddress == nullptr) {
Phil Burk99306c82017-08-14 12:38:58 -0700136 ALOGE("AudioEndpoint.configure() NULL counter address");
Phil Burk5204d312017-05-04 17:16:13 -0700137 return AAUDIO_ERROR_NULL;
138 }
139
Phil Burk99306c82017-08-14 12:38:58 -0700140 // Prevent memory leak and reuse.
141 if(mUpCommandQueue != nullptr || mDataQueue != nullptr) {
142 ALOGE("AudioEndpoint.configure() endpoint already used");
143 return AAUDIO_ERROR_INTERNAL;
144 }
145
Phil Burk204a1632017-01-03 17:23:43 -0800146 mUpCommandQueue = new FifoBuffer(
147 descriptor->bytesPerFrame,
148 descriptor->capacityInFrames,
149 descriptor->readCounterAddress,
150 descriptor->writeCounterAddress,
151 descriptor->dataAddress
152 );
Phil Burk5204d312017-05-04 17:16:13 -0700153
Phil Burkfd34a932017-07-19 07:03:52 -0700154 // ============================ data queue =============================
Phil Burk87c9f642017-05-17 07:22:39 -0700155 descriptor = &pEndpointDescriptor->dataQueueDescriptor;
Phil Burk99306c82017-08-14 12:38:58 -0700156 ALOGV("AudioEndpoint.configure() data framesPerBurst = %d", descriptor->framesPerBurst);
157 ALOGV("AudioEndpoint.configure() data readCounterAddress = %p",
Phil Burkfd34a932017-07-19 07:03:52 -0700158 descriptor->readCounterAddress);
159
160 // An example of free running is when the other side is read or written by hardware DMA
161 // or a DSP. It does not update its counter so we have to update it.
162 int64_t *remoteCounter = (direction == AAUDIO_DIRECTION_OUTPUT)
163 ? descriptor->readCounterAddress // read by other side
164 : descriptor->writeCounterAddress; // written by other side
165 mFreeRunning = (remoteCounter == nullptr);
Phil Burk99306c82017-08-14 12:38:58 -0700166 ALOGV("AudioEndpoint.configure() mFreeRunning = %d", mFreeRunning ? 1 : 0);
Phil Burkfd34a932017-07-19 07:03:52 -0700167
Phil Burk204a1632017-01-03 17:23:43 -0800168 int64_t *readCounterAddress = (descriptor->readCounterAddress == nullptr)
169 ? &mDataReadCounter
170 : descriptor->readCounterAddress;
171 int64_t *writeCounterAddress = (descriptor->writeCounterAddress == nullptr)
172 ? &mDataWriteCounter
173 : descriptor->writeCounterAddress;
Phil Burkc0c70e32017-02-09 13:18:38 -0800174
Phil Burk87c9f642017-05-17 07:22:39 -0700175 mDataQueue = new FifoBuffer(
Phil Burk204a1632017-01-03 17:23:43 -0800176 descriptor->bytesPerFrame,
177 descriptor->capacityInFrames,
178 readCounterAddress,
179 writeCounterAddress,
180 descriptor->dataAddress
181 );
182 uint32_t threshold = descriptor->capacityInFrames / 2;
Phil Burk87c9f642017-05-17 07:22:39 -0700183 mDataQueue->setThreshold(threshold);
Phil Burk204a1632017-01-03 17:23:43 -0800184 return result;
185}
186
Phil Burk5ed503c2017-02-01 09:38:15 -0800187aaudio_result_t AudioEndpoint::readUpCommand(AAudioServiceMessage *commandPtr)
Phil Burk204a1632017-01-03 17:23:43 -0800188{
189 return mUpCommandQueue->read(commandPtr, 1);
190}
191
Phil Burkfd34a932017-07-19 07:03:52 -0700192int32_t AudioEndpoint::getEmptyFramesAvailable(WrappingBuffer *wrappingBuffer) {
193 return mDataQueue->getEmptyRoomAvailable(wrappingBuffer);
Phil Burkc0c70e32017-02-09 13:18:38 -0800194}
195
Phil Burk87c9f642017-05-17 07:22:39 -0700196int32_t AudioEndpoint::getEmptyFramesAvailable()
197{
198 return mDataQueue->getFifoControllerBase()->getEmptyFramesAvailable();
199}
200
Phil Burkfd34a932017-07-19 07:03:52 -0700201int32_t AudioEndpoint::getFullFramesAvailable(WrappingBuffer *wrappingBuffer)
Phil Burk87c9f642017-05-17 07:22:39 -0700202{
203 return mDataQueue->getFullDataAvailable(wrappingBuffer);
Phil Burk4485d412017-05-09 15:55:02 -0700204}
205
206int32_t AudioEndpoint::getFullFramesAvailable()
207{
Phil Burk87c9f642017-05-17 07:22:39 -0700208 return mDataQueue->getFifoControllerBase()->getFullFramesAvailable();
Phil Burk4485d412017-05-09 15:55:02 -0700209}
210
Phil Burkc0c70e32017-02-09 13:18:38 -0800211void AudioEndpoint::advanceWriteIndex(int32_t deltaFrames) {
Phil Burk87c9f642017-05-17 07:22:39 -0700212 mDataQueue->getFifoControllerBase()->advanceWriteIndex(deltaFrames);
Phil Burkc0c70e32017-02-09 13:18:38 -0800213}
214
Phil Burk87c9f642017-05-17 07:22:39 -0700215void AudioEndpoint::advanceReadIndex(int32_t deltaFrames) {
216 mDataQueue->getFifoControllerBase()->advanceReadIndex(deltaFrames);
Phil Burk204a1632017-01-03 17:23:43 -0800217}
218
Phil Burk87c9f642017-05-17 07:22:39 -0700219void AudioEndpoint::setDataReadCounter(fifo_counter_t framesRead)
Phil Burk204a1632017-01-03 17:23:43 -0800220{
Phil Burk87c9f642017-05-17 07:22:39 -0700221 mDataQueue->setReadCounter(framesRead);
Phil Burk204a1632017-01-03 17:23:43 -0800222}
223
Phil Burk87c9f642017-05-17 07:22:39 -0700224fifo_counter_t AudioEndpoint::getDataReadCounter()
Phil Burk204a1632017-01-03 17:23:43 -0800225{
Phil Burk87c9f642017-05-17 07:22:39 -0700226 return mDataQueue->getReadCounter();
Phil Burk204a1632017-01-03 17:23:43 -0800227}
228
Phil Burk87c9f642017-05-17 07:22:39 -0700229void AudioEndpoint::setDataWriteCounter(fifo_counter_t framesRead)
Phil Burk204a1632017-01-03 17:23:43 -0800230{
Phil Burk87c9f642017-05-17 07:22:39 -0700231 mDataQueue->setWriteCounter(framesRead);
232}
233
234fifo_counter_t AudioEndpoint::getDataWriteCounter()
235{
236 return mDataQueue->getWriteCounter();
Phil Burk204a1632017-01-03 17:23:43 -0800237}
238
Phil Burk3316d5e2017-02-15 11:23:01 -0800239int32_t AudioEndpoint::setBufferSizeInFrames(int32_t requestedFrames,
240 int32_t *actualFrames)
Phil Burk204a1632017-01-03 17:23:43 -0800241{
242 if (requestedFrames < ENDPOINT_DATA_QUEUE_SIZE_MIN) {
243 requestedFrames = ENDPOINT_DATA_QUEUE_SIZE_MIN;
244 }
Phil Burk87c9f642017-05-17 07:22:39 -0700245 mDataQueue->setThreshold(requestedFrames);
246 *actualFrames = mDataQueue->getThreshold();
Phil Burk5ed503c2017-02-01 09:38:15 -0800247 return AAUDIO_OK;
Phil Burk204a1632017-01-03 17:23:43 -0800248}
249
250int32_t AudioEndpoint::getBufferSizeInFrames() const
251{
Phil Burk87c9f642017-05-17 07:22:39 -0700252 return mDataQueue->getThreshold();
Phil Burk204a1632017-01-03 17:23:43 -0800253}
254
255int32_t AudioEndpoint::getBufferCapacityInFrames() const
256{
Phil Burk87c9f642017-05-17 07:22:39 -0700257 return (int32_t)mDataQueue->getBufferCapacityInFrames();
Phil Burk204a1632017-01-03 17:23:43 -0800258}
259
Phil Burkec89b2e2017-06-20 15:05:06 -0700260void AudioEndpoint::dump() const {
261 ALOGD("AudioEndpoint: data readCounter = %lld", (long long) mDataQueue->getReadCounter());
262 ALOGD("AudioEndpoint: data writeCounter = %lld", (long long) mDataQueue->getWriteCounter());
263}
Phil Burkea04d972017-08-07 12:30:44 -0700264
265void AudioEndpoint::eraseDataMemory() {
266 mDataQueue->eraseMemory();
267}