| Phil Burk | c0c70e3 | 2017-02-09 13:18:38 -0800 | [diff] [blame] | 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 |  | 
| Eric Laurent | cb4dae2 | 2017-07-01 19:39:32 -0700 | [diff] [blame] | 17 | #define LOG_TAG "AAudioServiceStreamShared" | 
| Phil Burk | c0c70e3 | 2017-02-09 13:18:38 -0800 | [diff] [blame] | 18 | //#define LOG_NDEBUG 0 | 
 | 19 | #include <utils/Log.h> | 
 | 20 |  | 
| Phil Burk | a5222e2 | 2017-07-28 13:31:14 -0700 | [diff] [blame] | 21 | #include <iomanip> | 
 | 22 | #include <iostream> | 
| Phil Burk | c0c70e3 | 2017-02-09 13:18:38 -0800 | [diff] [blame] | 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 |  | 
| Phil Burk | ec89b2e | 2017-06-20 15:05:06 -0700 | [diff] [blame] | 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) | 
| Phil Burk | c0c70e3 | 2017-02-09 13:18:38 -0800 | [diff] [blame] | 43 |  | 
 | 44 | AAudioServiceStreamShared::AAudioServiceStreamShared(AAudioService &audioService) | 
| Phil Burk | 39f02dd | 2017-08-04 09:13:31 -0700 | [diff] [blame] | 45 |     : AAudioServiceStreamBase(audioService) | 
| Phil Burk | 97350f9 | 2017-07-21 15:59:44 -0700 | [diff] [blame] | 46 |     , mTimestampPositionOffset(0) | 
| Phil Burk | 39f02dd | 2017-08-04 09:13:31 -0700 | [diff] [blame] | 47 |     , mXRunCount(0) { | 
| Phil Burk | c0c70e3 | 2017-02-09 13:18:38 -0800 | [diff] [blame] | 48 | } | 
 | 49 |  | 
