Home | History | Annotate | Download | only in client
      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