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("AAudioServiceStreamShared::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("AAudioServiceStreamShared::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("AAudioServiceStreamShared::calculateBufferCapacity() calc capacity %d > max %d",
    111               capacityInFrames, MAX_FRAMES_PER_BUFFER);
    112         return AAUDIO_ERROR_OUT_OF_RANGE;
    113     }
    114     ALOGD("AAudioServiceStreamShared::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     aaudio_result_t result = AAudioServiceStreamBase::open(request, AAUDIO_SHARING_MODE_SHARED);
    124     if (result != AAUDIO_OK) {
    125         ALOGE("AAudioServiceStreamBase open() returned %d", result);
    126         return result;
    127     }
    128 
    129     const AAudioStreamConfiguration &configurationInput = request.getConstantConfiguration();
    130 
    131 
    132     // Is the request compatible with the shared endpoint?
    133     setFormat(configurationInput.getFormat());
    134     if (getFormat() == AAUDIO_FORMAT_UNSPECIFIED) {
    135         setFormat(AAUDIO_FORMAT_PCM_FLOAT);
    136     } else if (getFormat() != AAUDIO_FORMAT_PCM_FLOAT) {
    137         ALOGE("AAudioServiceStreamShared::open() mAudioFormat = %d, need FLOAT", getFormat());
    138         result = AAUDIO_ERROR_INVALID_FORMAT;
    139         goto error;
    140     }
    141 
    142     setSampleRate(configurationInput.getSampleRate());
    143     if (getSampleRate() == AAUDIO_UNSPECIFIED) {
    144         setSampleRate(mServiceEndpoint->getSampleRate());
    145     } else if (getSampleRate() != mServiceEndpoint->getSampleRate()) {
    146         ALOGE("AAudioServiceStreamShared::open() mSampleRate = %d, need %d",
    147               getSampleRate(), mServiceEndpoint->getSampleRate());
    148         result = AAUDIO_ERROR_INVALID_RATE;
    149         goto error;
    150     }
    151 
    152     setSamplesPerFrame(configurationInput.getSamplesPerFrame());
    153     if (getSamplesPerFrame() == AAUDIO_UNSPECIFIED) {
    154         setSamplesPerFrame(mServiceEndpoint->getSamplesPerFrame());
    155     } else if (getSamplesPerFrame() != mServiceEndpoint->getSamplesPerFrame()) {
    156         ALOGE("AAudioServiceStreamShared::open() mSamplesPerFrame = %d, need %d",
    157               getSamplesPerFrame(), mServiceEndpoint->getSamplesPerFrame());
    158         result = AAUDIO_ERROR_OUT_OF_RANGE;
    159         goto error;
    160     }
    161 
    162     setBufferCapacity(calculateBufferCapacity(configurationInput.getBufferCapacity(),
    163                                      mFramesPerBurst));
    164     if (getBufferCapacity() < 0) {
    165         result = getBufferCapacity(); // negative error code
    166         setBufferCapacity(0);
    167         goto error;
    168     }
    169 
    170     {
    171         std::lock_guard<std::mutex> lock(mAudioDataQueueLock);
    172         // Create audio data shared memory buffer for client.
    173         mAudioDataQueue = new SharedRingBuffer();
    174         result = mAudioDataQueue->allocate(calculateBytesPerFrame(), getBufferCapacity());
    175         if (result != AAUDIO_OK) {
    176             ALOGE("AAudioServiceStreamShared::open() could not allocate FIFO with %d frames",
    177                   getBufferCapacity());
    178             result = AAUDIO_ERROR_NO_MEMORY;
    179             goto error;
    180         }
    181     }
    182 
    183     ALOGD("AAudioServiceStreamShared::open() actual rate = %d, channels = %d, deviceId = %d",
    184           getSampleRate(), getSamplesPerFrame(), mServiceEndpoint->getDeviceId());
    185 
    186     result = mServiceEndpoint->registerStream(keep);
    187     if (result != AAUDIO_OK) {
    188         goto error;
    189     }
    190 
    191     setState(AAUDIO_STREAM_STATE_OPEN);
    192     return AAUDIO_OK;
    193 
    194 error:
    195     close();
    196     return result;
    197 }
    198 
    199 
    200 aaudio_result_t AAudioServiceStreamShared::close()  {
    201     aaudio_result_t result = AAudioServiceStreamBase::close();
    202 
    203     {
    204         std::lock_guard<std::mutex> lock(mAudioDataQueueLock);
    205         delete mAudioDataQueue;
    206         mAudioDataQueue = nullptr;
    207     }
    208 
    209     return result;
    210 }
    211 
    212 /**
    213  * Get an immutable description of the data queue created by this service.
    214  */
    215 aaudio_result_t AAudioServiceStreamShared::getAudioDataDescription(
    216         AudioEndpointParcelable &parcelable)
    217 {
    218     std::lock_guard<std::mutex> lock(mAudioDataQueueLock);
    219     if (mAudioDataQueue == nullptr) {
    220         ALOGE("getAudioDataDescription(): mUpMessageQueue null! - stream not open");
    221         return AAUDIO_ERROR_NULL;
    222     }
    223     // Gather information on the data queue.
    224     mAudioDataQueue->fillParcelable(parcelable,
    225                                     parcelable.mDownDataQueueParcelable);
    226     parcelable.mDownDataQueueParcelable.setFramesPerBurst(getFramesPerBurst());
    227     return AAUDIO_OK;
    228 }
    229 
    230 void AAudioServiceStreamShared::markTransferTime(Timestamp &timestamp) {
    231     mAtomicTimestamp.write(timestamp);
    232 }
    233 
    234 // Get timestamp that was written by mixer or distributor.
    235 aaudio_result_t AAudioServiceStreamShared::getFreeRunningPosition(int64_t *positionFrames,
    236                                                                   int64_t *timeNanos) {
    237     // TODO Get presentation timestamp from the HAL
    238     if (mAtomicTimestamp.isValid()) {
    239         Timestamp timestamp = mAtomicTimestamp.read();
    240         *positionFrames = timestamp.getPosition();
    241         *timeNanos = timestamp.getNanoseconds();
    242         return AAUDIO_OK;
    243     } else {
    244         return AAUDIO_ERROR_UNAVAILABLE;
    245     }
    246 }
    247 
    248 // Get timestamp from lower level service.
    249 aaudio_result_t AAudioServiceStreamShared::getHardwareTimestamp(int64_t *positionFrames,
    250                                                                 int64_t *timeNanos) {
    251 
    252     int64_t position = 0;
    253     aaudio_result_t result = mServiceEndpoint->getTimestamp(&position, timeNanos);
    254     if (result == AAUDIO_OK) {
    255         int64_t offset = mTimestampPositionOffset.load();
    256         // TODO, do not go below starting value
    257         position -= offset; // Offset from shared MMAP stream
    258         ALOGV("getHardwareTimestamp() %8lld = %8lld - %8lld",
    259               (long long) position, (long long) (position + offset), (long long) offset);
    260     }
    261     *positionFrames = position;
    262     return result;
    263 }
    264