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
28using namespace android;
29using namespace aaudio;
30
31#define RIDICULOUSLY_LARGE_BUFFER_CAPACITY   (256 * 1024)
32#define RIDICULOUSLY_LARGE_FRAME_SIZE        4096
33
34AudioEndpoint::AudioEndpoint()
35    : mUpCommandQueue(nullptr)
36    , mDataQueue(nullptr)
37    , mFreeRunning(false)
38    , mDataReadCounter(0)
39    , mDataWriteCounter(0)
40{
41}
42
43AudioEndpoint::~AudioEndpoint() {
44    delete mDataQueue;
45    delete mUpCommandQueue;
46}
47
48// TODO Consider moving to a method in RingBufferDescriptor
49static 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
110aaudio_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
120aaudio_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
188aaudio_result_t AudioEndpoint::readUpCommand(AAudioServiceMessage *commandPtr)
189{
190    return mUpCommandQueue->read(commandPtr, 1);
191}
192
193int32_t AudioEndpoint::getEmptyFramesAvailable(WrappingBuffer *wrappingBuffer) {
194    return mDataQueue->getEmptyRoomAvailable(wrappingBuffer);
195}
196
197int32_t AudioEndpoint::getEmptyFramesAvailable()
198{
199    return mDataQueue->getFifoControllerBase()->getEmptyFramesAvailable();
200}
201
202int32_t AudioEndpoint::getFullFramesAvailable(WrappingBuffer *wrappingBuffer)
203{
204    return mDataQueue->getFullDataAvailable(wrappingBuffer);
205}
206
207int32_t AudioEndpoint::getFullFramesAvailable()
208{
209    return mDataQueue->getFifoControllerBase()->getFullFramesAvailable();
210}
211
212void AudioEndpoint::advanceWriteIndex(int32_t deltaFrames) {
213    mDataQueue->getFifoControllerBase()->advanceWriteIndex(deltaFrames);
214}
215
216void AudioEndpoint::advanceReadIndex(int32_t deltaFrames) {
217    mDataQueue->getFifoControllerBase()->advanceReadIndex(deltaFrames);
218}
219
220void AudioEndpoint::setDataReadCounter(fifo_counter_t framesRead)
221{
222    mDataQueue->setReadCounter(framesRead);
223}
224
225fifo_counter_t AudioEndpoint::getDataReadCounter()
226{
227    return mDataQueue->getReadCounter();
228}
229
230void AudioEndpoint::setDataWriteCounter(fifo_counter_t framesRead)
231{
232    mDataQueue->setWriteCounter(framesRead);
233}
234
235fifo_counter_t AudioEndpoint::getDataWriteCounter()
236{
237    return mDataQueue->getWriteCounter();
238}
239
240int32_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
251int32_t AudioEndpoint::getBufferSizeInFrames() const
252{
253    return mDataQueue->getThreshold();
254}
255
256int32_t AudioEndpoint::getBufferCapacityInFrames() const
257{
258    return (int32_t)mDataQueue->getBufferCapacityInFrames();
259}
260
261void AudioEndpoint::dump() const {
262    ALOGD("data readCounter  = %lld", (long long) mDataQueue->getReadCounter());
263    ALOGD("data writeCounter = %lld", (long long) mDataQueue->getWriteCounter());
264}
265
266void AudioEndpoint::eraseDataMemory() {
267    mDataQueue->eraseMemory();
268}
269