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 ×tamp) { 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