blob: fe049b2c4cdc9d7510e8af3ad5eee8599218a983 [file] [log] [blame]
Phil Burk204a1632017-01-03 17:23:43 -08001/*
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
Phil Burk5ed503c2017-02-01 09:38:15 -080017#define LOG_TAG "AAudio"
Phil Burk204a1632017-01-03 17:23:43 -080018//#define LOG_NDEBUG 0
19#include <utils/Log.h>
20
21#include <cassert>
Phil Burke4d7bb42017-03-28 11:32:39 -070022#include <aaudio/AAudio.h>
Phil Burk204a1632017-01-03 17:23:43 -080023
24#include "AudioEndpointParcelable.h"
25#include "AudioEndpoint.h"
Phil Burk5ed503c2017-02-01 09:38:15 -080026#include "AAudioServiceMessage.h"
Phil Burk204a1632017-01-03 17:23:43 -080027
28using namespace android;
Phil Burk5ed503c2017-02-01 09:38:15 -080029using namespace aaudio;
Phil Burk204a1632017-01-03 17:23:43 -080030
31AudioEndpoint::AudioEndpoint()
32 : mOutputFreeRunning(false)
33 , mDataReadCounter(0)
34 , mDataWriteCounter(0)
35{
36}
37
38AudioEndpoint::~AudioEndpoint()
39{
40}
41
Phil Burkc0c70e32017-02-09 13:18:38 -080042static aaudio_result_t AudioEndpoint_validateQueueDescriptor(const char *type,
Phil Burk204a1632017-01-03 17:23:43 -080043 const RingBufferDescriptor *descriptor) {
Phil Burkc0c70e32017-02-09 13:18:38 -080044 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 }
Phil Burk204a1632017-01-03 17:23:43 -080062 ALOGD("AudioEndpoint_validateQueueDescriptor %s, dataAddress at %p ====================",
63 type,
64 descriptor->dataAddress);
65 ALOGD("AudioEndpoint_validateQueueDescriptor readCounter at %p, writeCounter at %p",
66 descriptor->readCounterAddress,
67 descriptor->writeCounterAddress);
68
69 // Try to READ from the data area.
Phil Burkc0c70e32017-02-09 13:18:38 -080070 // This code will crash if the mmap failed.
Phil Burk204a1632017-01-03 17:23:43 -080071 uint8_t value = descriptor->dataAddress[0];
72 ALOGD("AudioEndpoint_validateQueueDescriptor() dataAddress[0] = %d, then try to write",
73 (int) value);
74 // Try to WRITE to the data area.
Phil Burkc0c70e32017-02-09 13:18:38 -080075 descriptor->dataAddress[0] = value * 3;
Phil Burk204a1632017-01-03 17:23:43 -080076 ALOGD("AudioEndpoint_validateQueueDescriptor() wrote successfully");
77
78 if (descriptor->readCounterAddress) {
79 fifo_counter_t counter = *descriptor->readCounterAddress;
80 ALOGD("AudioEndpoint_validateQueueDescriptor() *readCounterAddress = %d, now write",
81 (int) counter);
82 *descriptor->readCounterAddress = counter;
83 ALOGD("AudioEndpoint_validateQueueDescriptor() wrote readCounterAddress successfully");
84 }
85 if (descriptor->writeCounterAddress) {
86 fifo_counter_t counter = *descriptor->writeCounterAddress;
87 ALOGD("AudioEndpoint_validateQueueDescriptor() *writeCounterAddress = %d, now write",
88 (int) counter);
89 *descriptor->writeCounterAddress = counter;
90 ALOGD("AudioEndpoint_validateQueueDescriptor() wrote writeCounterAddress successfully");
91 }
Phil Burkc0c70e32017-02-09 13:18:38 -080092 return AAUDIO_OK;
Phil Burk204a1632017-01-03 17:23:43 -080093}
94
Phil Burkc0c70e32017-02-09 13:18:38 -080095aaudio_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;
Phil Burk204a1632017-01-03 17:23:43 -0800103}
104
Phil Burk5ed503c2017-02-01 09:38:15 -0800105aaudio_result_t AudioEndpoint::configure(const EndpointDescriptor *pEndpointDescriptor)
Phil Burk204a1632017-01-03 17:23:43 -0800106{
Phil Burkc0c70e32017-02-09 13:18:38 -0800107 // TODO maybe remove after debugging
108 aaudio_result_t result = AudioEndpoint_validateDescriptor(pEndpointDescriptor);
109 if (result != AAUDIO_OK) {
110 ALOGD("AudioEndpoint_validateQueueDescriptor returned %d %s",
111 result, AAudio_convertResultToText(result));
112 return result;
113 }
Phil Burk204a1632017-01-03 17:23:43 -0800114
115 const RingBufferDescriptor *descriptor = &pEndpointDescriptor->upMessageQueueDescriptor;
Phil Burk5ed503c2017-02-01 09:38:15 -0800116 assert(descriptor->bytesPerFrame == sizeof(AAudioServiceMessage));
Phil Burk204a1632017-01-03 17:23:43 -0800117 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 ALOGD("AudioEndpoint::configure() data framesPerBurst = %d", descriptor->framesPerBurst);
146 ALOGD("AudioEndpoint::configure() data readCounterAddress = %p", descriptor->readCounterAddress);
147 mOutputFreeRunning = descriptor->readCounterAddress == nullptr;
148 ALOGD("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;
Phil Burkc0c70e32017-02-09 13:18:38 -0800155
Phil Burk204a1632017-01-03 17:23:43 -0800156 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
Phil Burk5ed503c2017-02-01 09:38:15 -0800168aaudio_result_t AudioEndpoint::readUpCommand(AAudioServiceMessage *commandPtr)
Phil Burk204a1632017-01-03 17:23:43 -0800169{
170 return mUpCommandQueue->read(commandPtr, 1);
171}
172
Phil Burk5ed503c2017-02-01 09:38:15 -0800173aaudio_result_t AudioEndpoint::writeDataNow(const void *buffer, int32_t numFrames)
Phil Burk204a1632017-01-03 17:23:43 -0800174{
Phil Burkc0c70e32017-02-09 13:18:38 -0800175 // 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.
Phil Burk204a1632017-01-03 17:23:43 -0800177 return mDownDataQueue->write(buffer, numFrames);
178}
179
Phil Burkc0c70e32017-02-09 13:18:38 -0800180void AudioEndpoint::getEmptyRoomAvailable(WrappingBuffer *wrappingBuffer) {
181 mDownDataQueue->getEmptyRoomAvailable(wrappingBuffer);
182}
183
184void AudioEndpoint::advanceWriteIndex(int32_t deltaFrames) {
185 mDownDataQueue->getFifoControllerBase()->advanceWriteIndex(deltaFrames);
186}
187
Phil Burk204a1632017-01-03 17:23:43 -0800188void 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
Phil Burk3316d5e2017-02-15 11:23:01 -0800208int32_t AudioEndpoint::setBufferSizeInFrames(int32_t requestedFrames,
209 int32_t *actualFrames)
Phil Burk204a1632017-01-03 17:23:43 -0800210{
211 if (requestedFrames < ENDPOINT_DATA_QUEUE_SIZE_MIN) {
212 requestedFrames = ENDPOINT_DATA_QUEUE_SIZE_MIN;
213 }
214 mDownDataQueue->setThreshold(requestedFrames);
215 *actualFrames = mDownDataQueue->getThreshold();
Phil Burk5ed503c2017-02-01 09:38:15 -0800216 return AAUDIO_OK;
Phil Burk204a1632017-01-03 17:23:43 -0800217}
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}