AudioEndpoint.cpp revision 71f35bb687476694882a617ba4a810a0bb56fe23
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
31AudioEndpoint::AudioEndpoint()
32    : mOutputFreeRunning(false)
33    , mDataReadCounter(0)
34    , mDataWriteCounter(0)
35{
36}
37
38AudioEndpoint::~AudioEndpoint()
39{
40}
41
42static 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    if (descriptor->capacityInFrames <= 0) {
49        ALOGE("AudioEndpoint_validateQueueDescriptor() bad capacityInFrames = %d",
50              descriptor->capacityInFrames);
51        return AAUDIO_ERROR_OUT_OF_RANGE;
52    }
53    if (descriptor->bytesPerFrame <= 1) {
54        ALOGE("AudioEndpoint_validateQueueDescriptor() bad bytesPerFrame = %d",
55              descriptor->bytesPerFrame);
56        return AAUDIO_ERROR_OUT_OF_RANGE;
57    }
58    if (descriptor->dataAddress == nullptr) {
59        ALOGE("AudioEndpoint_validateQueueDescriptor() NULL dataAddress");
60        return AAUDIO_ERROR_NULL;
61    }
62    ALOGV("AudioEndpoint_validateQueueDescriptor %s, dataAddress at %p ====================",
63          type,
64          descriptor->dataAddress);
65    ALOGV("AudioEndpoint_validateQueueDescriptor  readCounter at %p, writeCounter at %p",
66          descriptor->readCounterAddress,
67          descriptor->writeCounterAddress);
68
69    // Try to READ from the data area.
70    // This code will crash if the mmap failed.
71    uint8_t value = descriptor->dataAddress[0];
72    ALOGV("AudioEndpoint_validateQueueDescriptor() dataAddress[0] = %d, then try to write",
73        (int) value);
74    // Try to WRITE to the data area.
75    descriptor->dataAddress[0] = value * 3;
76    ALOGV("AudioEndpoint_validateQueueDescriptor() wrote successfully");
77
78    if (descriptor->readCounterAddress) {
79        fifo_counter_t counter = *descriptor->readCounterAddress;
80        ALOGV("AudioEndpoint_validateQueueDescriptor() *readCounterAddress = %d, now write",
81              (int) counter);
82        *descriptor->readCounterAddress = counter;
83        ALOGV("AudioEndpoint_validateQueueDescriptor() wrote readCounterAddress successfully");
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    return AAUDIO_OK;
93}
94
95aaudio_result_t AudioEndpoint_validateDescriptor(const EndpointDescriptor *pEndpointDescriptor) {
96    aaudio_result_t result = AudioEndpoint_validateQueueDescriptor("messages",
97                                    &pEndpointDescriptor->upMessageQueueDescriptor);
98    if (result == AAUDIO_OK) {
99        result = AudioEndpoint_validateQueueDescriptor("data",
100                                                &pEndpointDescriptor->downDataQueueDescriptor);
101    }
102    return result;
103}
104
105aaudio_result_t AudioEndpoint::configure(const EndpointDescriptor *pEndpointDescriptor)
106{
107    // TODO maybe remove after debugging
108    aaudio_result_t result = AudioEndpoint_validateDescriptor(pEndpointDescriptor);
109    if (result != AAUDIO_OK) {
110        ALOGE("AudioEndpoint_validateQueueDescriptor returned %d %s",
111              result, AAudio_convertResultToText(result));
112        return result;
113    }
114
115    const RingBufferDescriptor *descriptor = &pEndpointDescriptor->upMessageQueueDescriptor;
116    assert(descriptor->bytesPerFrame == sizeof(AAudioServiceMessage));
117    assert(descriptor->readCounterAddress != nullptr);
118    assert(descriptor->writeCounterAddress != nullptr);
119    mUpCommandQueue = new FifoBuffer(
120            descriptor->bytesPerFrame,
121            descriptor->capacityInFrames,
122            descriptor->readCounterAddress,
123            descriptor->writeCounterAddress,
124            descriptor->dataAddress
125    );
126    /* TODO mDownCommandQueue
127    if (descriptor->capacityInFrames > 0) {
128        descriptor = &pEndpointDescriptor->downMessageQueueDescriptor;
129        mDownCommandQueue = new FifoBuffer(
130                descriptor->capacityInFrames,
131                descriptor->bytesPerFrame,
132                descriptor->readCounterAddress,
133                descriptor->writeCounterAddress,
134                descriptor->dataAddress
135        );
136    }
137     */
138    descriptor = &pEndpointDescriptor->downDataQueueDescriptor;
139    assert(descriptor->capacityInFrames > 0);
140    assert(descriptor->bytesPerFrame > 1);
141    assert(descriptor->bytesPerFrame < 4 * 16); // FIXME just for initial debugging
142    assert(descriptor->framesPerBurst > 0);
143    assert(descriptor->framesPerBurst < 8 * 1024); // FIXME just for initial debugging
144    assert(descriptor->dataAddress != nullptr);
145    ALOGV("AudioEndpoint::configure() data framesPerBurst = %d", descriptor->framesPerBurst);
146    ALOGV("AudioEndpoint::configure() data readCounterAddress = %p", descriptor->readCounterAddress);
147    mOutputFreeRunning = descriptor->readCounterAddress == nullptr;
148    ALOGV("AudioEndpoint::configure() mOutputFreeRunning = %d", mOutputFreeRunning ? 1 : 0);
149    int64_t *readCounterAddress = (descriptor->readCounterAddress == nullptr)
150                                  ? &mDataReadCounter
151                                  : descriptor->readCounterAddress;
152    int64_t *writeCounterAddress = (descriptor->writeCounterAddress == nullptr)
153                                  ? &mDataWriteCounter
154                                  : descriptor->writeCounterAddress;
155
156    mDownDataQueue = new FifoBuffer(
157            descriptor->bytesPerFrame,
158            descriptor->capacityInFrames,
159            readCounterAddress,
160            writeCounterAddress,
161            descriptor->dataAddress
162    );
163    uint32_t threshold = descriptor->capacityInFrames / 2;
164    mDownDataQueue->setThreshold(threshold);
165    return result;
166}
167
168aaudio_result_t AudioEndpoint::readUpCommand(AAudioServiceMessage *commandPtr)
169{
170    return mUpCommandQueue->read(commandPtr, 1);
171}
172
173aaudio_result_t AudioEndpoint::writeDataNow(const void *buffer, int32_t numFrames)
174{
175    // TODO Make it easier for the AAudioStreamInternal to scale floats and write shorts
176    // TODO Similar to block adapter write through technique. Add a DataConverter.
177    return mDownDataQueue->write(buffer, numFrames);
178}
179
180void AudioEndpoint::getEmptyRoomAvailable(WrappingBuffer *wrappingBuffer) {
181    mDownDataQueue->getEmptyRoomAvailable(wrappingBuffer);
182}
183
184void AudioEndpoint::advanceWriteIndex(int32_t deltaFrames) {
185    mDownDataQueue->getFifoControllerBase()->advanceWriteIndex(deltaFrames);
186}
187
188void AudioEndpoint::setDownDataReadCounter(fifo_counter_t framesRead)
189{
190    mDownDataQueue->setReadCounter(framesRead);
191}
192
193fifo_counter_t AudioEndpoint::getDownDataReadCounter()
194{
195    return mDownDataQueue->getReadCounter();
196}
197
198void AudioEndpoint::setDownDataWriteCounter(fifo_counter_t framesRead)
199{
200    mDownDataQueue->setWriteCounter(framesRead);
201}
202
203fifo_counter_t AudioEndpoint::getDownDataWriteCounter()
204{
205    return mDownDataQueue->getWriteCounter();
206}
207
208int32_t AudioEndpoint::setBufferSizeInFrames(int32_t requestedFrames,
209                                            int32_t *actualFrames)
210{
211    if (requestedFrames < ENDPOINT_DATA_QUEUE_SIZE_MIN) {
212        requestedFrames = ENDPOINT_DATA_QUEUE_SIZE_MIN;
213    }
214    mDownDataQueue->setThreshold(requestedFrames);
215    *actualFrames = mDownDataQueue->getThreshold();
216    return AAUDIO_OK;
217}
218
219int32_t AudioEndpoint::getBufferSizeInFrames() const
220{
221    return mDownDataQueue->getThreshold();
222}
223
224int32_t AudioEndpoint::getBufferCapacityInFrames() const
225{
226    return (int32_t)mDownDataQueue->getBufferCapacityInFrames();
227}
228
229int32_t AudioEndpoint::getFullFramesAvailable()
230{
231    return mDownDataQueue->getFifoControllerBase()->getFullFramesAvailable();
232}
233