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