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