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