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 "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