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 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 static aaudio_result_t AudioEndpoint_validateQueueDescriptor(const char *type, 49 const RingBufferDescriptor *descriptor) { 50 if (descriptor == nullptr) { 51 ALOGE("AudioEndpoint_validateQueueDescriptor() NULL descriptor"); 52 return AAUDIO_ERROR_NULL; 53 } 54 55 if (descriptor->capacityInFrames < 1 56 || descriptor->capacityInFrames > RIDICULOUSLY_LARGE_BUFFER_CAPACITY) { 57 ALOGE("AudioEndpoint_validateQueueDescriptor() bad capacityInFrames = %d", 58 descriptor->capacityInFrames); 59 return AAUDIO_ERROR_OUT_OF_RANGE; 60 } 61 62 // Reject extreme values to catch bugs and prevent numeric overflows. 63 if (descriptor->bytesPerFrame < 1 64 || descriptor->bytesPerFrame > RIDICULOUSLY_LARGE_FRAME_SIZE) { 65 ALOGE("AudioEndpoint_validateQueueDescriptor() bad bytesPerFrame = %d", 66 descriptor->bytesPerFrame); 67 return AAUDIO_ERROR_OUT_OF_RANGE; 68 } 69 70 if (descriptor->dataAddress == nullptr) { 71 ALOGE("AudioEndpoint_validateQueueDescriptor() NULL dataAddress"); 72 return AAUDIO_ERROR_NULL; 73 } 74 ALOGV("AudioEndpoint_validateQueueDescriptor %s, dataAddress at %p ====================", 75 type, 76 descriptor->dataAddress); 77 ALOGV("AudioEndpoint_validateQueueDescriptor readCounter at %p, writeCounter at %p", 78 descriptor->readCounterAddress, 79 descriptor->writeCounterAddress); 80 81 // Try to READ from the data area. 82 // This code will crash if the mmap failed. 83 uint8_t value = descriptor->dataAddress[0]; 84 ALOGV("AudioEndpoint_validateQueueDescriptor() dataAddress[0] = %d, then try to write", 85 (int) value); 86 // Try to WRITE to the data area. 87 descriptor->dataAddress[0] = value * 3; 88 ALOGV("AudioEndpoint_validateQueueDescriptor() wrote successfully"); 89 90 if (descriptor->readCounterAddress) { 91 fifo_counter_t counter = *descriptor->readCounterAddress; 92 ALOGV("AudioEndpoint_validateQueueDescriptor() *readCounterAddress = %d, now write", 93 (int) counter); 94 *descriptor->readCounterAddress = counter; 95 ALOGV("AudioEndpoint_validateQueueDescriptor() wrote readCounterAddress successfully"); 96 } 97 98 if (descriptor->writeCounterAddress) { 99 fifo_counter_t counter = *descriptor->writeCounterAddress; 100 ALOGV("AudioEndpoint_validateQueueDescriptor() *writeCounterAddress = %d, now write", 101 (int) counter); 102 *descriptor->writeCounterAddress = counter; 103 ALOGV("AudioEndpoint_validateQueueDescriptor() wrote writeCounterAddress successfully"); 104 } 105 106 return AAUDIO_OK; 107 } 108 109 aaudio_result_t AudioEndpoint_validateDescriptor(const EndpointDescriptor *pEndpointDescriptor) { 110 aaudio_result_t result = AudioEndpoint_validateQueueDescriptor("messages", 111 &pEndpointDescriptor->upMessageQueueDescriptor); 112 if (result == AAUDIO_OK) { 113 result = AudioEndpoint_validateQueueDescriptor("data", 114 &pEndpointDescriptor->dataQueueDescriptor); 115 } 116 return result; 117 } 118 119 aaudio_result_t AudioEndpoint::configure(const EndpointDescriptor *pEndpointDescriptor, 120 aaudio_direction_t direction) 121 { 122 aaudio_result_t result = AudioEndpoint_validateDescriptor(pEndpointDescriptor); 123 if (result != AAUDIO_OK) { 124 return result; 125 } 126 127 // ============================ up message queue ============================= 128 const RingBufferDescriptor *descriptor = &pEndpointDescriptor->upMessageQueueDescriptor; 129 if(descriptor->bytesPerFrame != sizeof(AAudioServiceMessage)) { 130 ALOGE("AudioEndpoint.configure() bytesPerFrame != sizeof(AAudioServiceMessage) = %d", 131 descriptor->bytesPerFrame); 132 return AAUDIO_ERROR_INTERNAL; 133 } 134 135 if(descriptor->readCounterAddress == nullptr || descriptor->writeCounterAddress == nullptr) { 136 ALOGE("AudioEndpoint.configure() NULL counter address"); 137 return AAUDIO_ERROR_NULL; 138 } 139 140 // Prevent memory leak and reuse. 141 if(mUpCommandQueue != nullptr || mDataQueue != nullptr) { 142 ALOGE("AudioEndpoint.configure() endpoint already used"); 143 return AAUDIO_ERROR_INTERNAL; 144 } 145 146 mUpCommandQueue = new FifoBuffer( 147 descriptor->bytesPerFrame, 148 descriptor->capacityInFrames, 149 descriptor->readCounterAddress, 150 descriptor->writeCounterAddress, 151 descriptor->dataAddress 152 ); 153 154 // ============================ data queue ============================= 155 descriptor = &pEndpointDescriptor->dataQueueDescriptor; 156 ALOGV("AudioEndpoint.configure() data framesPerBurst = %d", descriptor->framesPerBurst); 157 ALOGV("AudioEndpoint.configure() data readCounterAddress = %p", 158 descriptor->readCounterAddress); 159 160 // An example of free running is when the other side is read or written by hardware DMA 161 // or a DSP. It does not update its counter so we have to update it. 162 int64_t *remoteCounter = (direction == AAUDIO_DIRECTION_OUTPUT) 163 ? descriptor->readCounterAddress // read by other side 164 : descriptor->writeCounterAddress; // written by other side 165 mFreeRunning = (remoteCounter == nullptr); 166 ALOGV("AudioEndpoint.configure() mFreeRunning = %d", mFreeRunning ? 1 : 0); 167 168 int64_t *readCounterAddress = (descriptor->readCounterAddress == nullptr) 169 ? &mDataReadCounter 170 : descriptor->readCounterAddress; 171 int64_t *writeCounterAddress = (descriptor->writeCounterAddress == nullptr) 172 ? &mDataWriteCounter 173 : descriptor->writeCounterAddress; 174 175 mDataQueue = new FifoBuffer( 176 descriptor->bytesPerFrame, 177 descriptor->capacityInFrames, 178 readCounterAddress, 179 writeCounterAddress, 180 descriptor->dataAddress 181 ); 182 uint32_t threshold = descriptor->capacityInFrames / 2; 183 mDataQueue->setThreshold(threshold); 184 return result; 185 } 186 187 aaudio_result_t AudioEndpoint::readUpCommand(AAudioServiceMessage *commandPtr) 188 { 189 return mUpCommandQueue->read(commandPtr, 1); 190 } 191 192 int32_t AudioEndpoint::getEmptyFramesAvailable(WrappingBuffer *wrappingBuffer) { 193 return mDataQueue->getEmptyRoomAvailable(wrappingBuffer); 194 } 195 196 int32_t AudioEndpoint::getEmptyFramesAvailable() 197 { 198 return mDataQueue->getFifoControllerBase()->getEmptyFramesAvailable(); 199 } 200 201 int32_t AudioEndpoint::getFullFramesAvailable(WrappingBuffer *wrappingBuffer) 202 { 203 return mDataQueue->getFullDataAvailable(wrappingBuffer); 204 } 205 206 int32_t AudioEndpoint::getFullFramesAvailable() 207 { 208 return mDataQueue->getFifoControllerBase()->getFullFramesAvailable(); 209 } 210 211 void AudioEndpoint::advanceWriteIndex(int32_t deltaFrames) { 212 mDataQueue->getFifoControllerBase()->advanceWriteIndex(deltaFrames); 213 } 214 215 void AudioEndpoint::advanceReadIndex(int32_t deltaFrames) { 216 mDataQueue->getFifoControllerBase()->advanceReadIndex(deltaFrames); 217 } 218 219 void AudioEndpoint::setDataReadCounter(fifo_counter_t framesRead) 220 { 221 mDataQueue->setReadCounter(framesRead); 222 } 223 224 fifo_counter_t AudioEndpoint::getDataReadCounter() 225 { 226 return mDataQueue->getReadCounter(); 227 } 228 229 void AudioEndpoint::setDataWriteCounter(fifo_counter_t framesRead) 230 { 231 mDataQueue->setWriteCounter(framesRead); 232 } 233 234 fifo_counter_t AudioEndpoint::getDataWriteCounter() 235 { 236 return mDataQueue->getWriteCounter(); 237 } 238 239 int32_t AudioEndpoint::setBufferSizeInFrames(int32_t requestedFrames, 240 int32_t *actualFrames) 241 { 242 if (requestedFrames < ENDPOINT_DATA_QUEUE_SIZE_MIN) { 243 requestedFrames = ENDPOINT_DATA_QUEUE_SIZE_MIN; 244 } 245 mDataQueue->setThreshold(requestedFrames); 246 *actualFrames = mDataQueue->getThreshold(); 247 return AAUDIO_OK; 248 } 249 250 int32_t AudioEndpoint::getBufferSizeInFrames() const 251 { 252 return mDataQueue->getThreshold(); 253 } 254 255 int32_t AudioEndpoint::getBufferCapacityInFrames() const 256 { 257 return (int32_t)mDataQueue->getBufferCapacityInFrames(); 258 } 259 260 void AudioEndpoint::dump() const { 261 ALOGD("AudioEndpoint: data readCounter = %lld", (long long) mDataQueue->getReadCounter()); 262 ALOGD("AudioEndpoint: data writeCounter = %lld", (long long) mDataQueue->getWriteCounter()); 263 } 264 265 void AudioEndpoint::eraseDataMemory() { 266 mDataQueue->eraseMemory(); 267 } 268