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