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
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    : mFreeRunning(false)
36    , mDataReadCounter(0)
37    , mDataWriteCounter(0)
38{
39}
40
41AudioEndpoint::~AudioEndpoint()
42{
43}
44
45static 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
106aaudio_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
116aaudio_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
171aaudio_result_t AudioEndpoint::readUpCommand(AAudioServiceMessage *commandPtr)
172{
173    return mUpCommandQueue->read(commandPtr, 1);
174}
175
176aaudio_result_t AudioEndpoint::writeDataNow(const void *buffer, int32_t numFrames)
177{
178    return mDataQueue->write(buffer, numFrames);
179}
180
181void AudioEndpoint::getEmptyFramesAvailable(WrappingBuffer *wrappingBuffer) {
182    mDataQueue->getEmptyRoomAvailable(wrappingBuffer);
183}
184
185int32_t AudioEndpoint::getEmptyFramesAvailable()
186{
187    return mDataQueue->getFifoControllerBase()->getEmptyFramesAvailable();
188}
189
190void AudioEndpoint::getFullFramesAvailable(WrappingBuffer *wrappingBuffer)
191{
192    return mDataQueue->getFullDataAvailable(wrappingBuffer);
193}
194
195int32_t AudioEndpoint::getFullFramesAvailable()
196{
197    return mDataQueue->getFifoControllerBase()->getFullFramesAvailable();
198}
199
200void AudioEndpoint::advanceWriteIndex(int32_t deltaFrames) {
201    mDataQueue->getFifoControllerBase()->advanceWriteIndex(deltaFrames);
202}
203
204void AudioEndpoint::advanceReadIndex(int32_t deltaFrames) {
205    mDataQueue->getFifoControllerBase()->advanceReadIndex(deltaFrames);
206}
207
208void AudioEndpoint::setDataReadCounter(fifo_counter_t framesRead)
209{
210    mDataQueue->setReadCounter(framesRead);
211}
212
213fifo_counter_t AudioEndpoint::getDataReadCounter()
214{
215    return mDataQueue->getReadCounter();
216}
217
218void AudioEndpoint::setDataWriteCounter(fifo_counter_t framesRead)
219{
220    mDataQueue->setWriteCounter(framesRead);
221}
222
223fifo_counter_t AudioEndpoint::getDataWriteCounter()
224{
225    return mDataQueue->getWriteCounter();
226}
227
228int32_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
239int32_t AudioEndpoint::getBufferSizeInFrames() const
240{
241    return mDataQueue->getThreshold();
242}
243
244int32_t AudioEndpoint::getBufferCapacityInFrames() const
245{
246    return (int32_t)mDataQueue->getBufferCapacityInFrames();
247}
248
249