blob: b71b74af4913d0b26333b1946487adeb86693542 [file] [log] [blame]
Phil Burke1ce4912016-11-21 10:40:25 -08001/*
2 * Copyright 2016 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 "AudioStreamTrack"
18//#define LOG_NDEBUG 0
19#include <utils/Log.h>
20
21#include <stdint.h>
22#include <media/AudioTrack.h>
Phil Burke1ce4912016-11-21 10:40:25 -080023
Phil Burke4d7bb42017-03-28 11:32:39 -070024#include <aaudio/AAudio.h>
Phil Burkc0c70e32017-02-09 13:18:38 -080025#include "utility/AudioClock.h"
Phil Burke4d7bb42017-03-28 11:32:39 -070026#include "legacy/AudioStreamLegacy.h"
27#include "legacy/AudioStreamTrack.h"
28#include "utility/FixedBlockReader.h"
Phil Burke1ce4912016-11-21 10:40:25 -080029
30using namespace android;
Phil Burk5ed503c2017-02-01 09:38:15 -080031using namespace aaudio;
Phil Burke1ce4912016-11-21 10:40:25 -080032
Phil Burke4d7bb42017-03-28 11:32:39 -070033// Arbitrary and somewhat generous number of bursts.
34#define DEFAULT_BURSTS_PER_BUFFER_CAPACITY 8
Phil Burke572f462017-04-20 13:03:19 -070035static const bool FAST_TRACKS_ENABLED = true;
Phil Burke4d7bb42017-03-28 11:32:39 -070036
Phil Burke1ce4912016-11-21 10:40:25 -080037/*
38 * Create a stream that uses the AudioTrack.
39 */
40AudioStreamTrack::AudioStreamTrack()
Phil Burke4d7bb42017-03-28 11:32:39 -070041 : AudioStreamLegacy()
42 , mFixedBlockReader(*this)
Phil Burke1ce4912016-11-21 10:40:25 -080043{
44}
45
46AudioStreamTrack::~AudioStreamTrack()
47{
Phil Burk5ed503c2017-02-01 09:38:15 -080048 const aaudio_stream_state_t state = getState();
49 bool bad = !(state == AAUDIO_STREAM_STATE_UNINITIALIZED || state == AAUDIO_STREAM_STATE_CLOSED);
Phil Burke1ce4912016-11-21 10:40:25 -080050 ALOGE_IF(bad, "stream not closed, in state %d", state);
51}
52
Phil Burk5ed503c2017-02-01 09:38:15 -080053aaudio_result_t AudioStreamTrack::open(const AudioStreamBuilder& builder)
Phil Burke1ce4912016-11-21 10:40:25 -080054{
Phil Burk5ed503c2017-02-01 09:38:15 -080055 aaudio_result_t result = AAUDIO_OK;
Phil Burke1ce4912016-11-21 10:40:25 -080056
57 result = AudioStream::open(builder);
58 if (result != OK) {
59 return result;
60 }
61
Phil Burke4d7bb42017-03-28 11:32:39 -070062 ALOGD("AudioStreamTrack::open = %p", this);
63
Phil Burke1ce4912016-11-21 10:40:25 -080064 // Try to create an AudioTrack
65 // TODO Support UNSPECIFIED in AudioTrack. For now, use stereo if unspecified.
Phil Burk5ed503c2017-02-01 09:38:15 -080066 int32_t samplesPerFrame = (getSamplesPerFrame() == AAUDIO_UNSPECIFIED)
Phil Burke1ce4912016-11-21 10:40:25 -080067 ? 2 : getSamplesPerFrame();
68 audio_channel_mask_t channelMask = audio_channel_out_mask_from_count(samplesPerFrame);
Phil Burkd8bdcab2017-01-03 17:20:30 -080069 ALOGD("AudioStreamTrack::open(), samplesPerFrame = %d, channelMask = 0x%08x",
Phil Burke1ce4912016-11-21 10:40:25 -080070 samplesPerFrame, channelMask);
71
Phil Burke1ce4912016-11-21 10:40:25 -080072 // TODO add more performance options
Phil Burke572f462017-04-20 13:03:19 -070073 audio_output_flags_t flags = FAST_TRACKS_ENABLED
74 ? AUDIO_OUTPUT_FLAG_FAST
75 : AUDIO_OUTPUT_FLAG_NONE;
Phil Burke4d7bb42017-03-28 11:32:39 -070076
77 int32_t frameCount = builder.getBufferCapacity();
78 ALOGD("AudioStreamTrack::open(), requested buffer capacity %d", frameCount);
79
80 int32_t notificationFrames = 0;
81
Phil Burke1ce4912016-11-21 10:40:25 -080082 // TODO implement an unspecified AudioTrack format then use that.
Phil Burke4d7bb42017-03-28 11:32:39 -070083 audio_format_t format = (getFormat() == AAUDIO_FORMAT_UNSPECIFIED)
Phil Burke1ce4912016-11-21 10:40:25 -080084 ? AUDIO_FORMAT_PCM_FLOAT
Phil Burk5ed503c2017-02-01 09:38:15 -080085 : AAudioConvert_aaudioToAndroidDataFormat(getFormat());
Phil Burke1ce4912016-11-21 10:40:25 -080086
Phil Burke4d7bb42017-03-28 11:32:39 -070087 // Setup the callback if there is one.
88 AudioTrack::callback_t callback = nullptr;
89 void *callbackData = nullptr;
90 // Note that TRANSFER_SYNC does not allow FAST track
91 AudioTrack::transfer_type streamTransferType = AudioTrack::transfer_type::TRANSFER_SYNC;
92 if (builder.getDataCallbackProc() != nullptr) {
93 streamTransferType = AudioTrack::transfer_type::TRANSFER_CALLBACK;
94 callback = getLegacyCallback();
95 callbackData = this;
96
97 notificationFrames = builder.getFramesPerDataCallback();
98 // If the total buffer size is unspecified then base the size on the burst size.
99 if (frameCount == AAUDIO_UNSPECIFIED) {
100 // Take advantage of a special trick that allows us to create a buffer
101 // that is some multiple of the burst size.
102 notificationFrames = 0 - DEFAULT_BURSTS_PER_BUFFER_CAPACITY;
103 }
104 }
105 mCallbackBufferSize = builder.getFramesPerDataCallback();
106
107 ALOGD("AudioStreamTrack::open(), notificationFrames = %d", notificationFrames);
Phil Burke1ce4912016-11-21 10:40:25 -0800108 mAudioTrack = new AudioTrack(
109 (audio_stream_type_t) AUDIO_STREAM_MUSIC,
110 getSampleRate(),
111 format,
112 channelMask,
113 frameCount,
114 flags,
115 callback,
Phil Burke4d7bb42017-03-28 11:32:39 -0700116 callbackData,
117 notificationFrames,
Phil Burke1ce4912016-11-21 10:40:25 -0800118 AUDIO_SESSION_ALLOCATE,
Phil Burke4d7bb42017-03-28 11:32:39 -0700119 streamTransferType
Phil Burke1ce4912016-11-21 10:40:25 -0800120 );
121
122 // Did we get a valid track?
123 status_t status = mAudioTrack->initCheck();
Phil Burkd8bdcab2017-01-03 17:20:30 -0800124 ALOGD("AudioStreamTrack::open(), initCheck() returned %d", status);
Phil Burkdec33ab2017-01-17 14:48:16 -0800125 if (status != NO_ERROR) {
Phil Burke1ce4912016-11-21 10:40:25 -0800126 close();
127 ALOGE("AudioStreamTrack::open(), initCheck() returned %d", status);
Phil Burk5ed503c2017-02-01 09:38:15 -0800128 return AAudioConvert_androidToAAudioResult(status);
Phil Burke1ce4912016-11-21 10:40:25 -0800129 }
130
131 // Get the actual values from the AudioTrack.
132 setSamplesPerFrame(mAudioTrack->channelCount());
133 setSampleRate(mAudioTrack->getSampleRate());
Phil Burke4d7bb42017-03-28 11:32:39 -0700134 aaudio_audio_format_t aaudioFormat =
135 AAudioConvert_androidToAAudioDataFormat(mAudioTrack->format());
136 setFormat(aaudioFormat);
137
138 // We may need to pass the data through a block size adapter to guarantee constant size.
139 if (mCallbackBufferSize != AAUDIO_UNSPECIFIED) {
140 int callbackSizeBytes = getBytesPerFrame() * mCallbackBufferSize;
141 mFixedBlockReader.open(callbackSizeBytes);
142 mBlockAdapter = &mFixedBlockReader;
143 } else {
144 mBlockAdapter = nullptr;
145 }
Phil Burke1ce4912016-11-21 10:40:25 -0800146
Phil Burk5ed503c2017-02-01 09:38:15 -0800147 setState(AAUDIO_STREAM_STATE_OPEN);
Phil Burkc0c70e32017-02-09 13:18:38 -0800148 setDeviceId(mAudioTrack->getRoutedDeviceId());
Phil Burke1ce4912016-11-21 10:40:25 -0800149
Phil Burk5ed503c2017-02-01 09:38:15 -0800150 return AAUDIO_OK;
Phil Burke1ce4912016-11-21 10:40:25 -0800151}
152
Phil Burk5ed503c2017-02-01 09:38:15 -0800153aaudio_result_t AudioStreamTrack::close()
Phil Burke1ce4912016-11-21 10:40:25 -0800154{
155 // TODO maybe add close() or release() to AudioTrack API then call it from here
Phil Burk5ed503c2017-02-01 09:38:15 -0800156 if (getState() != AAUDIO_STREAM_STATE_CLOSED) {
Phil Burke1ce4912016-11-21 10:40:25 -0800157 mAudioTrack.clear(); // TODO is this right?
Phil Burk5ed503c2017-02-01 09:38:15 -0800158 setState(AAUDIO_STREAM_STATE_CLOSED);
Phil Burke1ce4912016-11-21 10:40:25 -0800159 }
Phil Burke4d7bb42017-03-28 11:32:39 -0700160 mFixedBlockReader.close();
Phil Burk5ed503c2017-02-01 09:38:15 -0800161 return AAUDIO_OK;
Phil Burke1ce4912016-11-21 10:40:25 -0800162}
163
Phil Burke4d7bb42017-03-28 11:32:39 -0700164void AudioStreamTrack::processCallback(int event, void *info) {
165
166 switch (event) {
167 case AudioTrack::EVENT_MORE_DATA:
168 processCallbackCommon(AAUDIO_CALLBACK_OPERATION_PROCESS_DATA, info);
169 break;
170
171 // Stream got rerouted so we disconnect.
172 case AudioTrack::EVENT_NEW_IAUDIOTRACK:
173 processCallbackCommon(AAUDIO_CALLBACK_OPERATION_DISCONNECTED, info);
174 break;
175
176 default:
177 break;
178 }
179 return;
180}
181
Phil Burk5ed503c2017-02-01 09:38:15 -0800182aaudio_result_t AudioStreamTrack::requestStart()
Phil Burke1ce4912016-11-21 10:40:25 -0800183{
Phil Burke4d7bb42017-03-28 11:32:39 -0700184 std::lock_guard<std::mutex> lock(mStreamMutex);
185
Phil Burkd8bdcab2017-01-03 17:20:30 -0800186 if (mAudioTrack.get() == nullptr) {
Phil Burk5ed503c2017-02-01 09:38:15 -0800187 return AAUDIO_ERROR_INVALID_STATE;
Phil Burke1ce4912016-11-21 10:40:25 -0800188 }
189 // Get current position so we can detect when the track is playing.
190 status_t err = mAudioTrack->getPosition(&mPositionWhenStarting);
191 if (err != OK) {
Phil Burk5ed503c2017-02-01 09:38:15 -0800192 return AAudioConvert_androidToAAudioResult(err);
Phil Burke1ce4912016-11-21 10:40:25 -0800193 }
Phil Burke4d7bb42017-03-28 11:32:39 -0700194
Phil Burke1ce4912016-11-21 10:40:25 -0800195 err = mAudioTrack->start();
196 if (err != OK) {
Phil Burk5ed503c2017-02-01 09:38:15 -0800197 return AAudioConvert_androidToAAudioResult(err);
Phil Burke1ce4912016-11-21 10:40:25 -0800198 } else {
Phil Burk5ed503c2017-02-01 09:38:15 -0800199 setState(AAUDIO_STREAM_STATE_STARTING);
Phil Burke1ce4912016-11-21 10:40:25 -0800200 }
Phil Burk5ed503c2017-02-01 09:38:15 -0800201 return AAUDIO_OK;
Phil Burke1ce4912016-11-21 10:40:25 -0800202}
203
Phil Burk5ed503c2017-02-01 09:38:15 -0800204aaudio_result_t AudioStreamTrack::requestPause()
Phil Burke1ce4912016-11-21 10:40:25 -0800205{
Phil Burke4d7bb42017-03-28 11:32:39 -0700206 std::lock_guard<std::mutex> lock(mStreamMutex);
207
Phil Burkd8bdcab2017-01-03 17:20:30 -0800208 if (mAudioTrack.get() == nullptr) {
Phil Burk5ed503c2017-02-01 09:38:15 -0800209 return AAUDIO_ERROR_INVALID_STATE;
210 } else if (getState() != AAUDIO_STREAM_STATE_STARTING
211 && getState() != AAUDIO_STREAM_STATE_STARTED) {
Phil Burke4d7bb42017-03-28 11:32:39 -0700212 ALOGE("requestPause(), called when state is %s",
213 AAudio_convertStreamStateToText(getState()));
Phil Burk5ed503c2017-02-01 09:38:15 -0800214 return AAUDIO_ERROR_INVALID_STATE;
Phil Burke1ce4912016-11-21 10:40:25 -0800215 }
Phil Burk5ed503c2017-02-01 09:38:15 -0800216 setState(AAUDIO_STREAM_STATE_PAUSING);
Phil Burke1ce4912016-11-21 10:40:25 -0800217 mAudioTrack->pause();
218 status_t err = mAudioTrack->getPosition(&mPositionWhenPausing);
219 if (err != OK) {
Phil Burk5ed503c2017-02-01 09:38:15 -0800220 return AAudioConvert_androidToAAudioResult(err);
Phil Burke1ce4912016-11-21 10:40:25 -0800221 }
Phil Burk5ed503c2017-02-01 09:38:15 -0800222 return AAUDIO_OK;
Phil Burke1ce4912016-11-21 10:40:25 -0800223}
224
Phil Burk5ed503c2017-02-01 09:38:15 -0800225aaudio_result_t AudioStreamTrack::requestFlush() {
Phil Burke4d7bb42017-03-28 11:32:39 -0700226 std::lock_guard<std::mutex> lock(mStreamMutex);
227
Phil Burkd8bdcab2017-01-03 17:20:30 -0800228 if (mAudioTrack.get() == nullptr) {
Phil Burk5ed503c2017-02-01 09:38:15 -0800229 return AAUDIO_ERROR_INVALID_STATE;
230 } else if (getState() != AAUDIO_STREAM_STATE_PAUSED) {
231 return AAUDIO_ERROR_INVALID_STATE;
Phil Burke1ce4912016-11-21 10:40:25 -0800232 }
Phil Burk5ed503c2017-02-01 09:38:15 -0800233 setState(AAUDIO_STREAM_STATE_FLUSHING);
Phil Burke1ce4912016-11-21 10:40:25 -0800234 incrementFramesRead(getFramesWritten() - getFramesRead());
235 mAudioTrack->flush();
236 mFramesWritten.reset32();
Phil Burk5ed503c2017-02-01 09:38:15 -0800237 return AAUDIO_OK;
Phil Burke1ce4912016-11-21 10:40:25 -0800238}
239
Phil Burk5ed503c2017-02-01 09:38:15 -0800240aaudio_result_t AudioStreamTrack::requestStop() {
Phil Burke4d7bb42017-03-28 11:32:39 -0700241 std::lock_guard<std::mutex> lock(mStreamMutex);
242
Phil Burkd8bdcab2017-01-03 17:20:30 -0800243 if (mAudioTrack.get() == nullptr) {
Phil Burk5ed503c2017-02-01 09:38:15 -0800244 return AAUDIO_ERROR_INVALID_STATE;
Phil Burke1ce4912016-11-21 10:40:25 -0800245 }
Phil Burk5ed503c2017-02-01 09:38:15 -0800246 setState(AAUDIO_STREAM_STATE_STOPPING);
Phil Burke1ce4912016-11-21 10:40:25 -0800247 incrementFramesRead(getFramesWritten() - getFramesRead()); // TODO review
248 mAudioTrack->stop();
249 mFramesWritten.reset32();
Phil Burk5ed503c2017-02-01 09:38:15 -0800250 return AAUDIO_OK;
Phil Burke1ce4912016-11-21 10:40:25 -0800251}
252
Phil Burke4d7bb42017-03-28 11:32:39 -0700253aaudio_result_t AudioStreamTrack::updateStateWhileWaiting()
Phil Burke1ce4912016-11-21 10:40:25 -0800254{
255 status_t err;
Phil Burk5ed503c2017-02-01 09:38:15 -0800256 aaudio_wrapping_frames_t position;
Phil Burke1ce4912016-11-21 10:40:25 -0800257 switch (getState()) {
258 // TODO add better state visibility to AudioTrack
Phil Burk5ed503c2017-02-01 09:38:15 -0800259 case AAUDIO_STREAM_STATE_STARTING:
Phil Burke1ce4912016-11-21 10:40:25 -0800260 if (mAudioTrack->hasStarted()) {
Phil Burk5ed503c2017-02-01 09:38:15 -0800261 setState(AAUDIO_STREAM_STATE_STARTED);
Phil Burke1ce4912016-11-21 10:40:25 -0800262 }
263 break;
Phil Burk5ed503c2017-02-01 09:38:15 -0800264 case AAUDIO_STREAM_STATE_PAUSING:
Phil Burke1ce4912016-11-21 10:40:25 -0800265 if (mAudioTrack->stopped()) {
266 err = mAudioTrack->getPosition(&position);
267 if (err != OK) {
Phil Burk5ed503c2017-02-01 09:38:15 -0800268 return AAudioConvert_androidToAAudioResult(err);
Phil Burke1ce4912016-11-21 10:40:25 -0800269 } else if (position == mPositionWhenPausing) {
270 // Has stream really stopped advancing?
Phil Burk5ed503c2017-02-01 09:38:15 -0800271 setState(AAUDIO_STREAM_STATE_PAUSED);
Phil Burke1ce4912016-11-21 10:40:25 -0800272 }
273 mPositionWhenPausing = position;
274 }
275 break;
Phil Burk5ed503c2017-02-01 09:38:15 -0800276 case AAUDIO_STREAM_STATE_FLUSHING:
Phil Burke1ce4912016-11-21 10:40:25 -0800277 {
278 err = mAudioTrack->getPosition(&position);
279 if (err != OK) {
Phil Burk5ed503c2017-02-01 09:38:15 -0800280 return AAudioConvert_androidToAAudioResult(err);
Phil Burke1ce4912016-11-21 10:40:25 -0800281 } else if (position == 0) {
282 // Advance frames read to match written.
Phil Burk5ed503c2017-02-01 09:38:15 -0800283 setState(AAUDIO_STREAM_STATE_FLUSHED);
Phil Burke1ce4912016-11-21 10:40:25 -0800284 }
285 }
286 break;
Phil Burk5ed503c2017-02-01 09:38:15 -0800287 case AAUDIO_STREAM_STATE_STOPPING:
Phil Burke1ce4912016-11-21 10:40:25 -0800288 if (mAudioTrack->stopped()) {
Phil Burk5ed503c2017-02-01 09:38:15 -0800289 setState(AAUDIO_STREAM_STATE_STOPPED);
Phil Burke1ce4912016-11-21 10:40:25 -0800290 }
291 break;
292 default:
293 break;
294 }
Phil Burk5ed503c2017-02-01 09:38:15 -0800295 return AAUDIO_OK;
Phil Burke1ce4912016-11-21 10:40:25 -0800296}
297
Phil Burk5ed503c2017-02-01 09:38:15 -0800298aaudio_result_t AudioStreamTrack::write(const void *buffer,
Phil Burk3316d5e2017-02-15 11:23:01 -0800299 int32_t numFrames,
300 int64_t timeoutNanoseconds)
Phil Burke1ce4912016-11-21 10:40:25 -0800301{
Phil Burk3316d5e2017-02-15 11:23:01 -0800302 int32_t bytesPerFrame = getBytesPerFrame();
303 int32_t numBytes;
Phil Burk5ed503c2017-02-01 09:38:15 -0800304 aaudio_result_t result = AAudioConvert_framesToBytes(numFrames, bytesPerFrame, &numBytes);
305 if (result != AAUDIO_OK) {
Phil Burke1ce4912016-11-21 10:40:25 -0800306 return result;
307 }
308
309 // TODO add timeout to AudioTrack
310 bool blocking = timeoutNanoseconds > 0;
311 ssize_t bytesWritten = mAudioTrack->write(buffer, numBytes, blocking);
312 if (bytesWritten == WOULD_BLOCK) {
313 return 0;
314 } else if (bytesWritten < 0) {
315 ALOGE("invalid write, returned %d", (int)bytesWritten);
Phil Burk5ed503c2017-02-01 09:38:15 -0800316 return AAudioConvert_androidToAAudioResult(bytesWritten);
Phil Burke1ce4912016-11-21 10:40:25 -0800317 }
Phil Burk3316d5e2017-02-15 11:23:01 -0800318 int32_t framesWritten = (int32_t)(bytesWritten / bytesPerFrame);
Phil Burke1ce4912016-11-21 10:40:25 -0800319 incrementFramesWritten(framesWritten);
320 return framesWritten;
321}
322
Phil Burk3316d5e2017-02-15 11:23:01 -0800323aaudio_result_t AudioStreamTrack::setBufferSize(int32_t requestedFrames)
Phil Burke1ce4912016-11-21 10:40:25 -0800324{
325 ssize_t result = mAudioTrack->setBufferSizeInFrames(requestedFrames);
Phil Burk3316d5e2017-02-15 11:23:01 -0800326 if (result < 0) {
Phil Burk5ed503c2017-02-01 09:38:15 -0800327 return AAudioConvert_androidToAAudioResult(result);
Phil Burke1ce4912016-11-21 10:40:25 -0800328 } else {
Phil Burk3316d5e2017-02-15 11:23:01 -0800329 return result;
Phil Burke1ce4912016-11-21 10:40:25 -0800330 }
331}
332
Phil Burk3316d5e2017-02-15 11:23:01 -0800333int32_t AudioStreamTrack::getBufferSize() const
Phil Burke1ce4912016-11-21 10:40:25 -0800334{
Phil Burk3316d5e2017-02-15 11:23:01 -0800335 return static_cast<int32_t>(mAudioTrack->getBufferSizeInFrames());
Phil Burke1ce4912016-11-21 10:40:25 -0800336}
337
Phil Burk3316d5e2017-02-15 11:23:01 -0800338int32_t AudioStreamTrack::getBufferCapacity() const
Phil Burke1ce4912016-11-21 10:40:25 -0800339{
Phil Burk3316d5e2017-02-15 11:23:01 -0800340 return static_cast<int32_t>(mAudioTrack->frameCount());
Phil Burke1ce4912016-11-21 10:40:25 -0800341}
342
343int32_t AudioStreamTrack::getXRunCount() const
344{
345 return static_cast<int32_t>(mAudioTrack->getUnderrunCount());
346}
347
348int32_t AudioStreamTrack::getFramesPerBurst() const
349{
Phil Burkb5884022017-03-27 15:26:14 -0700350 return static_cast<int32_t>(mAudioTrack->getNotificationPeriodInFrames());
Phil Burke1ce4912016-11-21 10:40:25 -0800351}
352
Phil Burk3316d5e2017-02-15 11:23:01 -0800353int64_t AudioStreamTrack::getFramesRead() {
Phil Burk5ed503c2017-02-01 09:38:15 -0800354 aaudio_wrapping_frames_t position;
Phil Burke1ce4912016-11-21 10:40:25 -0800355 status_t result;
356 switch (getState()) {
Phil Burk5ed503c2017-02-01 09:38:15 -0800357 case AAUDIO_STREAM_STATE_STARTING:
358 case AAUDIO_STREAM_STATE_STARTED:
359 case AAUDIO_STREAM_STATE_STOPPING:
Phil Burk4c5129b2017-04-28 15:17:32 -0700360 case AAUDIO_STREAM_STATE_PAUSING:
361 case AAUDIO_STREAM_STATE_PAUSED:
Phil Burke1ce4912016-11-21 10:40:25 -0800362 result = mAudioTrack->getPosition(&position);
363 if (result == OK) {
364 mFramesRead.update32(position);
365 }
366 break;
367 default:
368 break;
369 }
370 return AudioStream::getFramesRead();
371}
Phil Burk35e80f32017-03-28 10:25:21 -0700372
373aaudio_result_t AudioStreamTrack::getTimestamp(clockid_t clockId,
374 int64_t *framePosition,
375 int64_t *timeNanoseconds) {
376 ExtendedTimestamp extendedTimestamp;
377 status_t status = mAudioTrack->getTimestamp(&extendedTimestamp);
378 if (status != NO_ERROR) {
379 return AAudioConvert_androidToAAudioResult(status);
380 }
381 // TODO Merge common code into AudioStreamLegacy after rebasing.
382 int timebase;
Phil Burke4d7bb42017-03-28 11:32:39 -0700383 switch (clockId) {
Phil Burk35e80f32017-03-28 10:25:21 -0700384 case CLOCK_BOOTTIME:
385 timebase = ExtendedTimestamp::TIMEBASE_BOOTTIME;
386 break;
387 case CLOCK_MONOTONIC:
388 timebase = ExtendedTimestamp::TIMEBASE_MONOTONIC;
389 break;
390 default:
391 ALOGE("getTimestamp() - Unrecognized clock type %d", (int) clockId);
392 return AAUDIO_ERROR_UNEXPECTED_VALUE;
393 break;
394 }
395 status = extendedTimestamp.getBestTimestamp(framePosition, timeNanoseconds, timebase);
396 return AAudioConvert_androidToAAudioResult(status);
397}