1 /*
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
17 #define LOG_TAG "AudioEndpoint"
18 //#define LOG_NDEBUG 0
19 #include <utils/Log.h>
20
21 #include <cassert>
22 #include <aaudio/AAudio.h>
23
24 #include "AudioEndpointParcelable.h"
25 #include "AudioEndpoint.h"
26 #include "AAudioServiceMessage.h"
27
28 using namespace android;
29 using namespace aaudio;
30
31 #define RIDICULOUSLY_LARGE_BUFFER_CAPACITY (256 * 1024)
32 #define RIDICULOUSLY_LARGE_FRAME_SIZE 4096
33
34 // TODO Consider moving to a method in RingBufferDescriptor
AudioEndpoint_validateQueueDescriptor(const char * type,const RingBufferDescriptor * descriptor)35 static aaudio_result_t AudioEndpoint_validateQueueDescriptor(const char *type,
36 const RingBufferDescriptor *descriptor) {
37 if (descriptor == nullptr) {
38 ALOGE("AudioEndpoint_validateQueueDescriptor() NULL descriptor");
39 return AAUDIO_ERROR_NULL;
40 }
41
42 if (descriptor->capacityInFrames < 1
43 || descriptor->capacityInFrames > RIDICULOUSLY_LARGE_BUFFER_CAPACITY) {
44 ALOGE("AudioEndpoint_validateQueueDescriptor() bad capacityInFrames = %d",
45 descriptor->capacityInFrames);
46 return AAUDIO_ERROR_OUT_OF_RANGE;
47 }
48
49 // Reject extreme values to catch bugs and prevent numeric overflows.
50 if (descriptor->bytesPerFrame < 1
51 || descriptor->bytesPerFrame > RIDICULOUSLY_LARGE_FRAME_SIZE) {
52 ALOGE("AudioEndpoint_validateQueueDescriptor() bad bytesPerFrame = %d",
53 descriptor->bytesPerFrame);
54 return AAUDIO_ERROR_OUT_OF_RANGE;
55 }
56
57 if (descriptor->dataAddress == nullptr) {
58 ALOGE("AudioEndpoint_validateQueueDescriptor() NULL dataAddress");
59 return AAUDIO_ERROR_NULL;
60 }
61 ALOGV("AudioEndpoint_validateQueueDescriptor %s, dataAddress at %p ====================",
62 type,
63 descriptor->dataAddress);
64 ALOGV("AudioEndpoint_validateQueueDescriptor readCounter at %p, writeCounter at %p",
65 descriptor->readCounterAddress,
66 descriptor->writeCounterAddress);
67
68 // Try to READ from the data area.
69 // This code will crash if the mmap failed.
70 uint8_t value = descriptor->dataAddress[0];
71 ALOGV("AudioEndpoint_validateQueueDescriptor() dataAddress[0] = %d, then try to write",
72 (int) value);
73 // Try to WRITE to the data area.
74 descriptor->dataAddress[0] = value * 3;
75 ALOGV("AudioEndpoint_validateQueueDescriptor() wrote successfully");
76
77 if (descriptor->readCounterAddress) {
78 fifo_counter_t counter = *descriptor->readCounterAddress;
79 ALOGV("AudioEndpoint_validateQueueDescriptor() *readCounterAddress = %d, now write",
80 (int) counter);
81 *descriptor->readCounterAddress = counter;
82 ALOGV("AudioEndpoint_validateQueueDescriptor() wrote readCounterAddress successfully");
83 }
84
85 if (descriptor->writeCounterAddress) {
86 fifo_counter_t counter = *descriptor->writeCounterAddress;
87 ALOGV("AudioEndpoint_validateQueueDescriptor() *writeCounterAddress = %d, now write",
88 (int) counter);
89 *descriptor->writeCounterAddress = counter;
90 ALOGV("AudioEndpoint_validateQueueDescriptor() wrote writeCounterAddress successfully");
91 }
92
93 return AAUDIO_OK;
94 }
95
AudioEndpoint_validateDescriptor(const EndpointDescriptor * pEndpointDescriptor)96 aaudio_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",
101 &pEndpointDescriptor->dataQueueDescriptor);
102 }
103 return result;
104 }
105
configure(const EndpointDescriptor * pEndpointDescriptor,aaudio_direction_t direction)106 aaudio_result_t AudioEndpoint::configure(const EndpointDescriptor *pEndpointDescriptor,
107 aaudio_direction_t direction)
108 {
109 aaudio_result_t result = AudioEndpoint_validateDescriptor(pEndpointDescriptor);
110 if (result != AAUDIO_OK) {
111 return result;
112 }
113
114 // ============================ up message queue =============================
115 const RingBufferDescriptor *descriptor = &pEndpointDescriptor->upMessageQueueDescriptor;
116 if(descriptor->bytesPerFrame != sizeof(AAudioServiceMessage)) {
117 ALOGE("configure() bytesPerFrame != sizeof(AAudioServiceMessage) = %d",
118 descriptor->bytesPerFrame);
119 return AAUDIO_ERROR_INTERNAL;
120 }
121
122 if(descriptor->readCounterAddress == nullptr || descriptor->writeCounterAddress == nullptr) {
123 ALOGE("configure() NULL counter address");
124 return AAUDIO_ERROR_NULL;
125 }
126
127 // Prevent memory leak and reuse.
128 if(mUpCommandQueue != nullptr || mDataQueue != nullptr) {
129 ALOGE("configure() endpoint already used");
130 return AAUDIO_ERROR_INTERNAL;
131 }
132
133 mUpCommandQueue = std::make_unique<FifoBufferIndirect>(
134 descriptor->bytesPerFrame,
135 descriptor->capacityInFrames,
136 descriptor->readCounterAddress,
137 descriptor->writeCounterAddress,
138 descriptor->dataAddress
139 );
140
141 // ============================ data queue =============================
142 result = configureDataQueue(pEndpointDescriptor->dataQueueDescriptor, direction);
143
144 return result;
145 }
146
configureDataQueue(const RingBufferDescriptor & descriptor,aaudio_direction_t direction)147 aaudio_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);
155 ALOGV("configure() data readCounterAddress = %p",
156 descriptor.readCounterAddress);
157
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)
161 ? descriptor.readCounterAddress // read by other side
162 : descriptor.writeCounterAddress; // written by other side
163 mFreeRunning = (remoteCounter == nullptr);
164 ALOGV("configure() mFreeRunning = %d", mFreeRunning ? 1 : 0);
165
166 int64_t *readCounterAddress = (descriptor.readCounterAddress == nullptr)
167 ? &mDataReadCounter
168 : descriptor.readCounterAddress;
169 int64_t *writeCounterAddress = (descriptor.writeCounterAddress == nullptr)
170 ? &mDataWriteCounter
171 : descriptor.writeCounterAddress;
172
173 // Clear buffer to avoid an initial glitch on some devices.
174 size_t bufferSizeBytes = descriptor.capacityInFrames * descriptor.bytesPerFrame;
175 memset(descriptor.dataAddress, 0, bufferSizeBytes);
176
177 mDataQueue = std::make_unique<FifoBufferIndirect>(
178 descriptor.bytesPerFrame,
179 descriptor.capacityInFrames,
180 readCounterAddress,
181 writeCounterAddress,
182 descriptor.dataAddress
183 );
184 uint32_t threshold = descriptor.capacityInFrames / 2;
185 mDataQueue->setThreshold(threshold);
186 return result;
187 }
188
readUpCommand(AAudioServiceMessage * commandPtr)189 aaudio_result_t AudioEndpoint::readUpCommand(AAudioServiceMessage *commandPtr)
190 {
191 return mUpCommandQueue->read(commandPtr, 1);
192 }
193
getEmptyFramesAvailable(WrappingBuffer * wrappingBuffer)194 int32_t AudioEndpoint::getEmptyFramesAvailable(WrappingBuffer *wrappingBuffer) {
195 return mDataQueue == nullptr ? 0 : mDataQueue->getEmptyRoomAvailable(wrappingBuffer);
196 }
197
getEmptyFramesAvailable()198 int32_t AudioEndpoint::getEmptyFramesAvailable() {
199 return mDataQueue == nullptr ? 0 : mDataQueue->getEmptyFramesAvailable();
200 }
201
getFullFramesAvailable(WrappingBuffer * wrappingBuffer)202 int32_t AudioEndpoint::getFullFramesAvailable(WrappingBuffer *wrappingBuffer) {
203 return mDataQueue == nullptr ? 0 : mDataQueue->getFullDataAvailable(wrappingBuffer);
204 }
205
getFullFramesAvailable()206 int32_t AudioEndpoint::getFullFramesAvailable() {
207 return mDataQueue == nullptr ? 0 : mDataQueue->getFullFramesAvailable();
208 }
209
read(void * buffer,android::fifo_frames_t numFrames)210 android::fifo_frames_t AudioEndpoint::read(void *buffer, android::fifo_frames_t numFrames) {
211 return mDataQueue == nullptr ? 0 : mDataQueue->read(buffer, numFrames);
212 }
213
write(void * buffer,android::fifo_frames_t numFrames)214 android::fifo_frames_t AudioEndpoint::write(void *buffer, android::fifo_frames_t numFrames) {
215 return mDataQueue == nullptr ? 0 : mDataQueue->write(buffer, numFrames);
216 }
217
advanceWriteIndex(int32_t deltaFrames)218 void AudioEndpoint::advanceWriteIndex(int32_t deltaFrames) {
219 if (mDataQueue != nullptr) {
220 mDataQueue->advanceWriteIndex(deltaFrames);
221 }
222 }
223
advanceReadIndex(int32_t deltaFrames)224 void AudioEndpoint::advanceReadIndex(int32_t deltaFrames) {
225 if (mDataQueue != nullptr) {
226 mDataQueue->advanceReadIndex(deltaFrames);
227 }
228 }
229
setDataReadCounter(fifo_counter_t framesRead)230 void AudioEndpoint::setDataReadCounter(fifo_counter_t framesRead) {
231 if (mDataQueue != nullptr) {
232 mDataQueue->setReadCounter(framesRead);
233 }
234 }
235
getDataReadCounter() const236 fifo_counter_t AudioEndpoint::getDataReadCounter() const {
237 return mDataQueue == nullptr ? 0 : mDataQueue->getReadCounter();
238 }
239
setDataWriteCounter(fifo_counter_t framesRead)240 void AudioEndpoint::setDataWriteCounter(fifo_counter_t framesRead) {
241 if (mDataQueue != nullptr) {
242 mDataQueue->setWriteCounter(framesRead);
243 }
244 }
245
getDataWriteCounter() const246 fifo_counter_t AudioEndpoint::getDataWriteCounter() const {
247 return mDataQueue == nullptr ? 0 : mDataQueue->getWriteCounter();
248 }
249
setBufferSizeInFrames(int32_t requestedFrames,int32_t * actualFrames)250 int32_t AudioEndpoint::setBufferSizeInFrames(int32_t requestedFrames,
251 int32_t *actualFrames) {
252 if (mDataQueue == nullptr) {
253 return AAUDIO_ERROR_INVALID_STATE;
254 }
255 if (requestedFrames < ENDPOINT_DATA_QUEUE_SIZE_MIN) {
256 requestedFrames = ENDPOINT_DATA_QUEUE_SIZE_MIN;
257 }
258 mDataQueue->setThreshold(requestedFrames);
259 *actualFrames = mDataQueue->getThreshold();
260 return AAUDIO_OK;
261 }
262
getBufferSizeInFrames() const263 int32_t AudioEndpoint::getBufferSizeInFrames() const {
264 return mDataQueue == nullptr ? 0 : mDataQueue->getThreshold();
265 }
266
getBufferCapacityInFrames() const267 int32_t AudioEndpoint::getBufferCapacityInFrames() const {
268 return mDataQueue == nullptr ? 0 : (int32_t)mDataQueue->getBufferCapacityInFrames();
269 }
270
dump() const271 void AudioEndpoint::dump() const {
272 ALOGD("data readCounter = %lld", (long long) getDataReadCounter());
273 ALOGD("data writeCounter = %lld", (long long) getDataWriteCounter());
274 }
275
eraseDataMemory()276 void AudioEndpoint::eraseDataMemory() {
277 if (mDataQueue != nullptr) {
278 mDataQueue->eraseMemory();
279 }
280 }
281
eraseEmptyDataMemory(int32_t numFrames)282 void AudioEndpoint::eraseEmptyDataMemory(int32_t numFrames) {
283 if (mDataQueue != nullptr) {
284 mDataQueue->eraseEmptyMemory(numFrames);
285 }
286 }
287