• 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 "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 
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 
48 // TODO Consider moving to a method in RingBufferDescriptor
AudioEndpoint_validateQueueDescriptor(const char * type,const RingBufferDescriptor * descriptor)49 static aaudio_result_t AudioEndpoint_validateQueueDescriptor(const char *type,
50                                                   const RingBufferDescriptor *descriptor) {
51     if (descriptor == nullptr) {
52         ALOGE("AudioEndpoint_validateQueueDescriptor() NULL descriptor");
53         return AAUDIO_ERROR_NULL;
54     }
55 
56     if (descriptor->capacityInFrames < 1
57         || descriptor->capacityInFrames > RIDICULOUSLY_LARGE_BUFFER_CAPACITY) {
58         ALOGE("AudioEndpoint_validateQueueDescriptor() bad capacityInFrames = %d",
59               descriptor->capacityInFrames);
60         return AAUDIO_ERROR_OUT_OF_RANGE;
61     }
62 
63     // Reject extreme values to catch bugs and prevent numeric overflows.
64     if (descriptor->bytesPerFrame < 1
65         || descriptor->bytesPerFrame > RIDICULOUSLY_LARGE_FRAME_SIZE) {
66         ALOGE("AudioEndpoint_validateQueueDescriptor() bad bytesPerFrame = %d",
67               descriptor->bytesPerFrame);
68         return AAUDIO_ERROR_OUT_OF_RANGE;
69     }
70 
71     if (descriptor->dataAddress == nullptr) {
72         ALOGE("AudioEndpoint_validateQueueDescriptor() NULL dataAddress");
73         return AAUDIO_ERROR_NULL;
74     }
75     ALOGV("AudioEndpoint_validateQueueDescriptor %s, dataAddress at %p ====================",
76           type,
77           descriptor->dataAddress);
78     ALOGV("AudioEndpoint_validateQueueDescriptor  readCounter at %p, writeCounter at %p",
79           descriptor->readCounterAddress,
80           descriptor->writeCounterAddress);
81 
82     // Try to READ from the data area.
83     // This code will crash if the mmap failed.
84     uint8_t value = descriptor->dataAddress[0];
85     ALOGV("AudioEndpoint_validateQueueDescriptor() dataAddress[0] = %d, then try to write",
86         (int) value);
87     // Try to WRITE to the data area.
88     descriptor->dataAddress[0] = value * 3;
89     ALOGV("AudioEndpoint_validateQueueDescriptor() wrote successfully");
90 
91     if (descriptor->readCounterAddress) {
92         fifo_counter_t counter = *descriptor->readCounterAddress;
93         ALOGV("AudioEndpoint_validateQueueDescriptor() *readCounterAddress = %d, now write",
94               (int) counter);
95         *descriptor->readCounterAddress = counter;
96         ALOGV("AudioEndpoint_validateQueueDescriptor() wrote readCounterAddress successfully");
97     }
98 
99     if (descriptor->writeCounterAddress) {
100         fifo_counter_t counter = *descriptor->writeCounterAddress;
101         ALOGV("AudioEndpoint_validateQueueDescriptor() *writeCounterAddress = %d, now write",
102               (int) counter);
103         *descriptor->writeCounterAddress = counter;
104         ALOGV("AudioEndpoint_validateQueueDescriptor() wrote writeCounterAddress successfully");
105     }
106 
107     return AAUDIO_OK;
108 }
109 
AudioEndpoint_validateDescriptor(const EndpointDescriptor * pEndpointDescriptor)110 aaudio_result_t AudioEndpoint_validateDescriptor(const EndpointDescriptor *pEndpointDescriptor) {
111     aaudio_result_t result = AudioEndpoint_validateQueueDescriptor("messages",
112                                     &pEndpointDescriptor->upMessageQueueDescriptor);
113     if (result == AAUDIO_OK) {
114         result = AudioEndpoint_validateQueueDescriptor("data",
115                                                 &pEndpointDescriptor->dataQueueDescriptor);
116     }
117     return result;
118 }
119 
configure(const EndpointDescriptor * pEndpointDescriptor,aaudio_direction_t direction)120 aaudio_result_t AudioEndpoint::configure(const EndpointDescriptor *pEndpointDescriptor,
121                                          aaudio_direction_t   direction)
122 {
123     aaudio_result_t result = AudioEndpoint_validateDescriptor(pEndpointDescriptor);
124     if (result != AAUDIO_OK) {
125         return result;
126     }
127 
128     // ============================ up message queue =============================
129     const RingBufferDescriptor *descriptor = &pEndpointDescriptor->upMessageQueueDescriptor;
130     if(descriptor->bytesPerFrame != sizeof(AAudioServiceMessage)) {
131         ALOGE("configure() bytesPerFrame != sizeof(AAudioServiceMessage) = %d",
132               descriptor->bytesPerFrame);
133         return AAUDIO_ERROR_INTERNAL;
134     }
135 
136     if(descriptor->readCounterAddress == nullptr || descriptor->writeCounterAddress == nullptr) {
137         ALOGE("configure() NULL counter address");
138         return AAUDIO_ERROR_NULL;
139     }
140 
141     // Prevent memory leak and reuse.
142     if(mUpCommandQueue != nullptr || mDataQueue != nullptr) {
143         ALOGE("configure() endpoint already used");
144         return AAUDIO_ERROR_INTERNAL;
145     }
146 
147     mUpCommandQueue = new FifoBuffer(
148             descriptor->bytesPerFrame,
149             descriptor->capacityInFrames,
150             descriptor->readCounterAddress,
151             descriptor->writeCounterAddress,
152             descriptor->dataAddress
153     );
154 
155     // ============================ data queue =============================
156     descriptor = &pEndpointDescriptor->dataQueueDescriptor;
157     ALOGV("configure() data framesPerBurst = %d", descriptor->framesPerBurst);
158     ALOGV("configure() data readCounterAddress = %p",
159           descriptor->readCounterAddress);
160 
161     // An example of free running is when the other side is read or written by hardware DMA
162     // or a DSP. It does not update its counter so we have to update it.
163     int64_t *remoteCounter = (direction == AAUDIO_DIRECTION_OUTPUT)
164                              ? descriptor->readCounterAddress // read by other side
165                              : descriptor->writeCounterAddress; // written by other side
166     mFreeRunning = (remoteCounter == nullptr);
167     ALOGV("configure() mFreeRunning = %d", mFreeRunning ? 1 : 0);
168 
169     int64_t *readCounterAddress = (descriptor->readCounterAddress == nullptr)
170                                   ? &mDataReadCounter
171                                   : descriptor->readCounterAddress;
172     int64_t *writeCounterAddress = (descriptor->writeCounterAddress == nullptr)
173                                   ? &mDataWriteCounter
174                                   : descriptor->writeCounterAddress;
175 
176     mDataQueue = new FifoBuffer(
177             descriptor->bytesPerFrame,
178             descriptor->capacityInFrames,
179             readCounterAddress,
180             writeCounterAddress,
181             descriptor->dataAddress
182     );
183     uint32_t threshold = descriptor->capacityInFrames / 2;
184     mDataQueue->setThreshold(threshold);
185     return result;
186 }
187 
readUpCommand(AAudioServiceMessage * commandPtr)188 aaudio_result_t AudioEndpoint::readUpCommand(AAudioServiceMessage *commandPtr)
189 {
190     return mUpCommandQueue->read(commandPtr, 1);
191 }
192 
getEmptyFramesAvailable(WrappingBuffer * wrappingBuffer)193 int32_t AudioEndpoint::getEmptyFramesAvailable(WrappingBuffer *wrappingBuffer) {
194     return mDataQueue->getEmptyRoomAvailable(wrappingBuffer);
195 }
196 
getEmptyFramesAvailable()197 int32_t AudioEndpoint::getEmptyFramesAvailable()
198 {
199     return mDataQueue->getEmptyFramesAvailable();
200 }
201 
getFullFramesAvailable(WrappingBuffer * wrappingBuffer)202 int32_t AudioEndpoint::getFullFramesAvailable(WrappingBuffer *wrappingBuffer)
203 {
204     return mDataQueue->getFullDataAvailable(wrappingBuffer);
205 }
206 
getFullFramesAvailable()207 int32_t AudioEndpoint::getFullFramesAvailable()
208 {
209     return mDataQueue->getFullFramesAvailable();
210 }
211 
advanceWriteIndex(int32_t deltaFrames)212 void AudioEndpoint::advanceWriteIndex(int32_t deltaFrames) {
213     mDataQueue->advanceWriteIndex(deltaFrames);
214 }
215 
advanceReadIndex(int32_t deltaFrames)216 void AudioEndpoint::advanceReadIndex(int32_t deltaFrames) {
217     mDataQueue->advanceReadIndex(deltaFrames);
218 }
219 
setDataReadCounter(fifo_counter_t framesRead)220 void AudioEndpoint::setDataReadCounter(fifo_counter_t framesRead)
221 {
222     mDataQueue->setReadCounter(framesRead);
223 }
224 
getDataReadCounter()225 fifo_counter_t AudioEndpoint::getDataReadCounter()
226 {
227     return mDataQueue->getReadCounter();
228 }
229 
setDataWriteCounter(fifo_counter_t framesRead)230 void AudioEndpoint::setDataWriteCounter(fifo_counter_t framesRead)
231 {
232     mDataQueue->setWriteCounter(framesRead);
233 }
234 
getDataWriteCounter()235 fifo_counter_t AudioEndpoint::getDataWriteCounter()
236 {
237     return mDataQueue->getWriteCounter();
238 }
239 
setBufferSizeInFrames(int32_t requestedFrames,int32_t * actualFrames)240 int32_t AudioEndpoint::setBufferSizeInFrames(int32_t requestedFrames,
241                                             int32_t *actualFrames)
242 {
243     if (requestedFrames < ENDPOINT_DATA_QUEUE_SIZE_MIN) {
244         requestedFrames = ENDPOINT_DATA_QUEUE_SIZE_MIN;
245     }
246     mDataQueue->setThreshold(requestedFrames);
247     *actualFrames = mDataQueue->getThreshold();
248     return AAUDIO_OK;
249 }
250 
getBufferSizeInFrames() const251 int32_t AudioEndpoint::getBufferSizeInFrames() const
252 {
253     return mDataQueue->getThreshold();
254 }
255 
getBufferCapacityInFrames() const256 int32_t AudioEndpoint::getBufferCapacityInFrames() const
257 {
258     return (int32_t)mDataQueue->getBufferCapacityInFrames();
259 }
260 
dump() const261 void AudioEndpoint::dump() const {
262     ALOGD("data readCounter  = %lld", (long long) mDataQueue->getReadCounter());
263     ALOGD("data writeCounter = %lld", (long long) mDataQueue->getWriteCounter());
264 }
265 
eraseDataMemory()266 void AudioEndpoint::eraseDataMemory() {
267     mDataQueue->eraseMemory();
268 }
269