1e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk/*
2e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk * Copyright 2016 The Android Open Source Project
3e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk *
4e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk * Licensed under the Apache License, Version 2.0 (the "License");
5e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk * you may not use this file except in compliance with the License.
6e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk * You may obtain a copy of the License at
7e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk *
8e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk *      http://www.apache.org/licenses/LICENSE-2.0
9e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk *
10e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk * Unless required by applicable law or agreed to in writing, software
11e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk * distributed under the License is distributed on an "AS IS" BASIS,
12e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk * See the License for the specific language governing permissions and
14e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk * limitations under the License.
15e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk */
16e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk
17cf5f6d2825d9a8430a291042ca9c6f68e5b666d0Phil Burk#define LOG_TAG "AAudio"
18e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk//#define LOG_NDEBUG 0
19e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk#include <utils/Log.h>
20e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk
21e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk#include <stdint.h>
22e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk#include <media/AudioTrack.h>
23e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk
24e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk#include <aaudio/AAudio.h>
25c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk#include "utility/AudioClock.h"
26e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk#include "legacy/AudioStreamLegacy.h"
27e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk#include "legacy/AudioStreamTrack.h"
28e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk#include "utility/FixedBlockReader.h"
29e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk
30e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burkusing namespace android;
315ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkusing namespace aaudio;
32e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk
33e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk// Arbitrary and somewhat generous number of bursts.
34e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk#define DEFAULT_BURSTS_PER_BUFFER_CAPACITY     8
35e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk
36e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk/*
37e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk * Create a stream that uses the AudioTrack.
38e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk */
39e1ce491a25faf06fdeab00dd938515f71f28b095Phil BurkAudioStreamTrack::AudioStreamTrack()
40e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk    : AudioStreamLegacy()
41e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk    , mFixedBlockReader(*this)
42e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk{
43e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk}
44e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk
45e1ce491a25faf06fdeab00dd938515f71f28b095Phil BurkAudioStreamTrack::~AudioStreamTrack()
46e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk{
475ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk    const aaudio_stream_state_t state = getState();
485ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk    bool bad = !(state == AAUDIO_STREAM_STATE_UNINITIALIZED || state == AAUDIO_STREAM_STATE_CLOSED);
49e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    ALOGE_IF(bad, "stream not closed, in state %d", state);
50e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk}
51e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk
525ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkaaudio_result_t AudioStreamTrack::open(const AudioStreamBuilder& builder)
53e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk{
545ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk    aaudio_result_t result = AAUDIO_OK;
55e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk
56e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    result = AudioStream::open(builder);
57e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    if (result != OK) {
58e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk        return result;
59e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    }
60e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk
61e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    // Try to create an AudioTrack
625204d315c6c6f53188f8d1414dd1b55b6c90142bPhil Burk    // Use stereo if unspecified.
635ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk    int32_t samplesPerFrame = (getSamplesPerFrame() == AAUDIO_UNSPECIFIED)
64e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk                              ? 2 : getSamplesPerFrame();
65e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    audio_channel_mask_t channelMask = audio_channel_out_mask_from_count(samplesPerFrame);
66e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk
67e2fbb59e729f6c3cade3b531f6f6411417ccbf40Phil Burk    audio_output_flags_t flags = AUDIO_OUTPUT_FLAG_NONE;
6830a707773a043e5eebd552d369c0882f886b67e5Phil Burk    aaudio_performance_mode_t perfMode = getPerformanceMode();
6930a707773a043e5eebd552d369c0882f886b67e5Phil Burk    switch(perfMode) {
70e2fbb59e729f6c3cade3b531f6f6411417ccbf40Phil Burk        case AAUDIO_PERFORMANCE_MODE_LOW_LATENCY:
71e2fbb59e729f6c3cade3b531f6f6411417ccbf40Phil Burk            // Bypass the normal mixer and go straight to the FAST mixer.
72e2fbb59e729f6c3cade3b531f6f6411417ccbf40Phil Burk            flags = (audio_output_flags_t)(AUDIO_OUTPUT_FLAG_FAST | AUDIO_OUTPUT_FLAG_RAW);
73e2fbb59e729f6c3cade3b531f6f6411417ccbf40Phil Burk            break;
74e2fbb59e729f6c3cade3b531f6f6411417ccbf40Phil Burk
75e2fbb59e729f6c3cade3b531f6f6411417ccbf40Phil Burk        case AAUDIO_PERFORMANCE_MODE_POWER_SAVING:
76e2fbb59e729f6c3cade3b531f6f6411417ccbf40Phil Burk            // This uses a mixer that wakes up less often than the FAST mixer.
77e2fbb59e729f6c3cade3b531f6f6411417ccbf40Phil Burk            flags = AUDIO_OUTPUT_FLAG_DEEP_BUFFER;
78e2fbb59e729f6c3cade3b531f6f6411417ccbf40Phil Burk            break;
79e2fbb59e729f6c3cade3b531f6f6411417ccbf40Phil Burk
80e2fbb59e729f6c3cade3b531f6f6411417ccbf40Phil Burk        case AAUDIO_PERFORMANCE_MODE_NONE:
81e2fbb59e729f6c3cade3b531f6f6411417ccbf40Phil Burk        default:
82e2fbb59e729f6c3cade3b531f6f6411417ccbf40Phil Burk            // No flags. Use a normal mixer in front of the FAST mixer.
83e2fbb59e729f6c3cade3b531f6f6411417ccbf40Phil Burk            break;
84e2fbb59e729f6c3cade3b531f6f6411417ccbf40Phil Burk    }
85e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk
86cf5f6d2825d9a8430a291042ca9c6f68e5b666d0Phil Burk    size_t frameCount = (size_t)builder.getBufferCapacity();
87e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk
88e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk    int32_t notificationFrames = 0;
89e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk
90e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk    audio_format_t format = (getFormat() == AAUDIO_FORMAT_UNSPECIFIED)
91e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk            ? AUDIO_FORMAT_PCM_FLOAT
925ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk            : AAudioConvert_aaudioToAndroidDataFormat(getFormat());
93e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk
94e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk    // Setup the callback if there is one.
95e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk    AudioTrack::callback_t callback = nullptr;
96e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk    void *callbackData = nullptr;
97e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk    // Note that TRANSFER_SYNC does not allow FAST track
98e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk    AudioTrack::transfer_type streamTransferType = AudioTrack::transfer_type::TRANSFER_SYNC;
99e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk    if (builder.getDataCallbackProc() != nullptr) {
100e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk        streamTransferType = AudioTrack::transfer_type::TRANSFER_CALLBACK;
101e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk        callback = getLegacyCallback();
102e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk        callbackData = this;
103e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk
104e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk        // If the total buffer size is unspecified then base the size on the burst size.
1054485d41bcded0eceec7ec97d50aa2b0e702397a0Phil Burk        if (frameCount == 0
1064485d41bcded0eceec7ec97d50aa2b0e702397a0Phil Burk                && ((flags & AUDIO_OUTPUT_FLAG_FAST) != 0)) {
107e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk            // Take advantage of a special trick that allows us to create a buffer
108e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk            // that is some multiple of the burst size.
109e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk            notificationFrames = 0 - DEFAULT_BURSTS_PER_BUFFER_CAPACITY;
1104485d41bcded0eceec7ec97d50aa2b0e702397a0Phil Burk        } else {
1114485d41bcded0eceec7ec97d50aa2b0e702397a0Phil Burk            notificationFrames = builder.getFramesPerDataCallback();
112e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk        }
113e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk    }
114e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk    mCallbackBufferSize = builder.getFramesPerDataCallback();
115e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk
116cf5f6d2825d9a8430a291042ca9c6f68e5b666d0Phil Burk    ALOGD("AudioStreamTrack::open(), request notificationFrames = %d, frameCount = %u",
117cf5f6d2825d9a8430a291042ca9c6f68e5b666d0Phil Burk          notificationFrames, (uint)frameCount);
118fb00fc77f59ed5ebec4d38bac666e6521b6c1de0Eric Laurent    mAudioTrack = new AudioTrack();
119fb00fc77f59ed5ebec4d38bac666e6521b6c1de0Eric Laurent    if (getDeviceId() != AAUDIO_UNSPECIFIED) {
120fb00fc77f59ed5ebec4d38bac666e6521b6c1de0Eric Laurent        mAudioTrack->setOutputDevice(getDeviceId());
121fb00fc77f59ed5ebec4d38bac666e6521b6c1de0Eric Laurent    }
122fb00fc77f59ed5ebec4d38bac666e6521b6c1de0Eric Laurent    mAudioTrack->set(
123e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk            (audio_stream_type_t) AUDIO_STREAM_MUSIC,
124e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk            getSampleRate(),
125e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk            format,
126e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk            channelMask,
127e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk            frameCount,
128e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk            flags,
129e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk            callback,
130e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk            callbackData,
131e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk            notificationFrames,
132fb00fc77f59ed5ebec4d38bac666e6521b6c1de0Eric Laurent            0 /*sharedBuffer*/,
133fb00fc77f59ed5ebec4d38bac666e6521b6c1de0Eric Laurent            false /*threadCanCallJava*/,
134e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk            AUDIO_SESSION_ALLOCATE,
135e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk            streamTransferType
136e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk            );
137e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk
138e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    // Did we get a valid track?
139e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    status_t status = mAudioTrack->initCheck();
140dec33abe3739b2116ef6fbac36f7ca5d26f9d190Phil Burk    if (status != NO_ERROR) {
141e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk        close();
142e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk        ALOGE("AudioStreamTrack::open(), initCheck() returned %d", status);
1435ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk        return AAudioConvert_androidToAAudioResult(status);
144e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    }
145e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk
1461d32e9f8e5ba52d69c6319270c8a63a995d2c4f2Eric Laurent    //TrackPlayerBase init
1471d32e9f8e5ba52d69c6319270c8a63a995d2c4f2Eric Laurent    init(mAudioTrack.get(), PLAYER_TYPE_AAUDIO, AUDIO_USAGE_MEDIA);
1481d32e9f8e5ba52d69c6319270c8a63a995d2c4f2Eric Laurent
149e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    // Get the actual values from the AudioTrack.
150e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    setSamplesPerFrame(mAudioTrack->channelCount());
1519dca9824da74d50be02bc81f539cc77b7bde678aPhil Burk    aaudio_format_t aaudioFormat =
152e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk            AAudioConvert_androidToAAudioDataFormat(mAudioTrack->format());
153e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk    setFormat(aaudioFormat);
154e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk
155cf5f6d2825d9a8430a291042ca9c6f68e5b666d0Phil Burk    int32_t actualSampleRate = mAudioTrack->getSampleRate();
156cf5f6d2825d9a8430a291042ca9c6f68e5b666d0Phil Burk    ALOGW_IF(actualSampleRate != getSampleRate(),
157cf5f6d2825d9a8430a291042ca9c6f68e5b666d0Phil Burk             "AudioStreamTrack::open() sampleRate changed from %d to %d",
158cf5f6d2825d9a8430a291042ca9c6f68e5b666d0Phil Burk             getSampleRate(), actualSampleRate);
159cf5f6d2825d9a8430a291042ca9c6f68e5b666d0Phil Burk    setSampleRate(actualSampleRate);
160cf5f6d2825d9a8430a291042ca9c6f68e5b666d0Phil Burk
161e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk    // We may need to pass the data through a block size adapter to guarantee constant size.
162e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk    if (mCallbackBufferSize != AAUDIO_UNSPECIFIED) {
163e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk        int callbackSizeBytes = getBytesPerFrame() * mCallbackBufferSize;
164e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk        mFixedBlockReader.open(callbackSizeBytes);
165e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk        mBlockAdapter = &mFixedBlockReader;
166e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk    } else {
167e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk        mBlockAdapter = nullptr;
168e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk    }
169e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk
1705ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk    setState(AAUDIO_STREAM_STATE_OPEN);
171c0c70e3c7dd10bc2c0caffcab1f3f5fb406b35fbPhil Burk    setDeviceId(mAudioTrack->getRoutedDeviceId());
172fb00fc77f59ed5ebec4d38bac666e6521b6c1de0Eric Laurent    mAudioTrack->addAudioDeviceCallback(mDeviceCallback);
173e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk
17430a707773a043e5eebd552d369c0882f886b67e5Phil Burk    // Update performance mode based on the actual stream.
17530a707773a043e5eebd552d369c0882f886b67e5Phil Burk    // For example, if the sample rate is not allowed then you won't get a FAST track.
17630a707773a043e5eebd552d369c0882f886b67e5Phil Burk    audio_output_flags_t actualFlags = mAudioTrack->getFlags();
17730a707773a043e5eebd552d369c0882f886b67e5Phil Burk    aaudio_performance_mode_t actualPerformanceMode = AAUDIO_PERFORMANCE_MODE_NONE;
17830a707773a043e5eebd552d369c0882f886b67e5Phil Burk    if ((actualFlags & (AUDIO_OUTPUT_FLAG_FAST | AUDIO_OUTPUT_FLAG_RAW))
17930a707773a043e5eebd552d369c0882f886b67e5Phil Burk        == (AUDIO_OUTPUT_FLAG_FAST | AUDIO_OUTPUT_FLAG_RAW)) {
18030a707773a043e5eebd552d369c0882f886b67e5Phil Burk        actualPerformanceMode = AAUDIO_PERFORMANCE_MODE_LOW_LATENCY;
18130a707773a043e5eebd552d369c0882f886b67e5Phil Burk
18230a707773a043e5eebd552d369c0882f886b67e5Phil Burk    } else if ((actualFlags & AUDIO_OUTPUT_FLAG_DEEP_BUFFER) != 0) {
18330a707773a043e5eebd552d369c0882f886b67e5Phil Burk        actualPerformanceMode = AAUDIO_PERFORMANCE_MODE_POWER_SAVING;
18430a707773a043e5eebd552d369c0882f886b67e5Phil Burk    }
18530a707773a043e5eebd552d369c0882f886b67e5Phil Burk    setPerformanceMode(actualPerformanceMode);
18630a707773a043e5eebd552d369c0882f886b67e5Phil Burk    // Log warning if we did not get what we asked for.
18730a707773a043e5eebd552d369c0882f886b67e5Phil Burk    ALOGW_IF(actualFlags != flags,
18830a707773a043e5eebd552d369c0882f886b67e5Phil Burk             "AudioStreamTrack::open() flags changed from 0x%08X to 0x%08X",
18930a707773a043e5eebd552d369c0882f886b67e5Phil Burk             flags, actualFlags);
19030a707773a043e5eebd552d369c0882f886b67e5Phil Burk    ALOGW_IF(actualPerformanceMode != perfMode,
19130a707773a043e5eebd552d369c0882f886b67e5Phil Burk             "AudioStreamTrack::open() perfMode changed from %d to %d",
19230a707773a043e5eebd552d369c0882f886b67e5Phil Burk             perfMode, actualPerformanceMode);
19330a707773a043e5eebd552d369c0882f886b67e5Phil Burk
1945ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk    return AAUDIO_OK;
195e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk}
196e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk
1975ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkaaudio_result_t AudioStreamTrack::close()
198e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk{
1995ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk    if (getState() != AAUDIO_STREAM_STATE_CLOSED) {
2001d32e9f8e5ba52d69c6319270c8a63a995d2c4f2Eric Laurent        destroy();
2015ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk        setState(AAUDIO_STREAM_STATE_CLOSED);
202e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    }
203e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk    mFixedBlockReader.close();
2045ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk    return AAUDIO_OK;
205e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk}
206e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk
207e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burkvoid AudioStreamTrack::processCallback(int event, void *info) {
208e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk
209e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk    switch (event) {
210e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk        case AudioTrack::EVENT_MORE_DATA:
211e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk            processCallbackCommon(AAUDIO_CALLBACK_OPERATION_PROCESS_DATA, info);
212e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk            break;
213e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk
214e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk            // Stream got rerouted so we disconnect.
215e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk        case AudioTrack::EVENT_NEW_IAUDIOTRACK:
216e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk            processCallbackCommon(AAUDIO_CALLBACK_OPERATION_DISCONNECTED, info);
217e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk            break;
218e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk
219e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk        default:
220e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk            break;
221e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk    }
222e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk    return;
223e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk}
224e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk
2255ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkaaudio_result_t AudioStreamTrack::requestStart()
226e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk{
227e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk    std::lock_guard<std::mutex> lock(mStreamMutex);
228e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk
229d8bdcabbac30d48ed17fa76c83cb9ee95c290a07Phil Burk    if (mAudioTrack.get() == nullptr) {
2305ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk        return AAUDIO_ERROR_INVALID_STATE;
231e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    }
232e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    // Get current position so we can detect when the track is playing.
233e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    status_t err = mAudioTrack->getPosition(&mPositionWhenStarting);
234e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    if (err != OK) {
2355ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk        return AAudioConvert_androidToAAudioResult(err);
236e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    }
237e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk
2381d32e9f8e5ba52d69c6319270c8a63a995d2c4f2Eric Laurent    err = startWithStatus();
239e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    if (err != OK) {
2405ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk        return AAudioConvert_androidToAAudioResult(err);
241e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    } else {
242fb00fc77f59ed5ebec4d38bac666e6521b6c1de0Eric Laurent        onStart();
2435ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk        setState(AAUDIO_STREAM_STATE_STARTING);
244e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    }
2455ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk    return AAUDIO_OK;
246e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk}
247e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk
2485ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkaaudio_result_t AudioStreamTrack::requestPause()
249e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk{
250e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk    std::lock_guard<std::mutex> lock(mStreamMutex);
251e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk
252d8bdcabbac30d48ed17fa76c83cb9ee95c290a07Phil Burk    if (mAudioTrack.get() == nullptr) {
2535ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk        return AAUDIO_ERROR_INVALID_STATE;
2545ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk    } else if (getState() != AAUDIO_STREAM_STATE_STARTING
2555ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk            && getState() != AAUDIO_STREAM_STATE_STARTED) {
256e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk        ALOGE("requestPause(), called when state is %s",
257e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk              AAudio_convertStreamStateToText(getState()));
2585ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk        return AAUDIO_ERROR_INVALID_STATE;
259e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    }
260fb00fc77f59ed5ebec4d38bac666e6521b6c1de0Eric Laurent    onStop();
2615ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk    setState(AAUDIO_STREAM_STATE_PAUSING);
2621d32e9f8e5ba52d69c6319270c8a63a995d2c4f2Eric Laurent    pause();
263e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    status_t err = mAudioTrack->getPosition(&mPositionWhenPausing);
264e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    if (err != OK) {
2655ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk        return AAudioConvert_androidToAAudioResult(err);
266e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    }
2675ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk    return AAUDIO_OK;
268e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk}
269e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk
2705ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkaaudio_result_t AudioStreamTrack::requestFlush() {
271e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk    std::lock_guard<std::mutex> lock(mStreamMutex);
272e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk
273d8bdcabbac30d48ed17fa76c83cb9ee95c290a07Phil Burk    if (mAudioTrack.get() == nullptr) {
2745ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk        return AAUDIO_ERROR_INVALID_STATE;
2755ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk    } else if (getState() != AAUDIO_STREAM_STATE_PAUSED) {
2765ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk        return AAUDIO_ERROR_INVALID_STATE;
277e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    }
2785ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk    setState(AAUDIO_STREAM_STATE_FLUSHING);
279e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    incrementFramesRead(getFramesWritten() - getFramesRead());
280e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    mAudioTrack->flush();
281e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    mFramesWritten.reset32();
2825ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk    return AAUDIO_OK;
283e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk}
284e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk
2855ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkaaudio_result_t AudioStreamTrack::requestStop() {
286e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk    std::lock_guard<std::mutex> lock(mStreamMutex);
287e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burk
288d8bdcabbac30d48ed17fa76c83cb9ee95c290a07Phil Burk    if (mAudioTrack.get() == nullptr) {
2895ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk        return AAUDIO_ERROR_INVALID_STATE;
290e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    }
291fb00fc77f59ed5ebec4d38bac666e6521b6c1de0Eric Laurent    onStop();
2925ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk    setState(AAUDIO_STREAM_STATE_STOPPING);
293e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    incrementFramesRead(getFramesWritten() - getFramesRead()); // TODO review
2941d32e9f8e5ba52d69c6319270c8a63a995d2c4f2Eric Laurent    stop();
295e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    mFramesWritten.reset32();
2965ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk    return AAUDIO_OK;
297e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk}
298e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk
299e4d7bb418df0fdc4c708c334ba3601f5ed8d89b3Phil Burkaaudio_result_t AudioStreamTrack::updateStateWhileWaiting()
300e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk{
301e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    status_t err;
3025ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk    aaudio_wrapping_frames_t position;
303e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    switch (getState()) {
304e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    // TODO add better state visibility to AudioTrack
3055ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk    case AAUDIO_STREAM_STATE_STARTING:
306e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk        if (mAudioTrack->hasStarted()) {
3075ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk            setState(AAUDIO_STREAM_STATE_STARTED);
308e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk        }
309e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk        break;
3105ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk    case AAUDIO_STREAM_STATE_PAUSING:
311e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk        if (mAudioTrack->stopped()) {
312e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk            err = mAudioTrack->getPosition(&position);
313e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk            if (err != OK) {
3145ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk                return AAudioConvert_androidToAAudioResult(err);
315e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk            } else if (position == mPositionWhenPausing) {
316e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk                // Has stream really stopped advancing?
3175ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk                setState(AAUDIO_STREAM_STATE_PAUSED);
318e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk            }
319e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk            mPositionWhenPausing = position;
320e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk        }
321e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk        break;
3225ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk    case AAUDIO_STREAM_STATE_FLUSHING:
323e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk        {
324e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk            err = mAudioTrack->getPosition(&position);
325e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk            if (err != OK) {
3265ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk                return AAudioConvert_androidToAAudioResult(err);
327e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk            } else if (position == 0) {
3285204d315c6c6f53188f8d1414dd1b55b6c90142bPhil Burk                // TODO Advance frames read to match written.
3295ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk                setState(AAUDIO_STREAM_STATE_FLUSHED);
330e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk            }
331e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk        }
332e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk        break;
3335ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk    case AAUDIO_STREAM_STATE_STOPPING:
334e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk        if (mAudioTrack->stopped()) {
3355ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk            setState(AAUDIO_STREAM_STATE_STOPPED);
336e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk        }
337e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk        break;
338e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    default:
339e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk        break;
340e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    }
3415ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk    return AAUDIO_OK;
342e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk}
343e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk
3445ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burkaaudio_result_t AudioStreamTrack::write(const void *buffer,
3453316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk                                      int32_t numFrames,
3463316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk                                      int64_t timeoutNanoseconds)
347e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk{
3483316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk    int32_t bytesPerFrame = getBytesPerFrame();
3493316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk    int32_t numBytes;
3505ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk    aaudio_result_t result = AAudioConvert_framesToBytes(numFrames, bytesPerFrame, &numBytes);
3515ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk    if (result != AAUDIO_OK) {
352e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk        return result;
353e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    }
354e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk
355fb00fc77f59ed5ebec4d38bac666e6521b6c1de0Eric Laurent    if (getState() == AAUDIO_STREAM_STATE_DISCONNECTED) {
356fb00fc77f59ed5ebec4d38bac666e6521b6c1de0Eric Laurent        return AAUDIO_ERROR_DISCONNECTED;
357fb00fc77f59ed5ebec4d38bac666e6521b6c1de0Eric Laurent    }
358fb00fc77f59ed5ebec4d38bac666e6521b6c1de0Eric Laurent
359e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    // TODO add timeout to AudioTrack
360e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    bool blocking = timeoutNanoseconds > 0;
361e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    ssize_t bytesWritten = mAudioTrack->write(buffer, numBytes, blocking);
362e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    if (bytesWritten == WOULD_BLOCK) {
363e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk        return 0;
364e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    } else if (bytesWritten < 0) {
365e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk        ALOGE("invalid write, returned %d", (int)bytesWritten);
366fb00fc77f59ed5ebec4d38bac666e6521b6c1de0Eric Laurent        // in this context, a DEAD_OBJECT is more likely to be a disconnect notification due to
367fb00fc77f59ed5ebec4d38bac666e6521b6c1de0Eric Laurent        // AudioTrack invalidation
368fb00fc77f59ed5ebec4d38bac666e6521b6c1de0Eric Laurent        if (bytesWritten == DEAD_OBJECT) {
369fb00fc77f59ed5ebec4d38bac666e6521b6c1de0Eric Laurent            setState(AAUDIO_STREAM_STATE_DISCONNECTED);
370fb00fc77f59ed5ebec4d38bac666e6521b6c1de0Eric Laurent            return AAUDIO_ERROR_DISCONNECTED;
371fb00fc77f59ed5ebec4d38bac666e6521b6c1de0Eric Laurent        }
3725ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk        return AAudioConvert_androidToAAudioResult(bytesWritten);
373e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    }
3743316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk    int32_t framesWritten = (int32_t)(bytesWritten / bytesPerFrame);
375e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    incrementFramesWritten(framesWritten);
376e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    return framesWritten;
377e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk}
378e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk
3793316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burkaaudio_result_t AudioStreamTrack::setBufferSize(int32_t requestedFrames)
380e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk{
381e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    ssize_t result = mAudioTrack->setBufferSizeInFrames(requestedFrames);
3823316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk    if (result < 0) {
3835ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk        return AAudioConvert_androidToAAudioResult(result);
384e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    } else {
3853316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk        return result;
386e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    }
387e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk}
388e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk
3893316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burkint32_t AudioStreamTrack::getBufferSize() const
390e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk{
3913316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk    return static_cast<int32_t>(mAudioTrack->getBufferSizeInFrames());
392e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk}
393e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk
3943316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burkint32_t AudioStreamTrack::getBufferCapacity() const
395e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk{
3963316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burk    return static_cast<int32_t>(mAudioTrack->frameCount());
397e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk}
398e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk
399e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burkint32_t AudioStreamTrack::getXRunCount() const
400e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk{
401e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    return static_cast<int32_t>(mAudioTrack->getUnderrunCount());
402e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk}
403e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk
404e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burkint32_t AudioStreamTrack::getFramesPerBurst() const
405e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk{
406b588402d48c9634fa72e7e13ca6d6f2a0766cb98Phil Burk    return static_cast<int32_t>(mAudioTrack->getNotificationPeriodInFrames());
407e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk}
408e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk
4093316d5e6d375a4f09c681205e9094d30a0bfc4a2Phil Burkint64_t AudioStreamTrack::getFramesRead() {
4105ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk    aaudio_wrapping_frames_t position;
411e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    status_t result;
412e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    switch (getState()) {
4135ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk    case AAUDIO_STREAM_STATE_STARTING:
4145ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk    case AAUDIO_STREAM_STATE_STARTED:
4155ed503c7a66c90f93759c90237a9b432dbd93f9fPhil Burk    case AAUDIO_STREAM_STATE_STOPPING:
4164c5129b410884ec0400cbe65fce56d0ade12d11bPhil Burk    case AAUDIO_STREAM_STATE_PAUSING:
4174c5129b410884ec0400cbe65fce56d0ade12d11bPhil Burk    case AAUDIO_STREAM_STATE_PAUSED:
418e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk        result = mAudioTrack->getPosition(&position);
419e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk        if (result == OK) {
420e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk            mFramesRead.update32(position);
421e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk        }
422e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk        break;
423e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    default:
424e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk        break;
425e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    }
426e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk    return AudioStream::getFramesRead();
427e1ce491a25faf06fdeab00dd938515f71f28b095Phil Burk}
42835e80f34a9649752fceafa53e2094cd8eda50a0aPhil Burk
42935e80f34a9649752fceafa53e2094cd8eda50a0aPhil Burkaaudio_result_t AudioStreamTrack::getTimestamp(clockid_t clockId,
43035e80f34a9649752fceafa53e2094cd8eda50a0aPhil Burk                                     int64_t *framePosition,
43135e80f34a9649752fceafa53e2094cd8eda50a0aPhil Burk                                     int64_t *timeNanoseconds) {
43235e80f34a9649752fceafa53e2094cd8eda50a0aPhil Burk    ExtendedTimestamp extendedTimestamp;
43335e80f34a9649752fceafa53e2094cd8eda50a0aPhil Burk    status_t status = mAudioTrack->getTimestamp(&extendedTimestamp);
43435e80f34a9649752fceafa53e2094cd8eda50a0aPhil Burk    if (status != NO_ERROR) {
43535e80f34a9649752fceafa53e2094cd8eda50a0aPhil Burk        return AAudioConvert_androidToAAudioResult(status);
43635e80f34a9649752fceafa53e2094cd8eda50a0aPhil Burk    }
4375204d315c6c6f53188f8d1414dd1b55b6c90142bPhil Burk    return getBestTimestamp(clockId, framePosition, timeNanoseconds, &extendedTimestamp);
43835e80f34a9649752fceafa53e2094cd8eda50a0aPhil Burk}
439