Home | History | Annotate | Download | only in oboeservice
      1 /*
      2  * Copyright (C) 2017 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 "AAudioServiceStreamShared"
     18 //#define LOG_NDEBUG 0
     19 #include <utils/Log.h>
     20 
     21 #include <iomanip>
     22 #include <iostream>
     23 #include <mutex>
     24 
     25 #include <aaudio/AAudio.h>
     26 
     27 #include "binding/IAAudioService.h"
     28 
     29 #include "binding/AAudioServiceMessage.h"
     30 #include "AAudioServiceStreamBase.h"
     31 #include "AAudioServiceStreamShared.h"
     32 #include "AAudioEndpointManager.h"
     33 #include "AAudioService.h"
     34 #include "AAudioServiceEndpoint.h"
     35 
     36 using namespace android;
     37 using namespace aaudio;
     38 
     39 #define MIN_BURSTS_PER_BUFFER       2
     40 #define DEFAULT_BURSTS_PER_BUFFER   16
     41 // This is an arbitrary range. TODO review.
     42 #define MAX_FRAMES_PER_BUFFER       (32 * 1024)
     43 
     44 AAudioServiceStreamShared::AAudioServiceStreamShared(AAudioService &audioService)
     45     : AAudioServiceStreamBase(audioService)
     46     , mTimestampPositionOffset(0)
     47     , mXRunCount(0) {
     48 }
     49 
     50 std::string AAudioServiceStreamShared::dumpHeader() {
     51     std::stringstream result;
     52     result << AAudioServiceStreamBase::dumpHeader();
     53     result << "    Write#     Read#   Avail   XRuns";
     54     return result.str();
     55 }
     56 
     57 std::string AAudioServiceStreamShared::dump() const {
     58     std::stringstream result;
     59 
     60     result << AAudioServiceStreamBase::dump();
     61 
     62     auto fifo = mAudioDataQueue->getFifoBuffer();
     63     int32_t readCounter = fifo->getReadCounter();
     64     int32_t writeCounter = fifo->getWriteCounter();
     65     result << std::setw(10) << writeCounter;
     66     result << std::setw(10) << readCounter;
     67     result << std::setw(8) << (writeCounter - readCounter);
     68     result << std::setw(8) << getXRunCount();
     69 
     70     return result.str();
     71 }
     72 
     73 int32_t AAudioServiceStreamShared::calculateBufferCapacity(int32_t requestedCapacityFrames,
     74                                                            int32_t framesPerBurst) {
     75 
     76     if (requestedCapacityFrames > MAX_FRAMES_PER_BUFFER) {
     77         ALOGE("calculateBufferCapacity() requested capacity %d > max %d",
     78               requestedCapacityFrames, MAX_FRAMES_PER_BUFFER);
     79         return AAUDIO_ERROR_OUT_OF_RANGE;
     80     }
     81 
     82     // Determine how many bursts will fit in the buffer.
     83     int32_t numBursts;
     84     if (requestedCapacityFrames == AAUDIO_UNSPECIFIED) {
     85         // Use fewer bursts if default is too many.
     86         if ((DEFAULT_BURSTS_PER_BUFFER * framesPerBurst) > MAX_FRAMES_PER_BUFFER) {
     87             numBursts = MAX_FRAMES_PER_BUFFER / framesPerBurst;
     88         } else {
     89             numBursts = DEFAULT_BURSTS_PER_BUFFER;
     90         }
     91     } else {
     92         // round up to nearest burst boundary
     93         numBursts = (requestedCapacityFrames + framesPerBurst - 1) / framesPerBurst;
     94     }
     95 
     96     // Clip to bare minimum.
     97     if (numBursts < MIN_BURSTS_PER_BUFFER) {
     98         numBursts = MIN_BURSTS_PER_BUFFER;
     99     }
    100     // Check for numeric overflow.
    101     if (numBursts > 0x8000 || framesPerBurst > 0x8000) {
    102         ALOGE("calculateBufferCapacity() overflow, capacity = %d * %d",
    103               numBursts, framesPerBurst);
    104         return AAUDIO_ERROR_OUT_OF_RANGE;
    105     }
    106     int32_t capacityInFrames = numBursts * framesPerBurst;
    107 
    108     // Final sanity check.
    109     if (capacityInFrames > MAX_FRAMES_PER_BUFFER) {
    110         ALOGE("calculateBufferCapacity() calc capacity %d > max %d",
    111               capacityInFrames, MAX_FRAMES_PER_BUFFER);
    112         return AAUDIO_ERROR_OUT_OF_RANGE;
    113     }
    114     ALOGV("calculateBufferCapacity() requested %d frames, actual = %d",
    115           requestedCapacityFrames, capacityInFrames);
    116     return capacityInFrames;
    117 }
    118 
    119 aaudio_result_t AAudioServiceStreamShared::open(const aaudio::AAudioStreamRequest &request)  {
    120 
    121     sp<AAudioServiceStreamShared> keep(this);
    122 
    123     if (request.getConstantConfiguration().getSharingMode() != AAUDIO_SHARING_MODE_SHARED) {
    124         ALOGE("%s() sharingMode mismatch %d", __func__,
    125               request.getConstantConfiguration().getSharingMode());
    126         return AAUDIO_ERROR_INTERNAL;
    127     }
    128 
    129     aaudio_result_t result = AAudioServiceStreamBase::open(request);
    130     if (result != AAUDIO_OK) {
    131         return result;
    132     }
    133 
    134     const AAudioStreamConfiguration &configurationInput = request.getConstantConfiguration();
    135 
    136     sp<AAudioServiceEndpoint> endpoint = mServiceEndpointWeak.promote();
    137     if (endpoint == nullptr) {
    138         result = AAUDIO_ERROR_INVALID_STATE;
    139         goto error;
    140     }
    141 
    142     // Is the request compatible with the shared endpoint?
    143     setFormat(configurationInput.getFormat());
    144     if (getFormat() == AUDIO_FORMAT_DEFAULT) {
    145         setFormat(AUDIO_FORMAT_PCM_FLOAT);
    146     } else if (getFormat() != AUDIO_FORMAT_PCM_FLOAT) {
    147         ALOGD("%s() audio_format_t mAudioFormat = %d, need FLOAT", __func__, getFormat());
    148         result = AAUDIO_ERROR_INVALID_FORMAT;
    149         goto error;
    150     }
    151 
    152     setSampleRate(configurationInput.getSampleRate());
    153     if (getSampleRate() == AAUDIO_UNSPECIFIED) {
    154         setSampleRate(endpoint->getSampleRate());
    155     } else if (getSampleRate() != endpoint->getSampleRate()) {
    156         ALOGD("%s() mSampleRate = %d, need %d",
    157               __func__, getSampleRate(), endpoint->getSampleRate());
    158         result = AAUDIO_ERROR_INVALID_RATE;
    159         goto error;
    160     }
    161 
    162     setSamplesPerFrame(configurationInput.getSamplesPerFrame());
    163     if (getSamplesPerFrame() == AAUDIO_UNSPECIFIED) {
    164         setSamplesPerFrame(endpoint->getSamplesPerFrame());
    165     } else if (getSamplesPerFrame() != endpoint->getSamplesPerFrame()) {
    166         ALOGD("%s() mSamplesPerFrame = %d, need %d",
    167               __func__, getSamplesPerFrame(), endpoint->getSamplesPerFrame());
    168         result = AAUDIO_ERROR_OUT_OF_RANGE;
    169         goto error;
    170     }
    171 
    172     setBufferCapacity(calculateBufferCapacity(configurationInput.getBufferCapacity(),
    173                                      mFramesPerBurst));
    174     if (getBufferCapacity() < 0) {
    175         result = getBufferCapacity(); // negative error code
    176         setBufferCapacity(0);
    177         goto error;
    178     }
    179 
    180     {
    181         std::lock_guard<std::mutex> lock(mAudioDataQueueLock);
    182         // Create audio data shared memory buffer for client.
    183         mAudioDataQueue = new SharedRingBuffer();
    184         result = mAudioDataQueue->allocate(calculateBytesPerFrame(), getBufferCapacity());
    185         if (result != AAUDIO_OK) {
    186             ALOGE("%s() could not allocate FIFO with %d frames",
    187                   __func__, getBufferCapacity());
    188             result = AAUDIO_ERROR_NO_MEMORY;
    189             goto error;
    190         }
    191     }
    192 
    193     result = endpoint->registerStream(keep);
    194     if (result != AAUDIO_OK) {
    195         goto error;
    196     }
    197 
    198     setState(AAUDIO_STREAM_STATE_OPEN);
    199     return AAUDIO_OK;
    200 
    201 error:
    202     close();
    203     return result;
    204 }
    205 
    206 
    207 aaudio_result_t AAudioServiceStreamShared::close()  {
    208     aaudio_result_t result = AAudioServiceStreamBase::close();
    209 
    210     {
    211         std::lock_guard<std::mutex> lock(mAudioDataQueueLock);
    212         delete mAudioDataQueue;
    213         mAudioDataQueue = nullptr;
    214     }
    215 
    216     return result;
    217 }
    218 
    219 /**
    220  * Get an immutable description of the data queue created by this service.
    221  */
    222 aaudio_result_t AAudioServiceStreamShared::getAudioDataDescription(
    223         AudioEndpointParcelable &parcelable)
    224 {
    225     std::lock_guard<std::mutex> lock(mAudioDataQueueLock);
    226     if (mAudioDataQueue == nullptr) {
    227         ALOGW("%s(): mUpMessageQueue null! - stream not open", __func__);
    228         return AAUDIO_ERROR_NULL;
    229     }
    230     // Gather information on the data queue.
    231     mAudioDataQueue->fillParcelable(parcelable,
    232                                     parcelable.mDownDataQueueParcelable);
    233     parcelable.mDownDataQueueParcelable.setFramesPerBurst(getFramesPerBurst());
    234     return AAUDIO_OK;
    235 }
    236 
    237 void AAudioServiceStreamShared::markTransferTime(Timestamp &timestamp) {
    238     mAtomicStreamTimestamp.write(timestamp);
    239 }
    240 
    241 // Get timestamp that was written by mixer or distributor.
    242 aaudio_result_t AAudioServiceStreamShared::getFreeRunningPosition(int64_t *positionFrames,
    243                                                                   int64_t *timeNanos) {
    244     // TODO Get presentation timestamp from the HAL
    245     if (mAtomicStreamTimestamp.isValid()) {
    246         Timestamp timestamp = mAtomicStreamTimestamp.read();
    247         *positionFrames = timestamp.getPosition();
    248         *timeNanos = timestamp.getNanoseconds();
    249         return AAUDIO_OK;
    250     } else {
    251         return AAUDIO_ERROR_UNAVAILABLE;
    252     }
    253 }
    254 
    255 // Get timestamp from lower level service.
    256 aaudio_result_t AAudioServiceStreamShared::getHardwareTimestamp(int64_t *positionFrames,
    257                                                                 int64_t *timeNanos) {
    258 
    259     int64_t position = 0;
    260     sp<AAudioServiceEndpoint> endpoint = mServiceEndpointWeak.promote();
    261     if (endpoint == nullptr) {
    262         ALOGW("%s() has no endpoint", __func__);
    263         return AAUDIO_ERROR_INVALID_STATE;
    264     }
    265 
    266     aaudio_result_t result = endpoint->getTimestamp(&position, timeNanos);
    267     if (result == AAUDIO_OK) {
    268         int64_t offset = mTimestampPositionOffset.load();
    269         // TODO, do not go below starting value
    270         position -= offset; // Offset from shared MMAP stream
    271         ALOGV("%s() %8lld = %8lld - %8lld",
    272               __func__, (long long) position, (long long) (position + offset), (long long) offset);
    273     }
    274     *positionFrames = position;
    275     return result;
    276 }
    277