AAudioServiceStreamShared.cpp revision cf5f6d2825d9a8430a291042ca9c6f68e5b666d0
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 AAudioEndpointManager &mEndpointManager = AAudioEndpointManager::getInstance(); 63 mServiceEndpoint = mEndpointManager.openEndpoint(mAudioService, deviceId, direction); 64 if (mServiceEndpoint == nullptr) { 65 ALOGE("AAudioServiceStreamShared::open(), mServiceEndPoint = %p", mServiceEndpoint); 66 return AAUDIO_ERROR_UNAVAILABLE; 67 } 68 69 // Is the request compatible with the shared endpoint? 70 mAudioFormat = configurationInput.getAudioFormat(); 71 if (mAudioFormat == AAUDIO_FORMAT_UNSPECIFIED) { 72 mAudioFormat = AAUDIO_FORMAT_PCM_FLOAT; 73 } else if (mAudioFormat != AAUDIO_FORMAT_PCM_FLOAT) { 74 ALOGE("AAudioServiceStreamShared::open(), mAudioFormat = %d, need FLOAT", mAudioFormat); 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 ALOGE("AAudioServiceStreamShared::open(), mAudioFormat = %d, need %d", 83 mSampleRate, mServiceEndpoint->getSampleRate()); 84 return AAUDIO_ERROR_INVALID_RATE; 85 } 86 87 mSamplesPerFrame = configurationInput.getSamplesPerFrame(); 88 if (mSamplesPerFrame == AAUDIO_FORMAT_UNSPECIFIED) { 89 mSamplesPerFrame = mServiceEndpoint->getSamplesPerFrame(); 90 } else if (mSamplesPerFrame != mServiceEndpoint->getSamplesPerFrame()) { 91 ALOGE("AAudioServiceStreamShared::open(), mSamplesPerFrame = %d, need %d", 92 mSamplesPerFrame, mServiceEndpoint->getSamplesPerFrame()); 93 return AAUDIO_ERROR_OUT_OF_RANGE; 94 } 95 96 // Determine this stream's shared memory buffer capacity. 97 mFramesPerBurst = mServiceEndpoint->getFramesPerBurst(); 98 int32_t minCapacityFrames = configurationInput.getBufferCapacity(); 99 int32_t numBursts = MAX_BURSTS_PER_BUFFER; 100 if (minCapacityFrames != AAUDIO_UNSPECIFIED) { 101 numBursts = (minCapacityFrames + mFramesPerBurst - 1) / mFramesPerBurst; 102 if (numBursts < MIN_BURSTS_PER_BUFFER) { 103 numBursts = MIN_BURSTS_PER_BUFFER; 104 } else if (numBursts > MAX_BURSTS_PER_BUFFER) { 105 numBursts = MAX_BURSTS_PER_BUFFER; 106 } 107 } 108 mCapacityInFrames = numBursts * mFramesPerBurst; 109 ALOGD("AAudioServiceStreamShared::open(), mCapacityInFrames = %d", mCapacityInFrames); 110 111 // Create audio data shared memory buffer for client. 112 mAudioDataQueue = new SharedRingBuffer(); 113 mAudioDataQueue->allocate(calculateBytesPerFrame(), mCapacityInFrames); 114 115 // Fill in configuration for client. 116 configurationOutput.setSampleRate(mSampleRate); 117 configurationOutput.setSamplesPerFrame(mSamplesPerFrame); 118 configurationOutput.setAudioFormat(mAudioFormat); 119 configurationOutput.setDeviceId(deviceId); 120 121 mServiceEndpoint->registerStream(this); 122 123 return AAUDIO_OK; 124} 125 126/** 127 * Start the flow of audio data. 128 * 129 * An AAUDIO_SERVICE_EVENT_STARTED will be sent to the client when complete. 130 */ 131aaudio_result_t AAudioServiceStreamShared::start() { 132 AAudioServiceEndpoint *endpoint = mServiceEndpoint; 133 if (endpoint == nullptr) { 134 return AAUDIO_ERROR_INVALID_STATE; 135 } 136 // For output streams, this will add the stream to the mixer. 137 aaudio_result_t result = endpoint->startStream(this); 138 if (result != AAUDIO_OK) { 139 ALOGE("AAudioServiceStreamShared::start() mServiceEndpoint returned %d", result); 140 processError(); 141 } else { 142 result = AAudioServiceStreamBase::start(); 143 } 144 return AAUDIO_OK; 145} 146 147/** 148 * Stop the flow of data so that start() can resume without loss of data. 149 * 150 * An AAUDIO_SERVICE_EVENT_PAUSED will be sent to the client when complete. 151*/ 152aaudio_result_t AAudioServiceStreamShared::pause() { 153 AAudioServiceEndpoint *endpoint = mServiceEndpoint; 154 if (endpoint == nullptr) { 155 return AAUDIO_ERROR_INVALID_STATE; 156 } 157 // Add this stream to the mixer. 158 aaudio_result_t result = endpoint->stopStream(this); 159 if (result != AAUDIO_OK) { 160 ALOGE("AAudioServiceStreamShared::pause() mServiceEndpoint returned %d", result); 161 processError(); 162 } 163 return AAudioServiceStreamBase::pause(); 164} 165 166aaudio_result_t AAudioServiceStreamShared::stop() { 167 AAudioServiceEndpoint *endpoint = mServiceEndpoint; 168 if (endpoint == nullptr) { 169 return AAUDIO_ERROR_INVALID_STATE; 170 } 171 // Add this stream to the mixer. 172 aaudio_result_t result = endpoint->stopStream(this); 173 if (result != AAUDIO_OK) { 174 ALOGE("AAudioServiceStreamShared::stop() mServiceEndpoint returned %d", result); 175 processError(); 176 } 177 return AAudioServiceStreamBase::stop(); 178} 179 180/** 181 * Discard any data held by the underlying HAL or Service. 182 * 183 * An AAUDIO_SERVICE_EVENT_FLUSHED will be sent to the client when complete. 184 */ 185aaudio_result_t AAudioServiceStreamShared::flush() { 186 // TODO make sure we are paused 187 // TODO actually flush the data 188 return AAudioServiceStreamBase::flush() ; 189} 190 191aaudio_result_t AAudioServiceStreamShared::close() { 192 pause(); 193 // TODO wait for pause() to synchronize 194 AAudioServiceEndpoint *endpoint = mServiceEndpoint; 195 if (endpoint != nullptr) { 196 endpoint->unregisterStream(this); 197 198 AAudioEndpointManager &mEndpointManager = AAudioEndpointManager::getInstance(); 199 mEndpointManager.closeEndpoint(endpoint); 200 mServiceEndpoint = nullptr; 201 } 202 if (mAudioDataQueue != nullptr) { 203 delete mAudioDataQueue; 204 mAudioDataQueue = nullptr; 205 } 206 return AAudioServiceStreamBase::close(); 207} 208 209/** 210 * Get an immutable description of the data queue created by this service. 211 */ 212aaudio_result_t AAudioServiceStreamShared::getDownDataDescription(AudioEndpointParcelable &parcelable) 213{ 214 // Gather information on the data queue. 215 mAudioDataQueue->fillParcelable(parcelable, 216 parcelable.mDownDataQueueParcelable); 217 parcelable.mDownDataQueueParcelable.setFramesPerBurst(getFramesPerBurst()); 218 return AAUDIO_OK; 219} 220 221void AAudioServiceStreamShared::onStop() { 222} 223 224void AAudioServiceStreamShared::onDisconnect() { 225 mServiceEndpoint->close(); 226 mServiceEndpoint = nullptr; 227} 228 229void AAudioServiceStreamShared::markTransferTime(int64_t nanoseconds) { 230 mMarkedPosition = mAudioDataQueue->getFifoBuffer()->getReadCounter(); 231 mMarkedTime = nanoseconds; 232} 233 234aaudio_result_t AAudioServiceStreamShared::getFreeRunningPosition(int64_t *positionFrames, 235 int64_t *timeNanos) { 236 // TODO get these two numbers as an atomic pair 237 *positionFrames = mMarkedPosition; 238 *timeNanos = mMarkedTime; 239 return AAUDIO_OK; 240} 241