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