199e53b86eebb605b70dd7591b89bf61a9414ed0eGlenn Kasten/*
289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project**
389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project** Copyright 2007, The Android Open Source Project
489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project**
589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project** Licensed under the Apache License, Version 2.0 (the "License");
689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project** you may not use this file except in compliance with the License.
789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project** You may obtain a copy of the License at
889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project**
989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project**     http://www.apache.org/licenses/LICENSE-2.0
1089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project**
1189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project** Unless required by applicable law or agreed to in writing, software
1289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project** distributed under the License is distributed on an "AS IS" BASIS,
1389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project** See the License for the specific language governing permissions and
1589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project** limitations under the License.
1689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project*/
1789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
1889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project//#define LOG_NDEBUG 0
1989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project#define LOG_TAG "AudioTrack"
2089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
2134fb29696b0f3abf61b10f8d053b1f33d501de0aMark Salyzyn#include <inttypes.h>
22c56f3426099a3cf2d07ccff8886050c7fbce140fGlenn Kasten#include <math.h>
2389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project#include <sys/resource.h>
2434fb29696b0f3abf61b10f8d053b1f33d501de0aMark Salyzyn
259f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten#include <audio_utils/primitives.h>
269f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten#include <binder/IPCThreadState.h>
2789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project#include <media/AudioTrack.h>
2889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project#include <utils/Log.h>
299f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten#include <private/media/AudioTrackShared.h>
301ab85ec401801ef9a9184650d0f5a1639b45eeb9Glenn Kasten#include <media/IAudioFlinger.h>
31e83b55dc29ca16092ba02f36f55fa6e0e37fd78cEric Laurent#include <media/AudioPolicyHelper.h>
32cd04484f4837b8ca0041d118286ab6a98e84fc75Andy Hung#include <media/AudioResamplerPublic.h>
33fce7a473248381cc83a01855f92581077d3c9ee2Dima Zavin
34b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald#define WAIT_PERIOD_MS                  10
35b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald#define WAIT_STREAM_END_TIMEOUT_SEC     120
3653c3b5fc1afe162a8669cb3d27d6bb14e1847e39Andy Hungstatic const int kMaxLoopCountNotifications = 32;
37511754b5839fd9b09fc56b89ae007fbc39084a33Glenn Kasten
3889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectnamespace android {
3933005a932c60a0780fe9b7307d5988df3d9f6c26Chia-chi Yeh// ---------------------------------------------------------------------------
4033005a932c60a0780fe9b7307d5988df3d9f6c26Chia-chi Yeh
41a7f03353d5f172016f324e2a01f301cca6794152Andy Hung// TODO: Move to a separate .h
42a7f03353d5f172016f324e2a01f301cca6794152Andy Hung
434ede21d9c1f957baf5e561849ff9bbe4bcbefc20Andy Hungtemplate <typename T>
44a7f03353d5f172016f324e2a01f301cca6794152Andy Hungstatic inline const T &min(const T &x, const T &y) {
454ede21d9c1f957baf5e561849ff9bbe4bcbefc20Andy Hung    return x < y ? x : y;
464ede21d9c1f957baf5e561849ff9bbe4bcbefc20Andy Hung}
474ede21d9c1f957baf5e561849ff9bbe4bcbefc20Andy Hung
48a7f03353d5f172016f324e2a01f301cca6794152Andy Hungtemplate <typename T>
49a7f03353d5f172016f324e2a01f301cca6794152Andy Hungstatic inline const T &max(const T &x, const T &y) {
50a7f03353d5f172016f324e2a01f301cca6794152Andy Hung    return x > y ? x : y;
51a7f03353d5f172016f324e2a01f301cca6794152Andy Hung}
52a7f03353d5f172016f324e2a01f301cca6794152Andy Hung
53a7f03353d5f172016f324e2a01f301cca6794152Andy Hungstatic inline nsecs_t framesToNanoseconds(ssize_t frames, uint32_t sampleRate, float speed)
54a7f03353d5f172016f324e2a01f301cca6794152Andy Hung{
55a7f03353d5f172016f324e2a01f301cca6794152Andy Hung    return ((double)frames * 1000000000) / ((double)sampleRate * speed);
56a7f03353d5f172016f324e2a01f301cca6794152Andy Hung}
57a7f03353d5f172016f324e2a01f301cca6794152Andy Hung
587f1bc8af1c46695191bf7e2aba6467f3616629c0Andy Hungstatic int64_t convertTimespecToUs(const struct timespec &tv)
597f1bc8af1c46695191bf7e2aba6467f3616629c0Andy Hung{
607f1bc8af1c46695191bf7e2aba6467f3616629c0Andy Hung    return tv.tv_sec * 1000000ll + tv.tv_nsec / 1000;
617f1bc8af1c46695191bf7e2aba6467f3616629c0Andy Hung}
627f1bc8af1c46695191bf7e2aba6467f3616629c0Andy Hung
637f1bc8af1c46695191bf7e2aba6467f3616629c0Andy Hung// current monotonic time in microseconds.
647f1bc8af1c46695191bf7e2aba6467f3616629c0Andy Hungstatic int64_t getNowUs()
657f1bc8af1c46695191bf7e2aba6467f3616629c0Andy Hung{
667f1bc8af1c46695191bf7e2aba6467f3616629c0Andy Hung    struct timespec tv;
677f1bc8af1c46695191bf7e2aba6467f3616629c0Andy Hung    (void) clock_gettime(CLOCK_MONOTONIC, &tv);
687f1bc8af1c46695191bf7e2aba6467f3616629c0Andy Hung    return convertTimespecToUs(tv);
697f1bc8af1c46695191bf7e2aba6467f3616629c0Andy Hung}
707f1bc8af1c46695191bf7e2aba6467f3616629c0Andy Hung
7126145643ce22d797b3b1675c82c47a2d8c79ecaaAndy Hung// FIXME: we don't use the pitch setting in the time stretcher (not working);
7226145643ce22d797b3b1675c82c47a2d8c79ecaaAndy Hung// instead we emulate it using our sample rate converter.
7326145643ce22d797b3b1675c82c47a2d8c79ecaaAndy Hungstatic const bool kFixPitch = true; // enable pitch fix
7426145643ce22d797b3b1675c82c47a2d8c79ecaaAndy Hungstatic inline uint32_t adjustSampleRate(uint32_t sampleRate, float pitch)
7526145643ce22d797b3b1675c82c47a2d8c79ecaaAndy Hung{
7626145643ce22d797b3b1675c82c47a2d8c79ecaaAndy Hung    return kFixPitch ? (sampleRate * pitch + 0.5) : sampleRate;
7726145643ce22d797b3b1675c82c47a2d8c79ecaaAndy Hung}
7826145643ce22d797b3b1675c82c47a2d8c79ecaaAndy Hung
7926145643ce22d797b3b1675c82c47a2d8c79ecaaAndy Hungstatic inline float adjustSpeed(float speed, float pitch)
8026145643ce22d797b3b1675c82c47a2d8c79ecaaAndy Hung{
816c7f062d3149d6890daaee64828959ad6f61ea54Ricardo Garcia    return kFixPitch ? speed / max(pitch, AUDIO_TIMESTRETCH_PITCH_MIN_DELTA) : speed;
8226145643ce22d797b3b1675c82c47a2d8c79ecaaAndy Hung}
8326145643ce22d797b3b1675c82c47a2d8c79ecaaAndy Hung
8426145643ce22d797b3b1675c82c47a2d8c79ecaaAndy Hungstatic inline float adjustPitch(float pitch)
8526145643ce22d797b3b1675c82c47a2d8c79ecaaAndy Hung{
8626145643ce22d797b3b1675c82c47a2d8c79ecaaAndy Hung    return kFixPitch ? AUDIO_TIMESTRETCH_PITCH_NORMAL : pitch;
8726145643ce22d797b3b1675c82c47a2d8c79ecaaAndy Hung}
8826145643ce22d797b3b1675c82c47a2d8c79ecaaAndy Hung
898edb8dc44b8a2f81bdb5db645b6b708548771a31Andy Hung// Must match similar computation in createTrack_l in Threads.cpp.
908edb8dc44b8a2f81bdb5db645b6b708548771a31Andy Hung// TODO: Move to a common library
918edb8dc44b8a2f81bdb5db645b6b708548771a31Andy Hungstatic size_t calculateMinFrameCount(
928edb8dc44b8a2f81bdb5db645b6b708548771a31Andy Hung        uint32_t afLatencyMs, uint32_t afFrameCount, uint32_t afSampleRate,
93ea38ee7742e799b23bd8675f5801ef72f94de0f4Glenn Kasten        uint32_t sampleRate, float speed /*, uint32_t notificationsPerBufferReq*/)
948edb8dc44b8a2f81bdb5db645b6b708548771a31Andy Hung{
958edb8dc44b8a2f81bdb5db645b6b708548771a31Andy Hung    // Ensure that buffer depth covers at least audio hardware latency
968edb8dc44b8a2f81bdb5db645b6b708548771a31Andy Hung    uint32_t minBufCount = afLatencyMs / ((1000 * afFrameCount) / afSampleRate);
978edb8dc44b8a2f81bdb5db645b6b708548771a31Andy Hung    if (minBufCount < 2) {
988edb8dc44b8a2f81bdb5db645b6b708548771a31Andy Hung        minBufCount = 2;
998edb8dc44b8a2f81bdb5db645b6b708548771a31Andy Hung    }
100ea38ee7742e799b23bd8675f5801ef72f94de0f4Glenn Kasten#if 0
101ea38ee7742e799b23bd8675f5801ef72f94de0f4Glenn Kasten    // The notificationsPerBufferReq parameter is not yet used for non-fast tracks,
102ea38ee7742e799b23bd8675f5801ef72f94de0f4Glenn Kasten    // but keeping the code here to make it easier to add later.
103ea38ee7742e799b23bd8675f5801ef72f94de0f4Glenn Kasten    if (minBufCount < notificationsPerBufferReq) {
104ea38ee7742e799b23bd8675f5801ef72f94de0f4Glenn Kasten        minBufCount = notificationsPerBufferReq;
105ea38ee7742e799b23bd8675f5801ef72f94de0f4Glenn Kasten    }
106ea38ee7742e799b23bd8675f5801ef72f94de0f4Glenn Kasten#endif
1078edb8dc44b8a2f81bdb5db645b6b708548771a31Andy Hung    ALOGV("calculateMinFrameCount afLatency %u  afFrameCount %u  afSampleRate %u  "
108ea38ee7742e799b23bd8675f5801ef72f94de0f4Glenn Kasten            "sampleRate %u  speed %f  minBufCount: %u" /*"  notificationsPerBufferReq %u"*/,
109ea38ee7742e799b23bd8675f5801ef72f94de0f4Glenn Kasten            afLatencyMs, afFrameCount, afSampleRate, sampleRate, speed, minBufCount
110ea38ee7742e799b23bd8675f5801ef72f94de0f4Glenn Kasten            /*, notificationsPerBufferReq*/);
1118edb8dc44b8a2f81bdb5db645b6b708548771a31Andy Hung    return minBufCount * sourceFramesNeededWithTimestretch(
1128edb8dc44b8a2f81bdb5db645b6b708548771a31Andy Hung            sampleRate, afFrameCount, afSampleRate, speed);
1138edb8dc44b8a2f81bdb5db645b6b708548771a31Andy Hung}
1148edb8dc44b8a2f81bdb5db645b6b708548771a31Andy Hung
11533005a932c60a0780fe9b7307d5988df3d9f6c26Chia-chi Yeh// static
11633005a932c60a0780fe9b7307d5988df3d9f6c26Chia-chi Yehstatus_t AudioTrack::getMinFrameCount(
117e33054eb968cbf8ccaee1b0ff0301403902deed6Glenn Kasten        size_t* frameCount,
118fff6d715a8db0daf08a50634f242c40268de3d49Glenn Kasten        audio_stream_type_t streamType,
11933005a932c60a0780fe9b7307d5988df3d9f6c26Chia-chi Yeh        uint32_t sampleRate)
12033005a932c60a0780fe9b7307d5988df3d9f6c26Chia-chi Yeh{
121d65d73c4ae74d084751b417615a78cbe7a51372aGlenn Kasten    if (frameCount == NULL) {
122d65d73c4ae74d084751b417615a78cbe7a51372aGlenn Kasten        return BAD_VALUE;
123d65d73c4ae74d084751b417615a78cbe7a51372aGlenn Kasten    }
12404cd0186305e2b59d23c9147787046c6662029ccGlenn Kasten
1250e48d25606c82def035ad10a5b3923767a765cddAndy Hung    // FIXME handle in server, like createTrack_l(), possible missing info:
126e0fa467e1150c65a7b1b1ed904c579b40f97c9dfGlenn Kasten    //          audio_io_handle_t output
127e0fa467e1150c65a7b1b1ed904c579b40f97c9dfGlenn Kasten    //          audio_format_t format
128e0fa467e1150c65a7b1b1ed904c579b40f97c9dfGlenn Kasten    //          audio_channel_mask_t channelMask
1290e48d25606c82def035ad10a5b3923767a765cddAndy Hung    //          audio_output_flags_t flags (FAST)
1303b16c766d1ae2cfd8487e8ffb2b23936fc0a8e17Glenn Kasten    uint32_t afSampleRate;
13166a0467fdddada4caabd0f0a999fbb367fea7beeGlenn Kasten    status_t status;
13266a0467fdddada4caabd0f0a999fbb367fea7beeGlenn Kasten    status = AudioSystem::getOutputSamplingRate(&afSampleRate, streamType);
13366a0467fdddada4caabd0f0a999fbb367fea7beeGlenn Kasten    if (status != NO_ERROR) {
13470c0bfbe5ec88dcc3efa2bd8df26f36cff1cf03aGlenn Kasten        ALOGE("Unable to query output sample rate for stream type %d; status %d",
13570c0bfbe5ec88dcc3efa2bd8df26f36cff1cf03aGlenn Kasten                streamType, status);
13666a0467fdddada4caabd0f0a999fbb367fea7beeGlenn Kasten        return status;
13733005a932c60a0780fe9b7307d5988df3d9f6c26Chia-chi Yeh    }
138e33054eb968cbf8ccaee1b0ff0301403902deed6Glenn Kasten    size_t afFrameCount;
13966a0467fdddada4caabd0f0a999fbb367fea7beeGlenn Kasten    status = AudioSystem::getOutputFrameCount(&afFrameCount, streamType);
14066a0467fdddada4caabd0f0a999fbb367fea7beeGlenn Kasten    if (status != NO_ERROR) {
14170c0bfbe5ec88dcc3efa2bd8df26f36cff1cf03aGlenn Kasten        ALOGE("Unable to query output frame count for stream type %d; status %d",
14270c0bfbe5ec88dcc3efa2bd8df26f36cff1cf03aGlenn Kasten                streamType, status);
14366a0467fdddada4caabd0f0a999fbb367fea7beeGlenn Kasten        return status;
14433005a932c60a0780fe9b7307d5988df3d9f6c26Chia-chi Yeh    }
14533005a932c60a0780fe9b7307d5988df3d9f6c26Chia-chi Yeh    uint32_t afLatency;
14666a0467fdddada4caabd0f0a999fbb367fea7beeGlenn Kasten    status = AudioSystem::getOutputLatency(&afLatency, streamType);
14766a0467fdddada4caabd0f0a999fbb367fea7beeGlenn Kasten    if (status != NO_ERROR) {
14870c0bfbe5ec88dcc3efa2bd8df26f36cff1cf03aGlenn Kasten        ALOGE("Unable to query output latency for stream type %d; status %d",
14970c0bfbe5ec88dcc3efa2bd8df26f36cff1cf03aGlenn Kasten                streamType, status);
15066a0467fdddada4caabd0f0a999fbb367fea7beeGlenn Kasten        return status;
15133005a932c60a0780fe9b7307d5988df3d9f6c26Chia-chi Yeh    }
15233005a932c60a0780fe9b7307d5988df3d9f6c26Chia-chi Yeh
1538edb8dc44b8a2f81bdb5db645b6b708548771a31Andy Hung    // When called from createTrack, speed is 1.0f (normal speed).
1548edb8dc44b8a2f81bdb5db645b6b708548771a31Andy Hung    // This is rechecked again on setting playback rate (TODO: on setting sample rate, too).
155ea38ee7742e799b23bd8675f5801ef72f94de0f4Glenn Kasten    *frameCount = calculateMinFrameCount(afLatency, afFrameCount, afSampleRate, sampleRate, 1.0f
156ea38ee7742e799b23bd8675f5801ef72f94de0f4Glenn Kasten            /*, 0 notificationsPerBufferReq*/);
15733005a932c60a0780fe9b7307d5988df3d9f6c26Chia-chi Yeh
1580e48d25606c82def035ad10a5b3923767a765cddAndy Hung    // The formula above should always produce a non-zero value under normal circumstances:
1590e48d25606c82def035ad10a5b3923767a765cddAndy Hung    // AudioTrack.SAMPLE_RATE_HZ_MIN <= sampleRate <= AudioTrack.SAMPLE_RATE_HZ_MAX.
1600e48d25606c82def035ad10a5b3923767a765cddAndy Hung    // Return error in the unlikely event that it does not, as that's part of the API contract.
16166a0467fdddada4caabd0f0a999fbb367fea7beeGlenn Kasten    if (*frameCount == 0) {
1620e48d25606c82def035ad10a5b3923767a765cddAndy Hung        ALOGE("AudioTrack::getMinFrameCount failed for streamType %d, sampleRate %u",
16366a0467fdddada4caabd0f0a999fbb367fea7beeGlenn Kasten                streamType, sampleRate);
16466a0467fdddada4caabd0f0a999fbb367fea7beeGlenn Kasten        return BAD_VALUE;
16566a0467fdddada4caabd0f0a999fbb367fea7beeGlenn Kasten    }
1668edb8dc44b8a2f81bdb5db645b6b708548771a31Andy Hung    ALOGV("getMinFrameCount=%zu: afFrameCount=%zu, afSampleRate=%u, afLatency=%u",
1678edb8dc44b8a2f81bdb5db645b6b708548771a31Andy Hung            *frameCount, afFrameCount, afSampleRate, afLatency);
16833005a932c60a0780fe9b7307d5988df3d9f6c26Chia-chi Yeh    return NO_ERROR;
16933005a932c60a0780fe9b7307d5988df3d9f6c26Chia-chi Yeh}
17089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
17189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project// ---------------------------------------------------------------------------
17289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
17389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source ProjectAudioTrack::AudioTrack()
174879135196fd1c97deefc538c888037c56c2879a7Glenn Kasten    : mStatus(NO_INIT),
1759b3359feabbf138bb965da5173434da78bfe0929Haynes Mathew George      mState(STATE_STOPPED),
1764ff14bae91075eb274eb1c2975982358946e7e63John Grossman      mPreviousPriority(ANDROID_PRIORITY_NORMAL),
1777064fd2dcdfeafea53cd5a992bb78c413542f29fHaynes Mathew George      mPreviousSchedulingGroup(SP_DEFAULT),
178aa9811945f575614b3482d09e4d969792701cebbPaul McLean      mPausedPosition(0),
179aa9811945f575614b3482d09e4d969792701cebbPaul McLean      mSelectedDeviceId(AUDIO_PORT_HANDLE_NONE)
18089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
181faabb51ceef13bf1e3f692219ac410c1cd75d0deJean-Michel Trivi    mAttributes.content_type = AUDIO_CONTENT_TYPE_UNKNOWN;
182faabb51ceef13bf1e3f692219ac410c1cd75d0deJean-Michel Trivi    mAttributes.usage = AUDIO_USAGE_UNKNOWN;
183faabb51ceef13bf1e3f692219ac410c1cd75d0deJean-Michel Trivi    mAttributes.flags = 0x0;
184faabb51ceef13bf1e3f692219ac410c1cd75d0deJean-Michel Trivi    strcpy(mAttributes.tags, "");
18589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
18689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
18789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source ProjectAudioTrack::AudioTrack(
188fff6d715a8db0daf08a50634f242c40268de3d49Glenn Kasten        audio_stream_type_t streamType,
18989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        uint32_t sampleRate,
190e1c3962e268ffc12bfd1bd9ea84da1f135f36960Glenn Kasten        audio_format_t format,
19128b76b334f92a15a2be3cc9e2f7d229a3275d1acGlenn Kasten        audio_channel_mask_t channelMask,
192bce50bfc3846ab008bafa75c5d3f29fd7b5395f7Glenn Kasten        size_t frameCount,
1930ca3cf94c0dfc173ad7886ae162c4b67067539f6Eric Laurent        audio_output_flags_t flags,
19489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        callback_t cbf,
19589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        void* user,
196ea38ee7742e799b23bd8675f5801ef72f94de0f4Glenn Kasten        int32_t notificationFrames,
197d848eb48c121c119e8ba7583efc75415fe102570Glenn Kasten        audio_session_t sessionId,
198ad3af3305f024bcbbd55c894a4995e449498e1baRichard Fitzgerald        transfer_type transferType,
199462fd2fa9eef642b0574aa7409de0bde3fec8d43Marco Nelissen        const audio_offload_info_t *offloadInfo,
200d457c970c8d08519cd77280a90b61ae1e342cfe3Marco Nelissen        int uid,
201d9d7fa0873796ac661c44a7fcd6ad5ff697ff01fJean-Michel Trivi        pid_t pid,
202faeb0f291330134dc4468359a36e099aae508449Ronghua Wu        const audio_attributes_t* pAttributes,
203ff874dc957f9ea70d87f4d627bf903e1fc86d58bAndy Hung        bool doNotReconnect,
204ff874dc957f9ea70d87f4d627bf903e1fc86d58bAndy Hung        float maxRequiredSpeed)
205879135196fd1c97deefc538c888037c56c2879a7Glenn Kasten    : mStatus(NO_INIT),
2069b3359feabbf138bb965da5173434da78bfe0929Haynes Mathew George      mState(STATE_STOPPED),
2074ff14bae91075eb274eb1c2975982358946e7e63John Grossman      mPreviousPriority(ANDROID_PRIORITY_NORMAL),
2087064fd2dcdfeafea53cd5a992bb78c413542f29fHaynes Mathew George      mPreviousSchedulingGroup(SP_DEFAULT),
209aa9811945f575614b3482d09e4d969792701cebbPaul McLean      mPausedPosition(0),
210aa9811945f575614b3482d09e4d969792701cebbPaul McLean      mSelectedDeviceId(AUDIO_PORT_HANDLE_NONE)
21189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
2120d255b2d9061ba31f13ada3fc0f7e51916407176Jean-Michel Trivi    mStatus = set(streamType, sampleRate, format, channelMask,
213a514bdb58b5de4986679f72b7204b4764f7a2778Eric Laurent            frameCount, flags, cbf, user, notificationFrames,
214462fd2fa9eef642b0574aa7409de0bde3fec8d43Marco Nelissen            0 /*sharedBuffer*/, false /*threadCanCallJava*/, sessionId, transferType,
215ff874dc957f9ea70d87f4d627bf903e1fc86d58bAndy Hung            offloadInfo, uid, pid, pAttributes, doNotReconnect, maxRequiredSpeed);
21689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
21789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
218c813985abd8ba61e999b3505f6a332574f87a1beAndreas HuberAudioTrack::AudioTrack(
219fff6d715a8db0daf08a50634f242c40268de3d49Glenn Kasten        audio_stream_type_t streamType,
22089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        uint32_t sampleRate,
221e1c3962e268ffc12bfd1bd9ea84da1f135f36960Glenn Kasten        audio_format_t format,
22228b76b334f92a15a2be3cc9e2f7d229a3275d1acGlenn Kasten        audio_channel_mask_t channelMask,
22389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        const sp<IMemory>& sharedBuffer,
2240ca3cf94c0dfc173ad7886ae162c4b67067539f6Eric Laurent        audio_output_flags_t flags,
22589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        callback_t cbf,
22689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        void* user,
227ea38ee7742e799b23bd8675f5801ef72f94de0f4Glenn Kasten        int32_t notificationFrames,
228d848eb48c121c119e8ba7583efc75415fe102570Glenn Kasten        audio_session_t sessionId,
229ad3af3305f024bcbbd55c894a4995e449498e1baRichard Fitzgerald        transfer_type transferType,
230462fd2fa9eef642b0574aa7409de0bde3fec8d43Marco Nelissen        const audio_offload_info_t *offloadInfo,
231d457c970c8d08519cd77280a90b61ae1e342cfe3Marco Nelissen        int uid,
232d9d7fa0873796ac661c44a7fcd6ad5ff697ff01fJean-Michel Trivi        pid_t pid,
233faeb0f291330134dc4468359a36e099aae508449Ronghua Wu        const audio_attributes_t* pAttributes,
234ff874dc957f9ea70d87f4d627bf903e1fc86d58bAndy Hung        bool doNotReconnect,
235ff874dc957f9ea70d87f4d627bf903e1fc86d58bAndy Hung        float maxRequiredSpeed)
236879135196fd1c97deefc538c888037c56c2879a7Glenn Kasten    : mStatus(NO_INIT),
2379b3359feabbf138bb965da5173434da78bfe0929Haynes Mathew George      mState(STATE_STOPPED),
2384ff14bae91075eb274eb1c2975982358946e7e63John Grossman      mPreviousPriority(ANDROID_PRIORITY_NORMAL),
2397064fd2dcdfeafea53cd5a992bb78c413542f29fHaynes Mathew George      mPreviousSchedulingGroup(SP_DEFAULT),
240aa9811945f575614b3482d09e4d969792701cebbPaul McLean      mPausedPosition(0),
241aa9811945f575614b3482d09e4d969792701cebbPaul McLean      mSelectedDeviceId(AUDIO_PORT_HANDLE_NONE)
24289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
2430d255b2d9061ba31f13ada3fc0f7e51916407176Jean-Michel Trivi    mStatus = set(streamType, sampleRate, format, channelMask,
24417a736c3e1d062d7fc916329eb32aef8935614afGlenn Kasten            0 /*frameCount*/, flags, cbf, user, notificationFrames,
245d457c970c8d08519cd77280a90b61ae1e342cfe3Marco Nelissen            sharedBuffer, false /*threadCanCallJava*/, sessionId, transferType, offloadInfo,
246ff874dc957f9ea70d87f4d627bf903e1fc86d58bAndy Hung            uid, pid, pAttributes, doNotReconnect, maxRequiredSpeed);
24789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
24889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
24989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source ProjectAudioTrack::~AudioTrack()
25089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
25189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    if (mStatus == NO_ERROR) {
25289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        // Make sure that callback function exits in the case where
25389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        // it is looping on buffer full condition in obtainBuffer().
25489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        // Otherwise the callback thread will never exit.
25589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        stop();
25689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        if (mAudioTrackThread != 0) {
257b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald            mProxy->interrupt();
2583acbd053c842e76e1a40fc8a0bf62de87eebf00fGlenn Kasten            mAudioTrackThread->requestExit();   // see comment in AudioTrack.h
25989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project            mAudioTrackThread->requestExitAndWait();
26089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project            mAudioTrackThread.clear();
26189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        }
262296fb13dd9b5e90d6a05cce897c3b1e7914a478aEric Laurent        // No lock here: worst case we remove a NULL callback which will be a nop
263296fb13dd9b5e90d6a05cce897c3b1e7914a478aEric Laurent        if (mDeviceCallback != 0 && mOutput != AUDIO_IO_HANDLE_NONE) {
264296fb13dd9b5e90d6a05cce897c3b1e7914a478aEric Laurent            AudioSystem::removeAudioDeviceCallback(mDeviceCallback, mOutput);
265296fb13dd9b5e90d6a05cce897c3b1e7914a478aEric Laurent        }
266f888020c6e2735624f2b2a30e72aca24e17b8b4dMarco Nelissen        IInterface::asBinder(mAudioTrack)->unlinkToDeath(mDeathNotifier, this);
26753cec22821072719ee02c856e9ac2dda2496c570Glenn Kasten        mAudioTrack.clear();
2683bcffa136909c1fb6e88ee4efd12ccac18360a85Eric Laurent        mCblkMemory.clear();
2693bcffa136909c1fb6e88ee4efd12ccac18360a85Eric Laurent        mSharedBuffer.clear();
27089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        IPCThreadState::self()->flushCommands();
2714c36d6f48f4eecacc148317f775f65961a4f03d2Glenn Kasten        ALOGV("~AudioTrack, releasing session id %d from %d on behalf of %d",
2724c36d6f48f4eecacc148317f775f65961a4f03d2Glenn Kasten                mSessionId, IPCThreadState::self()->getCallingPid(), mClientPid);
273d457c970c8d08519cd77280a90b61ae1e342cfe3Marco Nelissen        AudioSystem::releaseAudioSessionId(mSessionId, mClientPid);
27489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
27589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
27689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
27789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectstatus_t AudioTrack::set(
278fff6d715a8db0daf08a50634f242c40268de3d49Glenn Kasten        audio_stream_type_t streamType,
27989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        uint32_t sampleRate,
280e1c3962e268ffc12bfd1bd9ea84da1f135f36960Glenn Kasten        audio_format_t format,
28128b76b334f92a15a2be3cc9e2f7d229a3275d1acGlenn Kasten        audio_channel_mask_t channelMask,
282bce50bfc3846ab008bafa75c5d3f29fd7b5395f7Glenn Kasten        size_t frameCount,
2830ca3cf94c0dfc173ad7886ae162c4b67067539f6Eric Laurent        audio_output_flags_t flags,
28489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        callback_t cbf,
28589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        void* user,
286ea38ee7742e799b23bd8675f5801ef72f94de0f4Glenn Kasten        int32_t notificationFrames,
28789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        const sp<IMemory>& sharedBuffer,
288be916aa1267e2e6b1c148f51d11bcbbc79cb864cEric Laurent        bool threadCanCallJava,
289d848eb48c121c119e8ba7583efc75415fe102570Glenn Kasten        audio_session_t sessionId,
290ad3af3305f024bcbbd55c894a4995e449498e1baRichard Fitzgerald        transfer_type transferType,
291462fd2fa9eef642b0574aa7409de0bde3fec8d43Marco Nelissen        const audio_offload_info_t *offloadInfo,
292d457c970c8d08519cd77280a90b61ae1e342cfe3Marco Nelissen        int uid,
293faabb51ceef13bf1e3f692219ac410c1cd75d0deJean-Michel Trivi        pid_t pid,
294faeb0f291330134dc4468359a36e099aae508449Ronghua Wu        const audio_attributes_t* pAttributes,
295ff874dc957f9ea70d87f4d627bf903e1fc86d58bAndy Hung        bool doNotReconnect,
296ff874dc957f9ea70d87f4d627bf903e1fc86d58bAndy Hung        float maxRequiredSpeed)
29789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
298bce50bfc3846ab008bafa75c5d3f29fd7b5395f7Glenn Kasten    ALOGV("set(): streamType %d, sampleRate %u, format %#x, channelMask %#x, frameCount %zu, "
299ea38ee7742e799b23bd8675f5801ef72f94de0f4Glenn Kasten          "flags #%x, notificationFrames %d, sessionId %d, transferType %d, uid %d, pid %d",
300bce50bfc3846ab008bafa75c5d3f29fd7b5395f7Glenn Kasten          streamType, sampleRate, format, channelMask, frameCount, flags, notificationFrames,
3014c36d6f48f4eecacc148317f775f65961a4f03d2Glenn Kasten          sessionId, transferType, uid, pid);
30286f04663032ddaa25110149d709bbf896ad83b02Glenn Kasten
30333ff89ba94a527e4293ee5349da01483252d5c83Phil Burk    mThreadCanCallJava = threadCanCallJava;
30433ff89ba94a527e4293ee5349da01483252d5c83Phil Burk
3059f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    switch (transferType) {
3069f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    case TRANSFER_DEFAULT:
3079f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        if (sharedBuffer != 0) {
3089f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            transferType = TRANSFER_SHARED;
3099f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        } else if (cbf == NULL || threadCanCallJava) {
3109f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            transferType = TRANSFER_SYNC;
3119f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        } else {
3129f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            transferType = TRANSFER_CALLBACK;
3139f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        }
3149f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        break;
3159f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    case TRANSFER_CALLBACK:
3169f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        if (cbf == NULL || sharedBuffer != 0) {
3179f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            ALOGE("Transfer type TRANSFER_CALLBACK but cbf == NULL || sharedBuffer != 0");
3189f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            return BAD_VALUE;
3199f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        }
3209f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        break;
3219f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    case TRANSFER_OBTAIN:
3229f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    case TRANSFER_SYNC:
3239f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        if (sharedBuffer != 0) {
3249f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            ALOGE("Transfer type TRANSFER_OBTAIN but sharedBuffer != 0");
3259f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            return BAD_VALUE;
3269f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        }
3279f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        break;
3289f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    case TRANSFER_SHARED:
3299f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        if (sharedBuffer == 0) {
3309f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            ALOGE("Transfer type TRANSFER_SHARED but sharedBuffer == 0");
3319f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            return BAD_VALUE;
3329f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        }
3339f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        break;
3349f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    default:
3359f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        ALOGE("Invalid transfer type %d", transferType);
3369f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        return BAD_VALUE;
3379f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
338dd5f4c8c4059f890e81b28b026a688febb4e1dd9Glenn Kasten    mSharedBuffer = sharedBuffer;
3399f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    mTransfer = transferType;
340faeb0f291330134dc4468359a36e099aae508449Ronghua Wu    mDoNotReconnect = doNotReconnect;
3419f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
34297c9f4fd7bc31e2968d816402659ba1c64f10b42Eric Laurent    ALOGV_IF(sharedBuffer != 0, "sharedBuffer: %p, size: %zu", sharedBuffer->pointer(),
34385ab62c4b433df3f1a9826bed1c9bec07a86c750Glenn Kasten            sharedBuffer->size());
34489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
34534fb29696b0f3abf61b10f8d053b1f33d501de0aMark Salyzyn    ALOGV("set() streamType %d frameCount %zu flags %04x", streamType, frameCount, flags);
3461a9ed11a472493cac7f6dfcbfac2064526a493edEric Laurent
34753cec22821072719ee02c856e9ac2dda2496c570Glenn Kasten    // invariant that mAudioTrack != 0 is true only after set() returns successfully
3481dd70b9f04961a06fcb73a97fca10a53b3245d3cEric Laurent    if (mAudioTrack != 0) {
34929357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("Track already in use");
35089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        return INVALID_OPERATION;
35189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
35289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
35389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    // handle default values first.
354e83b55dc29ca16092ba02f36f55fa6e0e37fd78cEric Laurent    if (streamType == AUDIO_STREAM_DEFAULT) {
355fce7a473248381cc83a01855f92581077d3c9ee2Dima Zavin        streamType = AUDIO_STREAM_MUSIC;
35689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
357faabb51ceef13bf1e3f692219ac410c1cd75d0deJean-Michel Trivi    if (pAttributes == NULL) {
358223fd5c9738e9665e495904d37d4632414b68c1eEric Laurent        if (uint32_t(streamType) >= AUDIO_STREAM_PUBLIC_CNT) {
359faabb51ceef13bf1e3f692219ac410c1cd75d0deJean-Michel Trivi            ALOGE("Invalid stream type %d", streamType);
360faabb51ceef13bf1e3f692219ac410c1cd75d0deJean-Michel Trivi            return BAD_VALUE;
361faabb51ceef13bf1e3f692219ac410c1cd75d0deJean-Michel Trivi        }
362faabb51ceef13bf1e3f692219ac410c1cd75d0deJean-Michel Trivi        mStreamType = streamType;
363e83b55dc29ca16092ba02f36f55fa6e0e37fd78cEric Laurent
364faabb51ceef13bf1e3f692219ac410c1cd75d0deJean-Michel Trivi    } else {
365faabb51ceef13bf1e3f692219ac410c1cd75d0deJean-Michel Trivi        // stream type shouldn't be looked at, this track has audio attributes
366faabb51ceef13bf1e3f692219ac410c1cd75d0deJean-Michel Trivi        memcpy(&mAttributes, pAttributes, sizeof(audio_attributes_t));
367faabb51ceef13bf1e3f692219ac410c1cd75d0deJean-Michel Trivi        ALOGV("Building AudioTrack with attributes: usage=%d content=%d flags=0x%x tags=[%s]",
368faabb51ceef13bf1e3f692219ac410c1cd75d0deJean-Michel Trivi                mAttributes.usage, mAttributes.content_type, mAttributes.flags, mAttributes.tags);
369e83b55dc29ca16092ba02f36f55fa6e0e37fd78cEric Laurent        mStreamType = AUDIO_STREAM_DEFAULT;
370c6bd5db9d9cf4bba1649b5b7ddea2d23f5de23a9Eric Laurent        if ((mAttributes.flags & AUDIO_FLAG_HW_AV_SYNC) != 0) {
371c6bd5db9d9cf4bba1649b5b7ddea2d23f5de23a9Eric Laurent            flags = (audio_output_flags_t)(flags | AUDIO_OUTPUT_FLAG_HW_AV_SYNC);
372c6bd5db9d9cf4bba1649b5b7ddea2d23f5de23a9Eric Laurent        }
37333ff89ba94a527e4293ee5349da01483252d5c83Phil Burk        if ((mAttributes.flags & AUDIO_FLAG_LOW_LATENCY) != 0) {
37433ff89ba94a527e4293ee5349da01483252d5c83Phil Burk            flags = (audio_output_flags_t) (flags | AUDIO_OUTPUT_FLAG_FAST);
37533ff89ba94a527e4293ee5349da01483252d5c83Phil Burk        }
376dd5f4c8c4059f890e81b28b026a688febb4e1dd9Glenn Kasten    }
377ea7939a079b3600cab955760839b021326f8cfc3Glenn Kasten
37889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    // these below should probably come from the audioFlinger too...
379e1c3962e268ffc12bfd1bd9ea84da1f135f36960Glenn Kasten    if (format == AUDIO_FORMAT_DEFAULT) {
380fce7a473248381cc83a01855f92581077d3c9ee2Dima Zavin        format = AUDIO_FORMAT_PCM_16_BIT;
381fdb3c07db5d44535eb8c3ec46dc78ad8446c01ebPhil Burk    } else if (format == AUDIO_FORMAT_IEC61937) { // HDMI pass-through?
382fdb3c07db5d44535eb8c3ec46dc78ad8446c01ebPhil Burk        mAttributes.flags |= AUDIO_OUTPUT_FLAG_IEC958_NONAUDIO;
38389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
38489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
38589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    // validate parameters
386fce7a473248381cc83a01855f92581077d3c9ee2Dima Zavin    if (!audio_is_valid_format(format)) {
387cac3daa6332bf6d1f7d26adc4a9915f3d7992dd9Glenn Kasten        ALOGE("Invalid format %#x", format);
38889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        return BAD_VALUE;
38989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
390dd5f4c8c4059f890e81b28b026a688febb4e1dd9Glenn Kasten    mFormat = format;
391c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent
3928ba90326d683b035d99e24db669093e4602a7149Glenn Kasten    if (!audio_is_output_channel(channelMask)) {
3938ba90326d683b035d99e24db669093e4602a7149Glenn Kasten        ALOGE("Invalid channel mask %#x", channelMask);
3948ba90326d683b035d99e24db669093e4602a7149Glenn Kasten        return BAD_VALUE;
3958ba90326d683b035d99e24db669093e4602a7149Glenn Kasten    }
396e3247bf8dd4f8fa8dfa3a108260241ae4a967569Glenn Kasten    mChannelMask = channelMask;
397e541269be94f3a1072932d51537905b120ef4733Andy Hung    uint32_t channelCount = audio_channel_count_from_out_mask(channelMask);
398e3247bf8dd4f8fa8dfa3a108260241ae4a967569Glenn Kasten    mChannelCount = channelCount;
3998ba90326d683b035d99e24db669093e4602a7149Glenn Kasten
400c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent    // force direct flag if format is not linear PCM
401b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald    // or offload was requested
402b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald    if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
403b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald            || !audio_is_linear_pcm(format)) {
404b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald        ALOGV( (flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
405b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald                    ? "Offload request, forcing to Direct Output"
406b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald                    : "Not linear PCM, forcing to Direct Output");
4070ca3cf94c0dfc173ad7886ae162c4b67067539f6Eric Laurent        flags = (audio_output_flags_t)
4083acbd053c842e76e1a40fc8a0bf62de87eebf00fGlenn Kasten                // FIXME why can't we allow direct AND fast?
4090ca3cf94c0dfc173ad7886ae162c4b67067539f6Eric Laurent                ((flags | AUDIO_OUTPUT_FLAG_DIRECT) & ~AUDIO_OUTPUT_FLAG_FAST);
410c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent    }
411c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent
412d1f69b0b17acbd96987ecb2f3378abd394d05903Eric Laurent    // force direct flag if HW A/V sync requested
413d1f69b0b17acbd96987ecb2f3378abd394d05903Eric Laurent    if ((flags & AUDIO_OUTPUT_FLAG_HW_AV_SYNC) != 0) {
414d1f69b0b17acbd96987ecb2f3378abd394d05903Eric Laurent        flags = (audio_output_flags_t)(flags | AUDIO_OUTPUT_FLAG_DIRECT);
415d1f69b0b17acbd96987ecb2f3378abd394d05903Eric Laurent    }
416d1f69b0b17acbd96987ecb2f3378abd394d05903Eric Laurent
417b773038277ba328696832b690b91ce6e95bd1a6cGlenn Kasten    if (flags & AUDIO_OUTPUT_FLAG_DIRECT) {
418fdb3c07db5d44535eb8c3ec46dc78ad8446c01ebPhil Burk        if (audio_has_proportional_frames(format)) {
419b773038277ba328696832b690b91ce6e95bd1a6cGlenn Kasten            mFrameSize = channelCount * audio_bytes_per_sample(format);
420b773038277ba328696832b690b91ce6e95bd1a6cGlenn Kasten        } else {
421b773038277ba328696832b690b91ce6e95bd1a6cGlenn Kasten            mFrameSize = sizeof(uint8_t);
422b773038277ba328696832b690b91ce6e95bd1a6cGlenn Kasten        }
423e3aa659e9cee7df5c12a80d285cc29ab3b2cbb39Glenn Kasten    } else {
424fdb3c07db5d44535eb8c3ec46dc78ad8446c01ebPhil Burk        ALOG_ASSERT(audio_has_proportional_frames(format));
425b773038277ba328696832b690b91ce6e95bd1a6cGlenn Kasten        mFrameSize = channelCount * audio_bytes_per_sample(format);
426b773038277ba328696832b690b91ce6e95bd1a6cGlenn Kasten        // createTrack will return an error if PCM format is not supported by server,
427b773038277ba328696832b690b91ce6e95bd1a6cGlenn Kasten        // so no need to check for specific PCM formats here
428e3aa659e9cee7df5c12a80d285cc29ab3b2cbb39Glenn Kasten    }
429e3aa659e9cee7df5c12a80d285cc29ab3b2cbb39Glenn Kasten
4300d6db582f2ccc9f8943c5f3965e2994b7d137158Eric Laurent    // sampling rate must be specified for direct outputs
4310d6db582f2ccc9f8943c5f3965e2994b7d137158Eric Laurent    if (sampleRate == 0 && (flags & AUDIO_OUTPUT_FLAG_DIRECT) != 0) {
4320d6db582f2ccc9f8943c5f3965e2994b7d137158Eric Laurent        return BAD_VALUE;
4330d6db582f2ccc9f8943c5f3965e2994b7d137158Eric Laurent    }
4340d6db582f2ccc9f8943c5f3965e2994b7d137158Eric Laurent    mSampleRate = sampleRate;
4353a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    mOriginalSampleRate = sampleRate;
4365a8a95de6dad1a3bcf3da5a37b35766e89086e13Ricardo Garcia    mPlaybackRate = AUDIO_PLAYBACK_RATE_DEFAULT;
437ff874dc957f9ea70d87f4d627bf903e1fc86d58bAndy Hung    // 1.0 <= mMaxRequiredSpeed <= AUDIO_TIMESTRETCH_SPEED_MAX
438ff874dc957f9ea70d87f4d627bf903e1fc86d58bAndy Hung    mMaxRequiredSpeed = min(max(maxRequiredSpeed, 1.0f), AUDIO_TIMESTRETCH_SPEED_MAX);
4390d6db582f2ccc9f8943c5f3965e2994b7d137158Eric Laurent
440b5ccb2d99b2af400c70777a6452f090ac14f5a96Glenn Kasten    // Make copy of input parameter offloadInfo so that in the future:
441b5ccb2d99b2af400c70777a6452f090ac14f5a96Glenn Kasten    //  (a) createTrack_l doesn't need it as an input parameter
442b5ccb2d99b2af400c70777a6452f090ac14f5a96Glenn Kasten    //  (b) we can support re-creation of offloaded tracks
443b5ccb2d99b2af400c70777a6452f090ac14f5a96Glenn Kasten    if (offloadInfo != NULL) {
444b5ccb2d99b2af400c70777a6452f090ac14f5a96Glenn Kasten        mOffloadInfoCopy = *offloadInfo;
445b5ccb2d99b2af400c70777a6452f090ac14f5a96Glenn Kasten        mOffloadInfo = &mOffloadInfoCopy;
446b5ccb2d99b2af400c70777a6452f090ac14f5a96Glenn Kasten    } else {
447b5ccb2d99b2af400c70777a6452f090ac14f5a96Glenn Kasten        mOffloadInfo = NULL;
448b5ccb2d99b2af400c70777a6452f090ac14f5a96Glenn Kasten    }
449b5ccb2d99b2af400c70777a6452f090ac14f5a96Glenn Kasten
45066e4635cb09fadcaccf912f37c387396c428378aGlenn Kasten    mVolume[AUDIO_INTERLEAVE_LEFT] = 1.0f;
45166e4635cb09fadcaccf912f37c387396c428378aGlenn Kasten    mVolume[AUDIO_INTERLEAVE_RIGHT] = 1.0f;
45205632a5fa4b88ca474294887fc92a9fcdf0e2352Glenn Kasten    mSendLevel = 0.0f;
453396fabdb6efcdac5aea3d9f559d1beedf6a4cedcGlenn Kasten    // mFrameCount is initialized in createTrack_l
454b603744e96b07b1d5bf745bde593fb2c025cefcfGlenn Kasten    mReqFrameCount = frameCount;
455ea38ee7742e799b23bd8675f5801ef72f94de0f4Glenn Kasten    if (notificationFrames >= 0) {
456ea38ee7742e799b23bd8675f5801ef72f94de0f4Glenn Kasten        mNotificationFramesReq = notificationFrames;
457ea38ee7742e799b23bd8675f5801ef72f94de0f4Glenn Kasten        mNotificationsPerBufferReq = 0;
458ea38ee7742e799b23bd8675f5801ef72f94de0f4Glenn Kasten    } else {
459ea38ee7742e799b23bd8675f5801ef72f94de0f4Glenn Kasten        if (!(flags & AUDIO_OUTPUT_FLAG_FAST)) {
460ea38ee7742e799b23bd8675f5801ef72f94de0f4Glenn Kasten            ALOGE("notificationFrames=%d not permitted for non-fast track",
461ea38ee7742e799b23bd8675f5801ef72f94de0f4Glenn Kasten                    notificationFrames);
462ea38ee7742e799b23bd8675f5801ef72f94de0f4Glenn Kasten            return BAD_VALUE;
463ea38ee7742e799b23bd8675f5801ef72f94de0f4Glenn Kasten        }
464ea38ee7742e799b23bd8675f5801ef72f94de0f4Glenn Kasten        if (frameCount > 0) {
465ea38ee7742e799b23bd8675f5801ef72f94de0f4Glenn Kasten            ALOGE("notificationFrames=%d not permitted with non-zero frameCount=%zu",
466ea38ee7742e799b23bd8675f5801ef72f94de0f4Glenn Kasten                    notificationFrames, frameCount);
467ea38ee7742e799b23bd8675f5801ef72f94de0f4Glenn Kasten            return BAD_VALUE;
468ea38ee7742e799b23bd8675f5801ef72f94de0f4Glenn Kasten        }
469ea38ee7742e799b23bd8675f5801ef72f94de0f4Glenn Kasten        mNotificationFramesReq = 0;
470ea38ee7742e799b23bd8675f5801ef72f94de0f4Glenn Kasten        const uint32_t minNotificationsPerBuffer = 1;
471ea38ee7742e799b23bd8675f5801ef72f94de0f4Glenn Kasten        const uint32_t maxNotificationsPerBuffer = 8;
472ea38ee7742e799b23bd8675f5801ef72f94de0f4Glenn Kasten        mNotificationsPerBufferReq = min(maxNotificationsPerBuffer,
473ea38ee7742e799b23bd8675f5801ef72f94de0f4Glenn Kasten                max((uint32_t) -notificationFrames, minNotificationsPerBuffer));
474ea38ee7742e799b23bd8675f5801ef72f94de0f4Glenn Kasten        ALOGW_IF(mNotificationsPerBufferReq != (uint32_t) -notificationFrames,
475ea38ee7742e799b23bd8675f5801ef72f94de0f4Glenn Kasten                "notificationFrames=%d clamped to the range -%u to -%u",
476ea38ee7742e799b23bd8675f5801ef72f94de0f4Glenn Kasten                notificationFrames, minNotificationsPerBuffer, maxNotificationsPerBuffer);
477ea38ee7742e799b23bd8675f5801ef72f94de0f4Glenn Kasten    }
4789f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    mNotificationFramesAct = 0;
479caf7f48a0ef558689d39aafd187c1571ff4128b4Eric Laurent    if (sessionId == AUDIO_SESSION_ALLOCATE) {
480d848eb48c121c119e8ba7583efc75415fe102570Glenn Kasten        mSessionId = (audio_session_t) AudioSystem::newAudioUniqueId(AUDIO_UNIQUE_ID_USE_SESSION);
481caf7f48a0ef558689d39aafd187c1571ff4128b4Eric Laurent    } else {
482caf7f48a0ef558689d39aafd187c1571ff4128b4Eric Laurent        mSessionId = sessionId;
483caf7f48a0ef558689d39aafd187c1571ff4128b4Eric Laurent    }
484d457c970c8d08519cd77280a90b61ae1e342cfe3Marco Nelissen    int callingpid = IPCThreadState::self()->getCallingPid();
485d457c970c8d08519cd77280a90b61ae1e342cfe3Marco Nelissen    int mypid = getpid();
486d457c970c8d08519cd77280a90b61ae1e342cfe3Marco Nelissen    if (uid == -1 || (callingpid != mypid)) {
487462fd2fa9eef642b0574aa7409de0bde3fec8d43Marco Nelissen        mClientUid = IPCThreadState::self()->getCallingUid();
488462fd2fa9eef642b0574aa7409de0bde3fec8d43Marco Nelissen    } else {
489462fd2fa9eef642b0574aa7409de0bde3fec8d43Marco Nelissen        mClientUid = uid;
490462fd2fa9eef642b0574aa7409de0bde3fec8d43Marco Nelissen    }
491d457c970c8d08519cd77280a90b61ae1e342cfe3Marco Nelissen    if (pid == -1 || (callingpid != mypid)) {
492d457c970c8d08519cd77280a90b61ae1e342cfe3Marco Nelissen        mClientPid = callingpid;
493d457c970c8d08519cd77280a90b61ae1e342cfe3Marco Nelissen    } else {
494d457c970c8d08519cd77280a90b61ae1e342cfe3Marco Nelissen        mClientPid = pid;
495d457c970c8d08519cd77280a90b61ae1e342cfe3Marco Nelissen    }
4962beeb50b1bba9e92f6cacfeca37fe9fa9d36ead1Eric Laurent    mAuxEffectId = 0;
497ae34ed2bcc9fa49a22fe7497327adb689ef27e8dHaynes Mathew George    mOrigFlags = mFlags = flags;
4984a4a0959bca78e03e3c3f486ba17829c28314d8cGlenn Kasten    mCbf = cbf;
499be916aa1267e2e6b1c148f51d11bcbbc79cb864cEric Laurent
500a997e7a7c5aa2fc7e95316218316f8b7b98786baGlenn Kasten    if (cbf != NULL) {
501896adcd3ae6a1c7010e526327eff54e16179987bEric Laurent        mAudioTrackThread = new AudioTrackThread(*this, threadCanCallJava);
502a997e7a7c5aa2fc7e95316218316f8b7b98786baGlenn Kasten        mAudioTrackThread->run("AudioTrack", ANDROID_PRIORITY_AUDIO, 0 /*stack*/);
503bfd318402924414fbde4d31c9d23cc423f10b630Glenn Kasten        // thread begins in paused state, and will not reference us until start()
504a997e7a7c5aa2fc7e95316218316f8b7b98786baGlenn Kasten    }
505a997e7a7c5aa2fc7e95316218316f8b7b98786baGlenn Kasten
50634f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent    // create the IAudioTrack
5070d6db582f2ccc9f8943c5f3965e2994b7d137158Eric Laurent    status_t status = createTrack_l();
508a997e7a7c5aa2fc7e95316218316f8b7b98786baGlenn Kasten
50934f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent    if (status != NO_ERROR) {
510a997e7a7c5aa2fc7e95316218316f8b7b98786baGlenn Kasten        if (mAudioTrackThread != 0) {
511b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald            mAudioTrackThread->requestExit();   // see comment in AudioTrack.h
512b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald            mAudioTrackThread->requestExitAndWait();
513a997e7a7c5aa2fc7e95316218316f8b7b98786baGlenn Kasten            mAudioTrackThread.clear();
514a997e7a7c5aa2fc7e95316218316f8b7b98786baGlenn Kasten        }
51589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        return status;
51689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
51734f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent
51889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    mStatus = NO_ERROR;
51989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    mUserData = user;
5204ede21d9c1f957baf5e561849ff9bbe4bcbefc20Andy Hung    mLoopCount = 0;
5214ede21d9c1f957baf5e561849ff9bbe4bcbefc20Andy Hung    mLoopStart = 0;
5224ede21d9c1f957baf5e561849ff9bbe4bcbefc20Andy Hung    mLoopEnd = 0;
52353c3b5fc1afe162a8669cb3d27d6bb14e1847e39Andy Hung    mLoopCountNotified = 0;
52489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    mMarkerPosition = 0;
5252c22aeb65e801f663a754d043062f85e49f77739Jean-Michel Trivi    mMarkerReached = false;
52689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    mNewPosition = 0;
52789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    mUpdatePeriod = 0;
528200092b7f21d2b98f30b800e79d152636f9ba225Glenn Kasten    mPosition = 0;
529200092b7f21d2b98f30b800e79d152636f9ba225Glenn Kasten    mReleased = 0;
5307f1bc8af1c46695191bf7e2aba6467f3616629c0Andy Hung    mStartUs = 0;
531d457c970c8d08519cd77280a90b61ae1e342cfe3Marco Nelissen    AudioSystem::acquireAudioSessionId(mSessionId, mClientPid);
5329f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    mSequence = 1;
5339f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    mObservedSequence = mSequence;
5349f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    mInUnderrun = false;
5351b42097f38e72574ed853a35f4e8a66e4739c421Phil Burk    mPreviousTimestampValid = false;
536c8e09c610fabc7390297ecb48e939acbdfe27325Andy Hung    mTimestampStartupGlitchReported = false;
537c8e09c610fabc7390297ecb48e939acbdfe27325Andy Hung    mRetrogradeMotionReported = false;
538b01faa31462e19957ae3c0c3ada07c9576a9494fAndy Hung    mPreviousLocation = ExtendedTimestamp::LOCATION_INVALID;
5392812d9ea3a3a33142dd8e23c9d949c498d6f7a12Phil Burk    mUnderrunCountOffset = 0;
540ea2b9c07b34079f0dbd8610a511e006e69a15adcAndy Hung    mFramesWritten = 0;
541ea2b9c07b34079f0dbd8610a511e006e69a15adcAndy Hung    mFramesWrittenServerOffset = 0;
5429f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
54389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    return NO_ERROR;
54489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
54589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
54689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project// -------------------------------------------------------------------------
54789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
548b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgeraldstatus_t AudioTrack::start()
54989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
550f5aafb209d01ba2ab6cb55d1a12cfc653e2b4be0Eric Laurent    AutoMutex lock(mLock);
551b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald
5529f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (mState == STATE_ACTIVE) {
553b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald        return INVALID_OPERATION;
5549f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
5551703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent
5569f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    mInUnderrun = true;
5572b584244930c9de0e3bc46898a801e9ccb731900Eric Laurent
5589f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    State previousState = mState;
559b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald    if (previousState == STATE_PAUSED_STOPPING) {
560b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald        mState = STATE_STOPPING;
561b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald    } else {
562b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald        mState = STATE_ACTIVE;
563b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald    }
564200092b7f21d2b98f30b800e79d152636f9ba225Glenn Kasten    (void) updateAndGetPosition_l();
5659f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (previousState == STATE_STOPPED || previousState == STATE_FLUSHED) {
5669f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        // reset current position as seen by client to 0
567200092b7f21d2b98f30b800e79d152636f9ba225Glenn Kasten        mPosition = 0;
5681b42097f38e72574ed853a35f4e8a66e4739c421Phil Burk        mPreviousTimestampValid = false;
569c8e09c610fabc7390297ecb48e939acbdfe27325Andy Hung        mTimestampStartupGlitchReported = false;
570c8e09c610fabc7390297ecb48e939acbdfe27325Andy Hung        mRetrogradeMotionReported = false;
571b01faa31462e19957ae3c0c3ada07c9576a9494fAndy Hung        mPreviousLocation = ExtendedTimestamp::LOCATION_INVALID;
5721b42097f38e72574ed853a35f4e8a66e4739c421Phil Burk
573e1e9846a786a0d77a13b44f8e798e03b4cba9d77Andy Hung        // read last server side position change via timestamp.
574e1e9846a786a0d77a13b44f8e798e03b4cba9d77Andy Hung        ExtendedTimestamp ets;
575e1e9846a786a0d77a13b44f8e798e03b4cba9d77Andy Hung        if (mProxy->getTimestamp(&ets) == OK &&
576e1e9846a786a0d77a13b44f8e798e03b4cba9d77Andy Hung                ets.mTimeNs[ExtendedTimestamp::LOCATION_SERVER] > 0) {
577e1e9846a786a0d77a13b44f8e798e03b4cba9d77Andy Hung            // Server side has consumed something, but is it finished consuming?
578e1e9846a786a0d77a13b44f8e798e03b4cba9d77Andy Hung            // It is possible since flush and stop are asynchronous that the server
579e1e9846a786a0d77a13b44f8e798e03b4cba9d77Andy Hung            // is still active at this point.
580e1e9846a786a0d77a13b44f8e798e03b4cba9d77Andy Hung            ALOGV("start: server read:%lld  cumulative flushed:%lld  client written:%lld",
581e1e9846a786a0d77a13b44f8e798e03b4cba9d77Andy Hung                    (long long)(mFramesWrittenServerOffset
582e1e9846a786a0d77a13b44f8e798e03b4cba9d77Andy Hung                            + ets.mPosition[ExtendedTimestamp::LOCATION_SERVER]),
583e1e9846a786a0d77a13b44f8e798e03b4cba9d77Andy Hung                    (long long)ets.mFlushed,
584e1e9846a786a0d77a13b44f8e798e03b4cba9d77Andy Hung                    (long long)mFramesWritten);
585e1e9846a786a0d77a13b44f8e798e03b4cba9d77Andy Hung            mFramesWrittenServerOffset = -ets.mPosition[ExtendedTimestamp::LOCATION_SERVER];
58661be84167c1a11c8a030e00a2b79b2bc4fdf617fAndy Hung        }
587e1e9846a786a0d77a13b44f8e798e03b4cba9d77Andy Hung        mFramesWritten = 0;
588e1e9846a786a0d77a13b44f8e798e03b4cba9d77Andy Hung        mProxy->clearTimestamp(); // need new server push for valid timestamp
589e1e9846a786a0d77a13b44f8e798e03b4cba9d77Andy Hung        mMarkerReached = false;
59061be84167c1a11c8a030e00a2b79b2bc4fdf617fAndy Hung
5917f1bc8af1c46695191bf7e2aba6467f3616629c0Andy Hung        // For offloaded tracks, we don't know if the hardware counters are really zero here,
5927f1bc8af1c46695191bf7e2aba6467f3616629c0Andy Hung        // since the flush is asynchronous and stop may not fully drain.
5937f1bc8af1c46695191bf7e2aba6467f3616629c0Andy Hung        // We save the time when the track is started to later verify whether
5947f1bc8af1c46695191bf7e2aba6467f3616629c0Andy Hung        // the counters are realistic (i.e. start from zero after this time).
5957f1bc8af1c46695191bf7e2aba6467f3616629c0Andy Hung        mStartUs = getNowUs();
5967f1bc8af1c46695191bf7e2aba6467f3616629c0Andy Hung
597ec9a032c2e104ab1e3b5bf73e69dab1408ced0adEric Laurent        // force refresh of remaining frames by processAudioBuffer() as last
598ec9a032c2e104ab1e3b5bf73e69dab1408ced0adEric Laurent        // write before stop could be partial.
599ec9a032c2e104ab1e3b5bf73e69dab1408ced0adEric Laurent        mRefreshRemaining = true;
60089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
601200092b7f21d2b98f30b800e79d152636f9ba225Glenn Kasten    mNewPosition = mPosition + mUpdatePeriod;
60296f60d8f04432a1ed503b3e24d5736d28c63c9a2Glenn Kasten    int32_t flags = android_atomic_and(~CBLK_DISABLED, &mCblk->mFlags);
60389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
6049f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    status_t status = NO_ERROR;
6059f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (!(flags & CBLK_INVALID)) {
6069f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        status = mAudioTrack->start();
6079f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        if (status == DEAD_OBJECT) {
6089f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            flags |= CBLK_INVALID;
60989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        }
6109f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
6119f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (flags & CBLK_INVALID) {
6129f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        status = restoreTrack_l("start");
6139f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
6149f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
61579629f0716f04e79064256362be56730077b8c50Andy Hung    // resume or pause the callback thread as needed.
61679629f0716f04e79064256362be56730077b8c50Andy Hung    sp<AudioTrackThread> t = mAudioTrackThread;
61779629f0716f04e79064256362be56730077b8c50Andy Hung    if (status == NO_ERROR) {
61879629f0716f04e79064256362be56730077b8c50Andy Hung        if (t != 0) {
61979629f0716f04e79064256362be56730077b8c50Andy Hung            if (previousState == STATE_STOPPING) {
62079629f0716f04e79064256362be56730077b8c50Andy Hung                mProxy->interrupt();
62179629f0716f04e79064256362be56730077b8c50Andy Hung            } else {
62279629f0716f04e79064256362be56730077b8c50Andy Hung                t->resume();
62379629f0716f04e79064256362be56730077b8c50Andy Hung            }
62479629f0716f04e79064256362be56730077b8c50Andy Hung        } else {
62579629f0716f04e79064256362be56730077b8c50Andy Hung            mPreviousPriority = getpriority(PRIO_PROCESS, 0);
62679629f0716f04e79064256362be56730077b8c50Andy Hung            get_sched_policy(0, &mPreviousSchedulingGroup);
62779629f0716f04e79064256362be56730077b8c50Andy Hung            androidSetThreadPriority(0, ANDROID_PRIORITY_AUDIO);
62879629f0716f04e79064256362be56730077b8c50Andy Hung        }
62979629f0716f04e79064256362be56730077b8c50Andy Hung    } else {
6309f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        ALOGE("start() status %d", status);
6319f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        mState = previousState;
63289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        if (t != 0) {
633b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald            if (previousState != STATE_STOPPING) {
634b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald                t->pause();
635b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald            }
63689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        } else {
637879135196fd1c97deefc538c888037c56c2879a7Glenn Kasten            setpriority(PRIO_PROCESS, 0, mPreviousPriority);
638a636433cbd09c0708b85f337ef45c0cdef3bcb4dGlenn Kasten            set_sched_policy(0, mPreviousSchedulingGroup);
63989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        }
64089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
64189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
642b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald    return status;
6439f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten}
6449f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
6459f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kastenvoid AudioTrack::stop()
6469f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten{
6479f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    AutoMutex lock(mLock);
648397edb3377e5775f4df60afb8bf6d4711e5adc0eGlenn Kasten    if (mState != STATE_ACTIVE && mState != STATE_PAUSED) {
6499f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        return;
6509f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
6519f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
65223a7545c4de71e989c2d8ebf1d5b9dcf463c36a9Glenn Kasten    if (isOffloaded_l()) {
653b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald        mState = STATE_STOPPING;
654b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald    } else {
655b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald        mState = STATE_STOPPED;
656c2813e568aa476e03d159529c0af28c99536db8dAndy Hung        mReleased = 0;
657b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald    }
658b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald
6599f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    mProxy->interrupt();
6609f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    mAudioTrack->stop();
66161be84167c1a11c8a030e00a2b79b2bc4fdf617fAndy Hung
66261be84167c1a11c8a030e00a2b79b2bc4fdf617fAndy Hung    // Note: legacy handling - stop does not clear playback marker
66361be84167c1a11c8a030e00a2b79b2bc4fdf617fAndy Hung    // and periodic update counter, but flush does for streaming tracks.
6649b4615887c23548438fd0d8e3d8f04ac21912850Andy Hung
6659f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (mSharedBuffer != 0) {
6669b4615887c23548438fd0d8e3d8f04ac21912850Andy Hung        // clear buffer position and loop count.
6679b4615887c23548438fd0d8e3d8f04ac21912850Andy Hung        mStaticProxy->setBufferPositionAndLoop(0 /* position */,
6689b4615887c23548438fd0d8e3d8f04ac21912850Andy Hung                0 /* loopStart */, 0 /* loopEnd */, 0 /* loopCount */);
6699f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
670b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald
6719f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    sp<AudioTrackThread> t = mAudioTrackThread;
6729f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (t != 0) {
67323a7545c4de71e989c2d8ebf1d5b9dcf463c36a9Glenn Kasten        if (!isOffloaded_l()) {
674b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald            t->pause();
675b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald        }
6769f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    } else {
6779f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        setpriority(PRIO_PROCESS, 0, mPreviousPriority);
6789f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        set_sched_policy(0, mPreviousSchedulingGroup);
6799f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
68089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
68189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
68289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectbool AudioTrack::stopped() const
68389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
6849a2aaf927e56a4b4acab23ef16b3f133a9f48a63Glenn Kasten    AutoMutex lock(mLock);
6859f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    return mState != STATE_ACTIVE;
68689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
68789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
68889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectvoid AudioTrack::flush()
68989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
6909f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (mSharedBuffer != 0) {
6919f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        return;
6929f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
6931703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent    AutoMutex lock(mLock);
6949f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (mState == STATE_ACTIVE || mState == STATE_FLUSHED) {
6959f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        return;
6964bae3649d504d590a546717a8e49f96a30d9a745Glenn Kasten    }
6979f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    flush_l();
6981703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent}
6991703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent
7001703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurentvoid AudioTrack::flush_l()
7011703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent{
7029f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    ALOG_ASSERT(mState != STATE_ACTIVE);
703c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent
7042c22aeb65e801f663a754d043062f85e49f77739Jean-Michel Trivi    // clear playback marker and periodic update counter
7052c22aeb65e801f663a754d043062f85e49f77739Jean-Michel Trivi    mMarkerPosition = 0;
7062c22aeb65e801f663a754d043062f85e49f77739Jean-Michel Trivi    mMarkerReached = false;
7072c22aeb65e801f663a754d043062f85e49f77739Jean-Michel Trivi    mUpdatePeriod = 0;
708b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald    mRefreshRemaining = true;
709c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent
7109f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    mState = STATE_FLUSHED;
711c2813e568aa476e03d159529c0af28c99536db8dAndy Hung    mReleased = 0;
71223a7545c4de71e989c2d8ebf1d5b9dcf463c36a9Glenn Kasten    if (isOffloaded_l()) {
713b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald        mProxy->interrupt();
714b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald    }
7159f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    mProxy->flush();
7164bae3649d504d590a546717a8e49f96a30d9a745Glenn Kasten    mAudioTrack->flush();
71789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
71889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
71989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectvoid AudioTrack::pause()
72089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
721f5aafb209d01ba2ab6cb55d1a12cfc653e2b4be0Eric Laurent    AutoMutex lock(mLock);
722b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald    if (mState == STATE_ACTIVE) {
723b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald        mState = STATE_PAUSED;
724b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald    } else if (mState == STATE_STOPPING) {
725b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald        mState = STATE_PAUSED_STOPPING;
726b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald    } else {
7279f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        return;
72889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
7299f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    mProxy->interrupt();
7309f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    mAudioTrack->pause();
7317064fd2dcdfeafea53cd5a992bb78c413542f29fHaynes Mathew George
7323a90f2849d49bf65f2d6257fd6da30ae46d745faMarco Nelissen    if (isOffloaded_l()) {
733142f519aa1acd5804d111e60d100f170fed28405Glenn Kasten        if (mOutput != AUDIO_IO_HANDLE_NONE) {
7347f1bc8af1c46695191bf7e2aba6467f3616629c0Andy Hung            // An offload output can be re-used between two audio tracks having
7357f1bc8af1c46695191bf7e2aba6467f3616629c0Andy Hung            // the same configuration. A timestamp query for a paused track
7367f1bc8af1c46695191bf7e2aba6467f3616629c0Andy Hung            // while the other is running would return an incorrect time.
7377f1bc8af1c46695191bf7e2aba6467f3616629c0Andy Hung            // To fix this, cache the playback position on a pause() and return
7387f1bc8af1c46695191bf7e2aba6467f3616629c0Andy Hung            // this time when requested until the track is resumed.
739