• 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 
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