AAudioServiceStreamShared.cpp revision c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fb
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 "AAudioService" 18//#define LOG_NDEBUG 0 19#include <utils/Log.h> 20 21#include <mutex> 22 23#include <aaudio/AAudio.h> 24 25#include "binding/IAAudioService.h" 26 27#include "binding/AAudioServiceMessage.h" 28#include "AAudioServiceStreamBase.h" 29#include "AAudioServiceStreamShared.h" 30#include "AAudioEndpointManager.h" 31#include "AAudioService.h" 32#include "AAudioServiceEndpoint.h" 33 34using namespace android; 35using namespace aaudio; 36 37#define MIN_BURSTS_PER_BUFFER 2 38#define MAX_BURSTS_PER_BUFFER 32 39 40AAudioServiceStreamShared::AAudioServiceStreamShared(AAudioService &audioService) 41 : mAudioService(audioService) 42 { 43} 44 45AAudioServiceStreamShared::~AAudioServiceStreamShared() { 46 close(); 47} 48 49aaudio_result_t AAudioServiceStreamShared::open(const aaudio::AAudioStreamRequest &request, 50 aaudio::AAudioStreamConfiguration &configurationOutput) { 51 52 aaudio_result_t result = AAudioServiceStreamBase::open(request, configurationOutput); 53 if (result != AAUDIO_OK) { 54 ALOGE("AAudioServiceStreamBase open returned %d", result); 55 return result; 56 } 57 58 const AAudioStreamConfiguration &configurationInput = request.getConstantConfiguration(); 59 int32_t deviceId = configurationInput.getDeviceId(); 60 aaudio_direction_t direction = request.getDirection(); 61 62 ALOGD("AAudioServiceStreamShared::open(), direction = %d", direction); 63 AAudioEndpointManager &mEndpointManager = AAudioEndpointManager::getInstance(); 64 mServiceEndpoint = mEndpointManager.findEndpoint(mAudioService, deviceId, direction); 65 ALOGD("AAudioServiceStreamShared::open(), mServiceEndPoint = %p", mServiceEndpoint); 66 if (mServiceEndpoint == nullptr) { 67 return AAUDIO_ERROR_UNAVAILABLE; 68 } 69 70 // Is the request compatible with the shared endpoint? 71 mAudioFormat = configurationInput.getAudioFormat(); 72 if (mAudioFormat == AAUDIO_FORMAT_UNSPECIFIED) { 73 mAudioFormat = AAUDIO_FORMAT_PCM_FLOAT; 74 } else if (mAudioFormat != AAUDIO_FORMAT_PCM_FLOAT) { 75 return AAUDIO_ERROR_INVALID_FORMAT; 76 } 77 78 mSampleRate = configurationInput.getSampleRate(); 79 if (mSampleRate == AAUDIO_FORMAT_UNSPECIFIED) { 80 mSampleRate = mServiceEndpoint->getSampleRate(); 81 } else if (mSampleRate != mServiceEndpoint->getSampleRate()) { 82 return AAUDIO_ERROR_INVALID_RATE; 83 } 84 85 mSamplesPerFrame = configurationInput.getSamplesPerFrame(); 86 if (mSamplesPerFrame == AAUDIO_FORMAT_UNSPECIFIED) { 87 mSamplesPerFrame = mServiceEndpoint->getSamplesPerFrame(); 88 } else if (mSamplesPerFrame != mServiceEndpoint->getSamplesPerFrame()) { 89 return AAUDIO_ERROR_OUT_OF_RANGE; 90 } 91 92 // Determine this stream's shared memory buffer capacity. 93 mFramesPerBurst = mServiceEndpoint->getFramesPerBurst(); 94 int32_t minCapacityFrames = configurationInput.getBufferCapacity(); 95 int32_t numBursts = (minCapacityFrames + mFramesPerBurst - 1) / mFramesPerBurst; 96 if (numBursts < MIN_BURSTS_PER_BUFFER) { 97 numBursts = MIN_BURSTS_PER_BUFFER; 98 } else if (numBursts > MAX_BURSTS_PER_BUFFER) { 99 numBursts = MAX_BURSTS_PER_BUFFER; 100 } 101 mCapacityInFrames = numBursts * mFramesPerBurst; 102 ALOGD("AAudioServiceStreamShared::open(), mCapacityInFrames = %d", mCapacityInFrames); 103 104 // Create audio data shared memory buffer for client. 105 mAudioDataQueue = new SharedRingBuffer(); 106 mAudioDataQueue->allocate(calculateBytesPerFrame(), mCapacityInFrames); 107 108 // Fill in configuration for client. 109 configurationOutput.setSampleRate(mSampleRate); 110 configurationOutput.setSamplesPerFrame(mSamplesPerFrame); 111 configurationOutput.setAudioFormat(mAudioFormat); 112 configurationOutput.setDeviceId(deviceId); 113 114 mServiceEndpoint->registerStream(this); 115 116 return AAUDIO_OK; 117} 118 119/** 120 * Start the flow of audio data. 121 * 122 * An AAUDIO_SERVICE_EVENT_STARTED will be sent to the client when complete. 123 */ 124aaudio_result_t AAudioServiceStreamShared::start() { 125 // Add this stream to the mixer. 126 aaudio_result_t result = mServiceEndpoint->startStream(this); 127 if (result != AAUDIO_OK) { 128 ALOGE("AAudioServiceStreamShared::start() mServiceEndpoint returned %d", result); 129 processError(); 130 } else { 131 result = AAudioServiceStreamBase::start(); 132 } 133 return AAUDIO_OK; 134} 135 136/** 137 * Stop the flow of data so that start() can resume without loss of data. 138 * 139 * An AAUDIO_SERVICE_EVENT_PAUSED will be sent to the client when complete. 140*/ 141aaudio_result_t AAudioServiceStreamShared::pause() { 142 // Add this stream to the mixer. 143 aaudio_result_t result = mServiceEndpoint->stopStream(this); 144 if (result != AAUDIO_OK) { 145 ALOGE("AAudioServiceStreamShared::stop() mServiceEndpoint returned %d", result); 146 processError(); 147 } else { 148 result = AAudioServiceStreamBase::start(); 149 } 150 return AAUDIO_OK; 151} 152 153/** 154 * Discard any data held by the underlying HAL or Service. 155 * 156 * An AAUDIO_SERVICE_EVENT_FLUSHED will be sent to the client when complete. 157 */ 158aaudio_result_t AAudioServiceStreamShared::flush() { 159 // TODO make sure we are paused 160 return AAUDIO_OK; 161} 162 163aaudio_result_t AAudioServiceStreamShared::close() { 164 pause(); 165 // TODO wait for pause() to synchronize 166 mServiceEndpoint->unregisterStream(this); 167 mServiceEndpoint->close(); 168 mServiceEndpoint = nullptr; 169 return AAudioServiceStreamBase::close(); 170} 171 172/** 173 * Get an immutable description of the data queue created by this service. 174 */ 175aaudio_result_t AAudioServiceStreamShared::getDownDataDescription(AudioEndpointParcelable &parcelable) 176{ 177 // Gather information on the data queue. 178 mAudioDataQueue->fillParcelable(parcelable, 179 parcelable.mDownDataQueueParcelable); 180 parcelable.mDownDataQueueParcelable.setFramesPerBurst(getFramesPerBurst()); 181 return AAUDIO_OK; 182} 183 184void AAudioServiceStreamShared::onStop() { 185} 186 187void AAudioServiceStreamShared::onDisconnect() { 188 mServiceEndpoint->close(); 189 mServiceEndpoint = nullptr; 190} 191 192 193aaudio_result_t AAudioServiceStreamShared::getFreeRunningPosition(int64_t *positionFrames, 194 int64_t *timeNanos) { 195 *positionFrames = mAudioDataQueue->getFifoBuffer()->getReadCounter(); 196 *timeNanos = AudioClock::getNanoseconds(); 197 return AAUDIO_OK; 198} 199