• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "AAudio"
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 
AudioEndpoint()34 AudioEndpoint::AudioEndpoint()
35     : mUpCommandQueue(nullptr)
36     , mDataQueue(nullptr)
37     , mFreeRunning(false)
38     , mDataReadCounter(0)
39     , mDataWriteCounter(0)
40 {
41 }
42 
~AudioEndpoint()43 AudioEndpoint::~AudioEndpoint() {
44     delete mDataQueue;
45     delete mUpCommandQueue;
46 }
47 
AudioEndpoint_validateQueueDescriptor(const char * type,const RingBufferDescriptor * descriptor)48 static aaudio_result_t AudioEndpoint_validateQueueDescriptor(const char *type,
49                                                   const RingBufferDescriptor *descriptor) {
50     if (descriptor == nullptr) {
51         ALOGE("AudioEndpoint_validateQueueDescriptor() NULL descriptor");
52         return AAUDIO_ERROR_NULL;
53     }
54 
55     if (descriptor->capacityInFrames < 1
56         || descriptor->capacityInFrames > RIDICULOUSLY_LARGE_BUFFER_CAPACITY) {
57         ALOGE("AudioEndpoint_validateQueueDescriptor() bad capacityInFrames = %d",
58               descriptor->capacityInFrames);
59         return AAUDIO_ERROR_OUT_OF_RANGE;
60     }
61 
62     // Reject extreme values to catch bugs and prevent numeric overflows.
63     if (descriptor->bytesPerFrame < 1
64         || descriptor->bytesPerFrame > RIDICULOUSLY_LARGE_FRAME_SIZE) {
65         ALOGE("AudioEndpoint_validateQueueDescriptor() bad bytesPerFrame = %d",
66               descriptor->bytesPerFrame);
67         return AAUDIO_ERROR_OUT_OF_RANGE;
68     }
69 
70     if (descriptor->dataAddress == nullptr) {
71         ALOGE("AudioEndpoint_validateQueueDescriptor() NULL dataAddress");
72         return AAUDIO_ERROR_NULL;
73     }
74     ALOGV("AudioEndpoint_validateQueueDescriptor %s, dataAddress at %p ====================",
75           type,
76           descriptor->dataAddress);
77     ALOGV("AudioEndpoint_validateQueueDescriptor  readCounter at %p, writeCounter at %p",
78           descriptor->readCounterAddress,
79           descriptor->writeCounterAddress);
80 
81     // Try to READ from the data area.
82     // This code will crash if the mmap failed.
83     uint8_t value = descriptor->dataAddress[0];
84     ALOGV("AudioEndpoint_validateQueueDescriptor() dataAddress[0] = %d, then try to write",
85         (int) value);
86     // Try to WRITE to the data area.
87     descriptor->dataAddress[0] = value * 3;
88     ALOGV("AudioEndpoint_validateQueueDescriptor() wrote successfully");
89 
90     if (descriptor->readCounterAddress) {
91         fifo_counter_t counter = *descriptor->readCounterAddress;
92         ALOGV("AudioEndpoint_validateQueueDescriptor() *readCounterAddress = %d, now write",
93               (int) counter);
94         *descriptor->readCounterAddress = counter;
95         ALOGV("AudioEndpoint_validateQueueDescriptor() wrote readCounterAddress successfully");
96     }
97 
98     if (descriptor->writeCounterAddress) {
99         fifo_counter_t counter = *descriptor->writeCounterAddress;
100         ALOGV("AudioEndpoint_validateQueueDescriptor() *writeCounterAddress = %d, now write",
101               (int) counter);
102         *descriptor->writeCounterAddress = counter;
103         ALOGV("AudioEndpoint_validateQueueDescriptor() wrote writeCounterAddress successfully");
104     }
105 
106     return AAUDIO_OK;
107 }
108 
AudioEndpoint_validateDescriptor(const EndpointDescriptor * pEndpointDescriptor)109 aaudio_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",
114                                                 &pEndpointDescriptor->dataQueueDescriptor);
115     }
116     return result;
117 }
118 
configure(const EndpointDescriptor * pEndpointDescriptor,aaudio_direction_t direction)119 aaudio_result_t AudioEndpoint::configure(const EndpointDescriptor *pEndpointDescriptor,
120                                          aaudio_direction_t   direction)
121 {
122     aaudio_result_t result = AudioEndpoint_validateDescriptor(pEndpointDescriptor);
123     if (result != AAUDIO_OK) {
124         return result;
125     }
126 
127     // ============================ up message queue =============================
128     const RingBufferDescriptor *descriptor = &pEndpointDescriptor->upMessageQueueDescriptor;
129     if(descriptor->bytesPerFrame != sizeof(AAudioServiceMessage)) {
130         ALOGE("AudioEndpoint.configure() bytesPerFrame != sizeof(AAudioServiceMessage) = %d",
131               descriptor->bytesPerFrame);
132         return AAUDIO_ERROR_INTERNAL;
133     }
134 
135     if(descriptor->readCounterAddress == nullptr || descriptor->writeCounterAddress == nullptr) {
136         ALOGE("AudioEndpoint.configure() NULL counter address");
137         return AAUDIO_ERROR_NULL;
138     }
139 
140     // 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 
146     mUpCommandQueue = new FifoBuffer(
147             descriptor->bytesPerFrame,
148             descriptor->capacityInFrames,
149             descriptor->readCounterAddress,
150             descriptor->writeCounterAddress,
151             descriptor->dataAddress
152     );
153 
154     // ============================ data queue =============================
155     descriptor = &pEndpointDescriptor->dataQueueDescriptor;
156     ALOGV("AudioEndpoint.configure() data framesPerBurst = %d", descriptor->framesPerBurst);
157     ALOGV("AudioEndpoint.configure() data readCounterAddress = %p",
158           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);
166     ALOGV("AudioEndpoint.configure() mFreeRunning = %d", mFreeRunning ? 1 : 0);
167 
168     int64_t *readCounterAddress = (descriptor->readCounterAddress == nullptr)
169                                   ? &mDataReadCounter
170                                   : descriptor->readCounterAddress;
171     int64_t *writeCounterAddress = (descriptor->writeCounterAddress == nullptr)
172                                   ? &mDataWriteCounter
173                                   : descriptor->writeCounterAddress;
174 
175     mDataQueue = new FifoBuffer(
176             descriptor->bytesPerFrame,
177             descriptor->capacityInFrames,
178             readCounterAddress,
179             writeCounterAddress,
180             descriptor->dataAddress
181     );
182     uint32_t threshold = descriptor->capacityInFrames / 2;
183     mDataQueue->setThreshold(threshold);
184     return result;
185 }
186 
readUpCommand(AAudioServiceMessage * commandPtr)187 aaudio_result_t AudioEndpoint::readUpCommand(AAudioServiceMessage *commandPtr)
188 {
189     return mUpCommandQueue->read(commandPtr, 1);
190 }
191 
getEmptyFramesAvailable(WrappingBuffer * wrappingBuffer)192 int32_t AudioEndpoint::getEmptyFramesAvailable(WrappingBuffer *wrappingBuffer) {
193     return mDataQueue->getEmptyRoomAvailable(wrappingBuffer);
194 }
195 
getEmptyFramesAvailable()196 int32_t AudioEndpoint::getEmptyFramesAvailable()
197 {
198     return mDataQueue->getFifoControllerBase()->getEmptyFramesAvailable();
199 }
200 
getFullFramesAvailable(WrappingBuffer * wrappingBuffer)201 int32_t AudioEndpoint::getFullFramesAvailable(WrappingBuffer *wrappingBuffer)
202 {
203     return mDataQueue->getFullDataAvailable(wrappingBuffer);
204 }
205 
getFullFramesAvailable()206 int32_t AudioEndpoint::getFullFramesAvailable()
207 {
208     return mDataQueue->getFifoControllerBase()->getFullFramesAvailable();
209 }
210 
advanceWriteIndex(int32_t deltaFrames)211 void AudioEndpoint::advanceWriteIndex(int32_t deltaFrames) {
212     mDataQueue->getFifoControllerBase()->advanceWriteIndex(deltaFrames);
213 }
214 
advanceReadIndex(int32_t deltaFrames)215 void AudioEndpoint::advanceReadIndex(int32_t deltaFrames) {
216     mDataQueue->getFifoControllerBase()->advanceReadIndex(deltaFrames);
217 }
218 
setDataReadCounter(fifo_counter_t framesRead)219 void AudioEndpoint::setDataReadCounter(fifo_counter_t framesRead)
220 {
221     mDataQueue->setReadCounter(framesRead);
222 }
223 
getDataReadCounter()224 fifo_counter_t AudioEndpoint::getDataReadCounter()
225 {
226     return mDataQueue->getReadCounter();
227 }
228 
setDataWriteCounter(fifo_counter_t framesRead)229 void AudioEndpoint::setDataWriteCounter(fifo_counter_t framesRead)
230 {
231     mDataQueue->setWriteCounter(framesRead);
232 }
233 
getDataWriteCounter()234 fifo_counter_t AudioEndpoint::getDataWriteCounter()
235 {
236     return mDataQueue->getWriteCounter();
237 }
238 
setBufferSizeInFrames(int32_t requestedFrames,int32_t * actualFrames)239 int32_t AudioEndpoint::setBufferSizeInFrames(int32_t requestedFrames,
240                                             int32_t *actualFrames)
241 {
242     if (requestedFrames < ENDPOINT_DATA_QUEUE_SIZE_MIN) {
243         requestedFrames = ENDPOINT_DATA_QUEUE_SIZE_MIN;
244     }
245     mDataQueue->setThreshold(requestedFrames);
246     *actualFrames = mDataQueue->getThreshold();
247     return AAUDIO_OK;
248 }
249 
getBufferSizeInFrames() const250 int32_t AudioEndpoint::getBufferSizeInFrames() const
251 {
252     return mDataQueue->getThreshold();
253 }
254 
getBufferCapacityInFrames() const255 int32_t AudioEndpoint::getBufferCapacityInFrames() const
256 {
257     return (int32_t)mDataQueue->getBufferCapacityInFrames();
258 }
259 
dump() const260 void AudioEndpoint::dump() const {
261     ALOGD("AudioEndpoint: data readCounter  = %lld", (long long) mDataQueue->getReadCounter());
262     ALOGD("AudioEndpoint: data writeCounter = %lld", (long long) mDataQueue->getWriteCounter());
263 }
264 
eraseDataMemory()265 void AudioEndpoint::eraseDataMemory() {
266     mDataQueue->eraseMemory();
267 }
268