| Phil Burk | a5222e2 | 2017-07-28 13:31:14 -0700 | [diff] [blame] | 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; | 
| Phil Burk | 39f02dd | 2017-08-04 09:13:31 -0700 | [diff] [blame] | 59 |  | 
| Phil Burk | a5222e2 | 2017-07-28 13:31:14 -0700 | [diff] [blame] | 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 |  | 
| Phil Burk | ec89b2e | 2017-06-20 15:05:06 -0700 | [diff] [blame] | 73 | int32_t AAudioServiceStreamShared::calculateBufferCapacity(int32_t requestedCapacityFrames, | 
 | 74 |                                                            int32_t framesPerBurst) { | 
 | 75 |  | 
 | 76 |     if (requestedCapacityFrames > MAX_FRAMES_PER_BUFFER) { | 
| Phil Burk | fbf031e | 2017-10-12 15:58:31 -0700 | [diff] [blame] | 77 |         ALOGE("calculateBufferCapacity() requested capacity %d > max %d", | 
| Phil Burk | ec89b2e | 2017-06-20 15:05:06 -0700 | [diff] [blame] | 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) { | 
| Phil Burk | fbf031e | 2017-10-12 15:58:31 -0700 | [diff] [blame] | 102 |         ALOGE("calculateBufferCapacity() overflow, capacity = %d * %d", | 
| Phil Burk | ec89b2e | 2017-06-20 15:05:06 -0700 | [diff] [blame] | 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) { | 
| Phil Burk | fbf031e | 2017-10-12 15:58:31 -0700 | [diff] [blame] | 110 |         ALOGE("calculateBufferCapacity() calc capacity %d > max %d", | 
| Phil Burk | ec89b2e | 2017-06-20 15:05:06 -0700 | [diff] [blame] | 111 |               capacityInFrames, MAX_FRAMES_PER_BUFFER); | 
 | 112 |         return AAUDIO_ERROR_OUT_OF_RANGE; | 
 | 113 |     } | 
| Phil Burk | fbf031e | 2017-10-12 15:58:31 -0700 | [diff] [blame] | 114 |     ALOGD("calculateBufferCapacity() requested %d frames, actual = %d", | 
| Phil Burk | ec89b2e | 2017-06-20 15:05:06 -0700 | [diff] [blame] | 115 |           requestedCapacityFrames, capacityInFrames); | 
 | 116 |     return capacityInFrames; | 
 | 117 | } | 
 | 118 |  | 
| Phil Burk | 39f02dd | 2017-08-04 09:13:31 -0700 | [diff] [blame] | 119 | aaudio_result_t AAudioServiceStreamShared::open(const aaudio::AAudioStreamRequest &request)  { | 
| Phil Burk | c0c70e3 | 2017-02-09 13:18:38 -0800 | [diff] [blame] | 120 |  | 
| Phil Burk | 11e8d33 | 2017-05-24 09:59:02 -0700 | [diff] [blame] | 121 |     sp<AAudioServiceStreamShared> keep(this); | 
 | 122 |  | 
| Phil Burk | 15f97c9 | 2018-09-04 14:06:27 -0700 | [diff] [blame] | 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); | 
| Phil Burk | c0c70e3 | 2017-02-09 13:18:38 -0800 | [diff] [blame] | 130 |     if (result != AAUDIO_OK) { | 
| Phil Burk | 55e5eab | 2018-04-10 15:16:38 -0700 | [diff] [blame] | 131 |         ALOGE("%s() returned %d", __func__, result); | 
| Phil Burk | c0c70e3 | 2017-02-09 13:18:38 -0800 | [diff] [blame] | 132 |         return result; | 
 | 133 |     } | 
 | 134 |  | 
 | 135 |     const AAudioStreamConfiguration &configurationInput = request.getConstantConfiguration(); | 
| Phil Burk | c0c70e3 | 2017-02-09 13:18:38 -0800 | [diff] [blame] | 136 |  | 
| Phil Burk | 6e2770e | 2018-05-01 13:03:52 -0700 | [diff] [blame] | 137 |     sp<AAudioServiceEndpoint> endpoint = mServiceEndpointWeak.promote(); | 
 | 138 |     if (endpoint == nullptr) { | 
 | 139 |         result = AAUDIO_ERROR_INVALID_STATE; | 
 | 140 |         goto error; | 
 | 141 |     } | 
 | 142 |  | 
| Phil Burk | c0c70e3 | 2017-02-09 13:18:38 -0800 | [diff] [blame] | 143 |     // Is the request compatible with the shared endpoint? | 
| Phil Burk | 39f02dd | 2017-08-04 09:13:31 -0700 | [diff] [blame] | 144 |     setFormat(configurationInput.getFormat()); | 
| Phil Burk | 0127c1b | 2018-03-29 13:48:06 -0700 | [diff] [blame] | 145 |     if (getFormat() == AUDIO_FORMAT_DEFAULT) { | 
 | 146 |         setFormat(AUDIO_FORMAT_PCM_FLOAT); | 
 | 147 |     } else if (getFormat() != AUDIO_FORMAT_PCM_FLOAT) { | 
 | 148 |         ALOGE("%s() audio_format_t mAudioFormat = %d, need FLOAT", __func__, getFormat()); | 
| Phil Burk | ec89b2e | 2017-06-20 15:05:06 -0700 | [diff] [blame] | 149 |         result = AAUDIO_ERROR_INVALID_FORMAT; | 
 | 150 |         goto error; | 
| Phil Burk | c0c70e3 | 2017-02-09 13:18:38 -0800 | [diff] [blame] | 151 |     } | 
 | 152 |  | 
| Phil Burk | 39f02dd | 2017-08-04 09:13:31 -0700 | [diff] [blame] | 153 |     setSampleRate(configurationInput.getSampleRate()); | 
 | 154 |     if (getSampleRate() == AAUDIO_UNSPECIFIED) { | 
| Phil Burk | 6e2770e | 2018-05-01 13:03:52 -0700 | [diff] [blame] | 155 |         setSampleRate(endpoint->getSampleRate()); | 
 | 156 |     } else if (getSampleRate() != endpoint->getSampleRate()) { | 
| Phil Burk | 0127c1b | 2018-03-29 13:48:06 -0700 | [diff] [blame] | 157 |         ALOGE("%s() mSampleRate = %d, need %d", | 
| Phil Burk | 6e2770e | 2018-05-01 13:03:52 -0700 | [diff] [blame] | 158 |               __func__, getSampleRate(), endpoint->getSampleRate()); | 
| Phil Burk | ec89b2e | 2017-06-20 15:05:06 -0700 | [diff] [blame] | 159 |         result = AAUDIO_ERROR_INVALID_RATE; | 
 | 160 |         goto error; | 
| Phil Burk | c0c70e3 | 2017-02-09 13:18:38 -0800 | [diff] [blame] | 161 |     } | 
 | 162 |  | 
| Phil Burk | 39f02dd | 2017-08-04 09:13:31 -0700 | [diff] [blame] | 163 |     setSamplesPerFrame(configurationInput.getSamplesPerFrame()); | 
 | 164 |     if (getSamplesPerFrame() == AAUDIO_UNSPECIFIED) { | 
| Phil Burk | 6e2770e | 2018-05-01 13:03:52 -0700 | [diff] [blame] | 165 |         setSamplesPerFrame(endpoint->getSamplesPerFrame()); | 
 | 166 |     } else if (getSamplesPerFrame() != endpoint->getSamplesPerFrame()) { | 
| Phil Burk | 0127c1b | 2018-03-29 13:48:06 -0700 | [diff] [blame] | 167 |         ALOGE("%s() mSamplesPerFrame = %d, need %d", | 
| Phil Burk | 6e2770e | 2018-05-01 13:03:52 -0700 | [diff] [blame] | 168 |               __func__, getSamplesPerFrame(), endpoint->getSamplesPerFrame()); | 
| Phil Burk | ec89b2e | 2017-06-20 15:05:06 -0700 | [diff] [blame] | 169 |         result = AAUDIO_ERROR_OUT_OF_RANGE; | 
 | 170 |         goto error; | 
| Phil Burk | c0c70e3 | 2017-02-09 13:18:38 -0800 | [diff] [blame] | 171 |     } | 
 | 172 |  | 
| Phil Burk | 39f02dd | 2017-08-04 09:13:31 -0700 | [diff] [blame] | 173 |     setBufferCapacity(calculateBufferCapacity(configurationInput.getBufferCapacity(), | 
 | 174 |                                      mFramesPerBurst)); | 
 | 175 |     if (getBufferCapacity() < 0) { | 
 | 176 |         result = getBufferCapacity(); // negative error code | 
 | 177 |         setBufferCapacity(0); | 
| Phil Burk | ec89b2e | 2017-06-20 15:05:06 -0700 | [diff] [blame] | 178 |         goto error; | 
| Phil Burk | c0c70e3 | 2017-02-09 13:18:38 -0800 | [diff] [blame] | 179 |     } | 
| Phil Burk | c0c70e3 | 2017-02-09 13:18:38 -0800 | [diff] [blame] | 180 |  | 
| Phil Burk | 523b304 | 2017-09-13 13:03:08 -0700 | [diff] [blame] | 181 |     { | 
 | 182 |         std::lock_guard<std::mutex> lock(mAudioDataQueueLock); | 
 | 183 |         // Create audio data shared memory buffer for client. | 
 | 184 |         mAudioDataQueue = new SharedRingBuffer(); | 
 | 185 |         result = mAudioDataQueue->allocate(calculateBytesPerFrame(), getBufferCapacity()); | 
 | 186 |         if (result != AAUDIO_OK) { | 
| Phil Burk | 55e5eab | 2018-04-10 15:16:38 -0700 | [diff] [blame] | 187 |             ALOGE("%s() could not allocate FIFO with %d frames", | 
 | 188 |                   __func__, getBufferCapacity()); | 
| Phil Burk | 523b304 | 2017-09-13 13:03:08 -0700 | [diff] [blame] | 189 |             result = AAUDIO_ERROR_NO_MEMORY; | 
 | 190 |             goto error; | 
 | 191 |         } | 
| Phil Burk | ec89b2e | 2017-06-20 15:05:06 -0700 | [diff] [blame] | 192 |     } | 
 | 193 |  | 
| Phil Burk | 0127c1b | 2018-03-29 13:48:06 -0700 | [diff] [blame] | 194 |     ALOGD("%s() actual rate = %d, channels = %d, deviceId = %d", | 
 | 195 |           __func__, getSampleRate(), getSamplesPerFrame(), endpoint->getDeviceId()); | 
| Phil Burk | 6e2770e | 2018-05-01 13:03:52 -0700 | [diff] [blame] | 196 |  | 
 | 197 |     result = endpoint->registerStream(keep); | 
| Phil Burk | ec89b2e | 2017-06-20 15:05:06 -0700 | [diff] [blame] | 198 |     if (result != AAUDIO_OK) { | 
 | 199 |         goto error; | 
 | 200 |     } | 
| Phil Burk | c0c70e3 | 2017-02-09 13:18:38 -0800 | [diff] [blame] | 201 |  | 
| Phil Burk | 5a26e66 | 2017-07-07 12:44:48 -0700 | [diff] [blame] | 202 |     setState(AAUDIO_STREAM_STATE_OPEN); | 
| Phil Burk | c0c70e3 | 2017-02-09 13:18:38 -0800 | [diff] [blame] | 203 |     return AAUDIO_OK; | 
| Phil Burk | ec89b2e | 2017-06-20 15:05:06 -0700 | [diff] [blame] | 204 |  | 
 | 205 | error: | 
 | 206 |     close(); | 
 | 207 |     return result; | 
| Phil Burk | c0c70e3 | 2017-02-09 13:18:38 -0800 | [diff] [blame] | 208 | } | 
 | 209 |  | 
| Phil Burk | c0c70e3 | 2017-02-09 13:18:38 -0800 | [diff] [blame] | 210 |  | 
 | 211 | aaudio_result_t AAudioServiceStreamShared::close()  { | 
| Phil Burk | 39f02dd | 2017-08-04 09:13:31 -0700 | [diff] [blame] | 212 |     aaudio_result_t result = AAudioServiceStreamBase::close(); | 
| Phil Burk | 98d6d92 | 2017-07-06 11:52:45 -0700 | [diff] [blame] | 213 |  | 
| Phil Burk | 523b304 | 2017-09-13 13:03:08 -0700 | [diff] [blame] | 214 |     { | 
 | 215 |         std::lock_guard<std::mutex> lock(mAudioDataQueueLock); | 
 | 216 |         delete mAudioDataQueue; | 
 | 217 |         mAudioDataQueue = nullptr; | 
 | 218 |     } | 
| Eric Laurent | cb4dae2 | 2017-07-01 19:39:32 -0700 | [diff] [blame] | 219 |  | 
| Phil Burk | 39f02dd | 2017-08-04 09:13:31 -0700 | [diff] [blame] | 220 |     return result; | 
| Phil Burk | c0c70e3 | 2017-02-09 13:18:38 -0800 | [diff] [blame] | 221 | } | 
 | 222 |  | 
 | 223 | /** | 
 | 224 |  * Get an immutable description of the data queue created by this service. | 
 | 225 |  */ | 
| Phil Burk | 523b304 | 2017-09-13 13:03:08 -0700 | [diff] [blame] | 226 | aaudio_result_t AAudioServiceStreamShared::getAudioDataDescription( | 
 | 227 |         AudioEndpointParcelable &parcelable) | 
| Phil Burk | c0c70e3 | 2017-02-09 13:18:38 -0800 | [diff] [blame] | 228 | { | 
| Phil Burk | 523b304 | 2017-09-13 13:03:08 -0700 | [diff] [blame] | 229 |     std::lock_guard<std::mutex> lock(mAudioDataQueueLock); | 
 | 230 |     if (mAudioDataQueue == nullptr) { | 
| Phil Burk | 55e5eab | 2018-04-10 15:16:38 -0700 | [diff] [blame] | 231 |         ALOGE("%s(): mUpMessageQueue null! - stream not open", __func__); | 
| Phil Burk | 523b304 | 2017-09-13 13:03:08 -0700 | [diff] [blame] | 232 |         return AAUDIO_ERROR_NULL; | 
 | 233 |     } | 
| Phil Burk | c0c70e3 | 2017-02-09 13:18:38 -0800 | [diff] [blame] | 234 |     // Gather information on the data queue. | 
 | 235 |     mAudioDataQueue->fillParcelable(parcelable, | 
 | 236 |                                     parcelable.mDownDataQueueParcelable); | 
 | 237 |     parcelable.mDownDataQueueParcelable.setFramesPerBurst(getFramesPerBurst()); | 
 | 238 |     return AAUDIO_OK; | 
 | 239 | } | 
 | 240 |  | 
| Phil Burk | 97350f9 | 2017-07-21 15:59:44 -0700 | [diff] [blame] | 241 | void AAudioServiceStreamShared::markTransferTime(Timestamp ×tamp) { | 
 | 242 |     mAtomicTimestamp.write(timestamp); | 
| Phil Burk | 71f35bb | 2017-04-13 16:05:07 -0700 | [diff] [blame] | 243 | } | 
| Phil Burk | c0c70e3 | 2017-02-09 13:18:38 -0800 | [diff] [blame] | 244 |  | 
| Phil Burk | 39f02dd | 2017-08-04 09:13:31 -0700 | [diff] [blame] | 245 | // Get timestamp that was written by mixer or distributor. | 
| Phil Burk | c0c70e3 | 2017-02-09 13:18:38 -0800 | [diff] [blame] | 246 | aaudio_result_t AAudioServiceStreamShared::getFreeRunningPosition(int64_t *positionFrames, | 
| Phil Burk | 39f02dd | 2017-08-04 09:13:31 -0700 | [diff] [blame] | 247 |                                                                   int64_t *timeNanos) { | 
 | 248 |     // TODO Get presentation timestamp from the HAL | 
| Phil Burk | 97350f9 | 2017-07-21 15:59:44 -0700 | [diff] [blame] | 249 |     if (mAtomicTimestamp.isValid()) { | 
 | 250 |         Timestamp timestamp = mAtomicTimestamp.read(); | 
 | 251 |         *positionFrames = timestamp.getPosition(); | 
 | 252 |         *timeNanos = timestamp.getNanoseconds(); | 
 | 253 |         return AAUDIO_OK; | 
 | 254 |     } else { | 
 | 255 |         return AAUDIO_ERROR_UNAVAILABLE; | 
 | 256 |     } | 
 | 257 | } | 
 | 258 |  | 
 | 259 | // Get timestamp from lower level service. | 
 | 260 | aaudio_result_t AAudioServiceStreamShared::getHardwareTimestamp(int64_t *positionFrames, | 
| Phil Burk | 39f02dd | 2017-08-04 09:13:31 -0700 | [diff] [blame] | 261 |                                                                 int64_t *timeNanos) { | 
| Phil Burk | 97350f9 | 2017-07-21 15:59:44 -0700 | [diff] [blame] | 262 |  | 
| Phil Burk | bcc3674 | 2017-08-31 17:24:51 -0700 | [diff] [blame] | 263 |     int64_t position = 0; | 
| Phil Burk | 6e2770e | 2018-05-01 13:03:52 -0700 | [diff] [blame] | 264 |     sp<AAudioServiceEndpoint> endpoint = mServiceEndpointWeak.promote(); | 
 | 265 |     if (endpoint == nullptr) { | 
 | 266 |         ALOGE("%s() has no endpoint", __func__); | 
 | 267 |         return AAUDIO_ERROR_INVALID_STATE; | 
 | 268 |     } | 
 | 269 |  | 
 | 270 |     aaudio_result_t result = endpoint->getTimestamp(&position, timeNanos); | 
| Phil Burk | 97350f9 | 2017-07-21 15:59:44 -0700 | [diff] [blame] | 271 |     if (result == AAUDIO_OK) { | 
| Phil Burk | bcc3674 | 2017-08-31 17:24:51 -0700 | [diff] [blame] | 272 |         int64_t offset = mTimestampPositionOffset.load(); | 
 | 273 |         // TODO, do not go below starting value | 
 | 274 |         position -= offset; // Offset from shared MMAP stream | 
| Phil Burk | 55e5eab | 2018-04-10 15:16:38 -0700 | [diff] [blame] | 275 |         ALOGV("%s() %8lld = %8lld - %8lld", | 
 | 276 |               __func__, (long long) position, (long long) (position + offset), (long long) offset); | 
| Phil Burk | 97350f9 | 2017-07-21 15:59:44 -0700 | [diff] [blame] | 277 |     } | 
| Phil Burk | bcc3674 | 2017-08-31 17:24:51 -0700 | [diff] [blame] | 278 |     *positionFrames = position; | 
| Phil Burk | 97350f9 | 2017-07-21 15:59:44 -0700 | [diff] [blame] | 279 |     return result; | 
| Phil Burk | c0c70e3 | 2017-02-09 13:18:38 -0800 | [diff] [blame] | 280 | } |