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