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