AudioTrack.cpp revision 223fd5c9738e9665e495904d37d4632414b68c1e
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/AudioResamplerPublic.h>
32cd04484f4837b8ca0041d118286ab6a98e84fc75Andy Hung
33fce7a473248381cc83a01855f92581077d3c9ee2Dima Zavin#define WAIT_PERIOD_MS                  10
34b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald#define WAIT_STREAM_END_TIMEOUT_SEC     120
35b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald
3653c3b5fc1afe162a8669cb3d27d6bb14e1847e39Andy Hung
37511754b5839fd9b09fc56b89ae007fbc39084a33Glenn Kastennamespace android {
3889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project// ---------------------------------------------------------------------------
3933005a932c60a0780fe9b7307d5988df3d9f6c26Chia-chi Yeh
4033005a932c60a0780fe9b7307d5988df3d9f6c26Chia-chi Yehstatic int64_t convertTimespecToUs(const struct timespec &tv)
41a7f03353d5f172016f324e2a01f301cca6794152Andy Hung{
42a7f03353d5f172016f324e2a01f301cca6794152Andy Hung    return tv.tv_sec * 1000000ll + tv.tv_nsec / 1000;
434ede21d9c1f957baf5e561849ff9bbe4bcbefc20Andy Hung}
44a7f03353d5f172016f324e2a01f301cca6794152Andy Hung
454ede21d9c1f957baf5e561849ff9bbe4bcbefc20Andy Hung// current monotonic time in microseconds.
464ede21d9c1f957baf5e561849ff9bbe4bcbefc20Andy Hungstatic int64_t getNowUs()
474ede21d9c1f957baf5e561849ff9bbe4bcbefc20Andy Hung{
48a7f03353d5f172016f324e2a01f301cca6794152Andy Hung    struct timespec tv;
49a7f03353d5f172016f324e2a01f301cca6794152Andy Hung    (void) clock_gettime(CLOCK_MONOTONIC, &tv);
50a7f03353d5f172016f324e2a01f301cca6794152Andy Hung    return convertTimespecToUs(tv);
51a7f03353d5f172016f324e2a01f301cca6794152Andy Hung}
52a7f03353d5f172016f324e2a01f301cca6794152Andy Hung
53a7f03353d5f172016f324e2a01f301cca6794152Andy Hung// static
54a7f03353d5f172016f324e2a01f301cca6794152Andy Hungstatus_t AudioTrack::getMinFrameCount(
55a7f03353d5f172016f324e2a01f301cca6794152Andy Hung        size_t* frameCount,
56a7f03353d5f172016f324e2a01f301cca6794152Andy Hung        audio_stream_type_t streamType,
57a7f03353d5f172016f324e2a01f301cca6794152Andy Hung        uint32_t sampleRate)
587f1bc8af1c46695191bf7e2aba6467f3616629c0Andy Hung{
597f1bc8af1c46695191bf7e2aba6467f3616629c0Andy Hung    if (frameCount == NULL) {
607f1bc8af1c46695191bf7e2aba6467f3616629c0Andy Hung        return BAD_VALUE;
617f1bc8af1c46695191bf7e2aba6467f3616629c0Andy Hung    }
627f1bc8af1c46695191bf7e2aba6467f3616629c0Andy Hung
637f1bc8af1c46695191bf7e2aba6467f3616629c0Andy Hung    // FIXME merge with similar code in createTrack_l(), except we're missing
647f1bc8af1c46695191bf7e2aba6467f3616629c0Andy Hung    //       some information here that is available in createTrack_l():
657f1bc8af1c46695191bf7e2aba6467f3616629c0Andy Hung    //          audio_io_handle_t output
667f1bc8af1c46695191bf7e2aba6467f3616629c0Andy Hung    //          audio_format_t format
677f1bc8af1c46695191bf7e2aba6467f3616629c0Andy Hung    //          audio_channel_mask_t channelMask
687f1bc8af1c46695191bf7e2aba6467f3616629c0Andy Hung    //          audio_output_flags_t flags
697f1bc8af1c46695191bf7e2aba6467f3616629c0Andy Hung    uint32_t afSampleRate;
707f1bc8af1c46695191bf7e2aba6467f3616629c0Andy Hung    status_t status;
7126145643ce22d797b3b1675c82c47a2d8c79ecaaAndy Hung    status = AudioSystem::getOutputSamplingRate(&afSampleRate, streamType);
7226145643ce22d797b3b1675c82c47a2d8c79ecaaAndy Hung    if (status != NO_ERROR) {
7326145643ce22d797b3b1675c82c47a2d8c79ecaaAndy Hung        ALOGE("Unable to query output sample rate for stream type %d; status %d",
7426145643ce22d797b3b1675c82c47a2d8c79ecaaAndy Hung                streamType, status);
7526145643ce22d797b3b1675c82c47a2d8c79ecaaAndy Hung        return status;
7626145643ce22d797b3b1675c82c47a2d8c79ecaaAndy Hung    }
7726145643ce22d797b3b1675c82c47a2d8c79ecaaAndy Hung    size_t afFrameCount;
7826145643ce22d797b3b1675c82c47a2d8c79ecaaAndy Hung    status = AudioSystem::getOutputFrameCount(&afFrameCount, streamType);
7926145643ce22d797b3b1675c82c47a2d8c79ecaaAndy Hung    if (status != NO_ERROR) {
8026145643ce22d797b3b1675c82c47a2d8c79ecaaAndy Hung        ALOGE("Unable to query output frame count for stream type %d; status %d",
816c7f062d3149d6890daaee64828959ad6f61ea54Ricardo Garcia                streamType, status);
8226145643ce22d797b3b1675c82c47a2d8c79ecaaAndy Hung        return status;
8326145643ce22d797b3b1675c82c47a2d8c79ecaaAndy Hung    }
8426145643ce22d797b3b1675c82c47a2d8c79ecaaAndy Hung    uint32_t afLatency;
8526145643ce22d797b3b1675c82c47a2d8c79ecaaAndy Hung    status = AudioSystem::getOutputLatency(&afLatency, streamType);
8626145643ce22d797b3b1675c82c47a2d8c79ecaaAndy Hung    if (status != NO_ERROR) {
8726145643ce22d797b3b1675c82c47a2d8c79ecaaAndy Hung        ALOGE("Unable to query output latency for stream type %d; status %d",
8826145643ce22d797b3b1675c82c47a2d8c79ecaaAndy Hung                streamType, status);
898edb8dc44b8a2f81bdb5db645b6b708548771a31Andy Hung        return status;
908edb8dc44b8a2f81bdb5db645b6b708548771a31Andy Hung    }
918edb8dc44b8a2f81bdb5db645b6b708548771a31Andy Hung
928edb8dc44b8a2f81bdb5db645b6b708548771a31Andy Hung    // Ensure that buffer depth covers at least audio hardware latency
93ea38ee7742e799b23bd8675f5801ef72f94de0f4Glenn Kasten    uint32_t minBufCount = afLatency / ((1000 * afFrameCount) / afSampleRate);
948edb8dc44b8a2f81bdb5db645b6b708548771a31Andy Hung    if (minBufCount < 2) {
958edb8dc44b8a2f81bdb5db645b6b708548771a31Andy Hung        minBufCount = 2;
968edb8dc44b8a2f81bdb5db645b6b708548771a31Andy Hung    }
978edb8dc44b8a2f81bdb5db645b6b708548771a31Andy Hung
988edb8dc44b8a2f81bdb5db645b6b708548771a31Andy Hung    *frameCount = (sampleRate == 0) ? afFrameCount * minBufCount :
998edb8dc44b8a2f81bdb5db645b6b708548771a31Andy Hung            afFrameCount * minBufCount * uint64_t(sampleRate) / afSampleRate;
100ea38ee7742e799b23bd8675f5801ef72f94de0f4Glenn Kasten    // The formula above should always produce a non-zero value, but return an error
101ea38ee7742e799b23bd8675f5801ef72f94de0f4Glenn Kasten    // in the unlikely event that it does not, as that's part of the API contract.
102ea38ee7742e799b23bd8675f5801ef72f94de0f4Glenn Kasten    if (*frameCount == 0) {
103ea38ee7742e799b23bd8675f5801ef72f94de0f4Glenn Kasten        ALOGE("AudioTrack::getMinFrameCount failed for streamType %d, sampleRate %d",
104ea38ee7742e799b23bd8675f5801ef72f94de0f4Glenn Kasten                streamType, sampleRate);
105ea38ee7742e799b23bd8675f5801ef72f94de0f4Glenn Kasten        return BAD_VALUE;
106ea38ee7742e799b23bd8675f5801ef72f94de0f4Glenn Kasten    }
1078edb8dc44b8a2f81bdb5db645b6b708548771a31Andy Hung    ALOGV("getMinFrameCount=%zu: afFrameCount=%zu, minBufCount=%d, afSampleRate=%d, afLatency=%d",
108ea38ee7742e799b23bd8675f5801ef72f94de0f4Glenn Kasten            *frameCount, afFrameCount, minBufCount, afSampleRate, afLatency);
109ea38ee7742e799b23bd8675f5801ef72f94de0f4Glenn Kasten    return NO_ERROR;
110ea38ee7742e799b23bd8675f5801ef72f94de0f4Glenn Kasten}
1118edb8dc44b8a2f81bdb5db645b6b708548771a31Andy Hung
1128edb8dc44b8a2f81bdb5db645b6b708548771a31Andy Hung// ---------------------------------------------------------------------------
1138edb8dc44b8a2f81bdb5db645b6b708548771a31Andy Hung
1148edb8dc44b8a2f81bdb5db645b6b708548771a31Andy HungAudioTrack::AudioTrack()
11533005a932c60a0780fe9b7307d5988df3d9f6c26Chia-chi Yeh    : mStatus(NO_INIT),
11633005a932c60a0780fe9b7307d5988df3d9f6c26Chia-chi Yeh      mIsTimed(false),
117e33054eb968cbf8ccaee1b0ff0301403902deed6Glenn Kasten      mPreviousPriority(ANDROID_PRIORITY_NORMAL),
118fff6d715a8db0daf08a50634f242c40268de3d49Glenn Kasten      mPreviousSchedulingGroup(SP_DEFAULT),
11933005a932c60a0780fe9b7307d5988df3d9f6c26Chia-chi Yeh      mPausedPosition(0)
12033005a932c60a0780fe9b7307d5988df3d9f6c26Chia-chi Yeh{
121d65d73c4ae74d084751b417615a78cbe7a51372aGlenn Kasten    mAttributes.content_type = AUDIO_CONTENT_TYPE_UNKNOWN;
122d65d73c4ae74d084751b417615a78cbe7a51372aGlenn Kasten    mAttributes.usage = AUDIO_USAGE_UNKNOWN;
123d65d73c4ae74d084751b417615a78cbe7a51372aGlenn Kasten    mAttributes.flags = 0x0;
12404cd0186305e2b59d23c9147787046c6662029ccGlenn Kasten    strcpy(mAttributes.tags, "");
1250e48d25606c82def035ad10a5b3923767a765cddAndy Hung}
126e0fa467e1150c65a7b1b1ed904c579b40f97c9dfGlenn Kasten
127e0fa467e1150c65a7b1b1ed904c579b40f97c9dfGlenn KastenAudioTrack::AudioTrack(
128e0fa467e1150c65a7b1b1ed904c579b40f97c9dfGlenn Kasten        audio_stream_type_t streamType,
1290e48d25606c82def035ad10a5b3923767a765cddAndy Hung        uint32_t sampleRate,
1303b16c766d1ae2cfd8487e8ffb2b23936fc0a8e17Glenn Kasten        audio_format_t format,
13166a0467fdddada4caabd0f0a999fbb367fea7beeGlenn Kasten        audio_channel_mask_t channelMask,
13266a0467fdddada4caabd0f0a999fbb367fea7beeGlenn Kasten        size_t frameCount,
13366a0467fdddada4caabd0f0a999fbb367fea7beeGlenn Kasten        audio_output_flags_t flags,
13470c0bfbe5ec88dcc3efa2bd8df26f36cff1cf03aGlenn Kasten        callback_t cbf,
13570c0bfbe5ec88dcc3efa2bd8df26f36cff1cf03aGlenn Kasten        void* user,
13666a0467fdddada4caabd0f0a999fbb367fea7beeGlenn Kasten        uint32_t notificationFrames,
13733005a932c60a0780fe9b7307d5988df3d9f6c26Chia-chi Yeh        int sessionId,
138e33054eb968cbf8ccaee1b0ff0301403902deed6Glenn Kasten        transfer_type transferType,
13966a0467fdddada4caabd0f0a999fbb367fea7beeGlenn Kasten        const audio_offload_info_t *offloadInfo,
14066a0467fdddada4caabd0f0a999fbb367fea7beeGlenn Kasten        int uid,
14170c0bfbe5ec88dcc3efa2bd8df26f36cff1cf03aGlenn Kasten        pid_t pid,
14270c0bfbe5ec88dcc3efa2bd8df26f36cff1cf03aGlenn Kasten        const audio_attributes_t* pAttributes)
14366a0467fdddada4caabd0f0a999fbb367fea7beeGlenn Kasten    : mStatus(NO_INIT),
14433005a932c60a0780fe9b7307d5988df3d9f6c26Chia-chi Yeh      mIsTimed(false),
14533005a932c60a0780fe9b7307d5988df3d9f6c26Chia-chi Yeh      mPreviousPriority(ANDROID_PRIORITY_NORMAL),
14666a0467fdddada4caabd0f0a999fbb367fea7beeGlenn Kasten      mPreviousSchedulingGroup(SP_DEFAULT),
14766a0467fdddada4caabd0f0a999fbb367fea7beeGlenn Kasten      mPausedPosition(0)
14870c0bfbe5ec88dcc3efa2bd8df26f36cff1cf03aGlenn Kasten{
14970c0bfbe5ec88dcc3efa2bd8df26f36cff1cf03aGlenn Kasten    mStatus = set(streamType, sampleRate, format, channelMask,
15066a0467fdddada4caabd0f0a999fbb367fea7beeGlenn Kasten            frameCount, flags, cbf, user, notificationFrames,
15133005a932c60a0780fe9b7307d5988df3d9f6c26Chia-chi Yeh            0 /*sharedBuffer*/, false /*threadCanCallJava*/, sessionId, transferType,
15233005a932c60a0780fe9b7307d5988df3d9f6c26Chia-chi Yeh            offloadInfo, uid, pid, pAttributes);
1538edb8dc44b8a2f81bdb5db645b6b708548771a31Andy Hung}
1548edb8dc44b8a2f81bdb5db645b6b708548771a31Andy Hung
155ea38ee7742e799b23bd8675f5801ef72f94de0f4Glenn KastenAudioTrack::AudioTrack(
156ea38ee7742e799b23bd8675f5801ef72f94de0f4Glenn Kasten        audio_stream_type_t streamType,
15733005a932c60a0780fe9b7307d5988df3d9f6c26Chia-chi Yeh        uint32_t sampleRate,
1580e48d25606c82def035ad10a5b3923767a765cddAndy Hung        audio_format_t format,
1590e48d25606c82def035ad10a5b3923767a765cddAndy Hung        audio_channel_mask_t channelMask,
1600e48d25606c82def035ad10a5b3923767a765cddAndy Hung        const sp<IMemory>& sharedBuffer,
16166a0467fdddada4caabd0f0a999fbb367fea7beeGlenn Kasten        audio_output_flags_t flags,
1620e48d25606c82def035ad10a5b3923767a765cddAndy Hung        callback_t cbf,
16366a0467fdddada4caabd0f0a999fbb367fea7beeGlenn Kasten        void* user,
16466a0467fdddada4caabd0f0a999fbb367fea7beeGlenn Kasten        uint32_t notificationFrames,
16566a0467fdddada4caabd0f0a999fbb367fea7beeGlenn Kasten        int sessionId,
1668edb8dc44b8a2f81bdb5db645b6b708548771a31Andy Hung        transfer_type transferType,
1678edb8dc44b8a2f81bdb5db645b6b708548771a31Andy Hung        const audio_offload_info_t *offloadInfo,
16833005a932c60a0780fe9b7307d5988df3d9f6c26Chia-chi Yeh        int uid,
16933005a932c60a0780fe9b7307d5988df3d9f6c26Chia-chi Yeh        pid_t pid,
17089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        const audio_attributes_t* pAttributes)
17189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    : mStatus(NO_INIT),
17289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project      mIsTimed(false),
17389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project      mPreviousPriority(ANDROID_PRIORITY_NORMAL),
174879135196fd1c97deefc538c888037c56c2879a7Glenn Kasten      mPreviousSchedulingGroup(SP_DEFAULT),
1759b3359feabbf138bb965da5173434da78bfe0929Haynes Mathew George      mPausedPosition(0)
1764ff14bae91075eb274eb1c2975982358946e7e63John Grossman{
1777064fd2dcdfeafea53cd5a992bb78c413542f29fHaynes Mathew George    mStatus = set(streamType, sampleRate, format, channelMask,
178aa9811945f575614b3482d09e4d969792701cebbPaul McLean            0 /*frameCount*/, flags, cbf, user, notificationFrames,
179aa9811945f575614b3482d09e4d969792701cebbPaul McLean            sharedBuffer, false /*threadCanCallJava*/, sessionId, transferType, offloadInfo,
18089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project            uid, pid, pAttributes);
181faabb51ceef13bf1e3f692219ac410c1cd75d0deJean-Michel Trivi}
182faabb51ceef13bf1e3f692219ac410c1cd75d0deJean-Michel Trivi
183faabb51ceef13bf1e3f692219ac410c1cd75d0deJean-Michel TriviAudioTrack::~AudioTrack()
184faabb51ceef13bf1e3f692219ac410c1cd75d0deJean-Michel Trivi{
18589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    if (mStatus == NO_ERROR) {
18689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        // Make sure that callback function exits in the case where
18789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        // it is looping on buffer full condition in obtainBuffer().
188fff6d715a8db0daf08a50634f242c40268de3d49Glenn Kasten        // Otherwise the callback thread will never exit.
18989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        stop();
190e1c3962e268ffc12bfd1bd9ea84da1f135f36960Glenn Kasten        if (mAudioTrackThread != 0) {
19128b76b334f92a15a2be3cc9e2f7d229a3275d1acGlenn Kasten            mProxy->interrupt();
192bce50bfc3846ab008bafa75c5d3f29fd7b5395f7Glenn Kasten            mAudioTrackThread->requestExit();   // see comment in AudioTrack.h
1930ca3cf94c0dfc173ad7886ae162c4b67067539f6Eric Laurent            mAudioTrackThread->requestExitAndWait();
19489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project            mAudioTrackThread.clear();
19589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        }
196ea38ee7742e799b23bd8675f5801ef72f94de0f4Glenn Kasten        mAudioTrack->asBinder()->unlinkToDeath(mDeathNotifier, this);
197d848eb48c121c119e8ba7583efc75415fe102570Glenn Kasten        mAudioTrack.clear();
198ad3af3305f024bcbbd55c894a4995e449498e1baRichard Fitzgerald        mCblkMemory.clear();
199462fd2fa9eef642b0574aa7409de0bde3fec8d43Marco Nelissen        mSharedBuffer.clear();
200d457c970c8d08519cd77280a90b61ae1e342cfe3Marco Nelissen        IPCThreadState::self()->flushCommands();
201d9d7fa0873796ac661c44a7fcd6ad5ff697ff01fJean-Michel Trivi        ALOGV("~AudioTrack, releasing session id from %d on behalf of %d",
202faeb0f291330134dc4468359a36e099aae508449Ronghua Wu                IPCThreadState::self()->getCallingPid(), mClientPid);
203ff874dc957f9ea70d87f4d627bf903e1fc86d58bAndy Hung        AudioSystem::releaseAudioSessionId(mSessionId, mClientPid);
204ff874dc957f9ea70d87f4d627bf903e1fc86d58bAndy Hung    }
205879135196fd1c97deefc538c888037c56c2879a7Glenn Kasten}
2069b3359feabbf138bb965da5173434da78bfe0929Haynes Mathew George
2074ff14bae91075eb274eb1c2975982358946e7e63John Grossmanstatus_t AudioTrack::set(
2087064fd2dcdfeafea53cd5a992bb78c413542f29fHaynes Mathew George        audio_stream_type_t streamType,
209aa9811945f575614b3482d09e4d969792701cebbPaul McLean        uint32_t sampleRate,
210aa9811945f575614b3482d09e4d969792701cebbPaul McLean        audio_format_t format,
21189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        audio_channel_mask_t channelMask,
2120d255b2d9061ba31f13ada3fc0f7e51916407176Jean-Michel Trivi        size_t frameCount,
213a514bdb58b5de4986679f72b7204b4764f7a2778Eric Laurent        audio_output_flags_t flags,
214462fd2fa9eef642b0574aa7409de0bde3fec8d43Marco Nelissen        callback_t cbf,
215ff874dc957f9ea70d87f4d627bf903e1fc86d58bAndy Hung        void* user,
21689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        uint32_t notificationFrames,
21789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        const sp<IMemory>& sharedBuffer,
218c813985abd8ba61e999b3505f6a332574f87a1beAndreas Huber        bool threadCanCallJava,
219fff6d715a8db0daf08a50634f242c40268de3d49Glenn Kasten        int sessionId,
22089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        transfer_type transferType,
221e1c3962e268ffc12bfd1bd9ea84da1f135f36960Glenn Kasten        const audio_offload_info_t *offloadInfo,
22228b76b334f92a15a2be3cc9e2f7d229a3275d1acGlenn Kasten        int uid,
22389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        pid_t pid,
2240ca3cf94c0dfc173ad7886ae162c4b67067539f6Eric Laurent        const audio_attributes_t* pAttributes)
22589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
22689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    ALOGV("set(): streamType %d, sampleRate %u, format %#x, channelMask %#x, frameCount %zu, "
227ea38ee7742e799b23bd8675f5801ef72f94de0f4Glenn Kasten          "flags #%x, notificationFrames %u, sessionId %d, transferType %d",
228d848eb48c121c119e8ba7583efc75415fe102570Glenn Kasten          streamType, sampleRate, format, channelMask, frameCount, flags, notificationFrames,
229ad3af3305f024bcbbd55c894a4995e449498e1baRichard Fitzgerald          sessionId, transferType);
230462fd2fa9eef642b0574aa7409de0bde3fec8d43Marco Nelissen
231d457c970c8d08519cd77280a90b61ae1e342cfe3Marco Nelissen    switch (transferType) {
232d9d7fa0873796ac661c44a7fcd6ad5ff697ff01fJean-Michel Trivi    case TRANSFER_DEFAULT:
233faeb0f291330134dc4468359a36e099aae508449Ronghua Wu        if (sharedBuffer != 0) {
234ff874dc957f9ea70d87f4d627bf903e1fc86d58bAndy Hung            transferType = TRANSFER_SHARED;
235ff874dc957f9ea70d87f4d627bf903e1fc86d58bAndy Hung        } else if (cbf == NULL || threadCanCallJava) {
236879135196fd1c97deefc538c888037c56c2879a7Glenn Kasten            transferType = TRANSFER_SYNC;
2379b3359feabbf138bb965da5173434da78bfe0929Haynes Mathew George        } else {
2384ff14bae91075eb274eb1c2975982358946e7e63John Grossman            transferType = TRANSFER_CALLBACK;
2397064fd2dcdfeafea53cd5a992bb78c413542f29fHaynes Mathew George        }
240aa9811945f575614b3482d09e4d969792701cebbPaul McLean        break;
241aa9811945f575614b3482d09e4d969792701cebbPaul McLean    case TRANSFER_CALLBACK:
24289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        if (cbf == NULL || sharedBuffer != 0) {
2430d255b2d9061ba31f13ada3fc0f7e51916407176Jean-Michel Trivi            ALOGE("Transfer type TRANSFER_CALLBACK but cbf == NULL || sharedBuffer != 0");
24417a736c3e1d062d7fc916329eb32aef8935614afGlenn Kasten            return BAD_VALUE;
245d457c970c8d08519cd77280a90b61ae1e342cfe3Marco Nelissen        }
246ff874dc957f9ea70d87f4d627bf903e1fc86d58bAndy Hung        break;
24789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    case TRANSFER_OBTAIN:
24889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    case TRANSFER_SYNC:
24989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        if (sharedBuffer != 0) {
25089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project            ALOGE("Transfer type TRANSFER_OBTAIN but sharedBuffer != 0");
25189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project            return BAD_VALUE;
25289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        }
25389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        break;
25489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    case TRANSFER_SHARED:
25589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        if (sharedBuffer == 0) {
25689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project            ALOGE("Transfer type TRANSFER_SHARED but sharedBuffer == 0");
257b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald            return BAD_VALUE;
2583acbd053c842e76e1a40fc8a0bf62de87eebf00fGlenn Kasten        }
25989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        break;
26089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    default:
26189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        ALOGE("Invalid transfer type %d", transferType);
262296fb13dd9b5e90d6a05cce897c3b1e7914a478aEric Laurent        return BAD_VALUE;
263296fb13dd9b5e90d6a05cce897c3b1e7914a478aEric Laurent    }
264296fb13dd9b5e90d6a05cce897c3b1e7914a478aEric Laurent    mSharedBuffer = sharedBuffer;
265296fb13dd9b5e90d6a05cce897c3b1e7914a478aEric Laurent    mTransfer = transferType;
266f888020c6e2735624f2b2a30e72aca24e17b8b4dMarco Nelissen
26753cec22821072719ee02c856e9ac2dda2496c570Glenn Kasten    ALOGV_IF(sharedBuffer != 0, "sharedBuffer: %p, size: %d", sharedBuffer->pointer(),
2683bcffa136909c1fb6e88ee4efd12ccac18360a85Eric Laurent            sharedBuffer->size());
2693bcffa136909c1fb6e88ee4efd12ccac18360a85Eric Laurent
27089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    ALOGV("set() streamType %d frameCount %zu flags %04x", streamType, frameCount, flags);
2714c36d6f48f4eecacc148317f775f65961a4f03d2Glenn Kasten
2724c36d6f48f4eecacc148317f775f65961a4f03d2Glenn Kasten    AutoMutex lock(mLock);
273d457c970c8d08519cd77280a90b61ae1e342cfe3Marco Nelissen
27489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    // invariant that mAudioTrack != 0 is true only after set() returns successfully
27589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    if (mAudioTrack != 0) {
27689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        ALOGE("Track already in use");
27789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        return INVALID_OPERATION;
278fff6d715a8db0daf08a50634f242c40268de3d49Glenn Kasten    }
27989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
280e1c3962e268ffc12bfd1bd9ea84da1f135f36960Glenn Kasten    // handle default values first.
28128b76b334f92a15a2be3cc9e2f7d229a3275d1acGlenn Kasten    // TODO once AudioPolicyManager fully supports audio_attributes_t,
282bce50bfc3846ab008bafa75c5d3f29fd7b5395f7Glenn Kasten    //   remove stream "text-to-speech" redirect
2830ca3cf94c0dfc173ad7886ae162c4b67067539f6Eric Laurent    if ((streamType == AUDIO_STREAM_DEFAULT) || (streamType == AUDIO_STREAM_TTS)) {
28489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        streamType = AUDIO_STREAM_MUSIC;
28589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
286ea38ee7742e799b23bd8675f5801ef72f94de0f4Glenn Kasten
28789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    if (pAttributes == NULL) {
288be916aa1267e2e6b1c148f51d11bcbbc79cb864cEric Laurent        if (uint32_t(streamType) >= AUDIO_STREAM_PUBLIC_CNT) {
289d848eb48c121c119e8ba7583efc75415fe102570Glenn Kasten            ALOGE("Invalid stream type %d", streamType);
290ad3af3305f024bcbbd55c894a4995e449498e1baRichard Fitzgerald            return BAD_VALUE;
291462fd2fa9eef642b0574aa7409de0bde3fec8d43Marco Nelissen        }
292d457c970c8d08519cd77280a90b61ae1e342cfe3Marco Nelissen        setAttributesFromStreamType(streamType);
293faabb51ceef13bf1e3f692219ac410c1cd75d0deJean-Michel Trivi        mStreamType = streamType;
294faeb0f291330134dc4468359a36e099aae508449Ronghua Wu    } else {
295ff874dc957f9ea70d87f4d627bf903e1fc86d58bAndy Hung        if (!isValidAttributes(pAttributes)) {
296ff874dc957f9ea70d87f4d627bf903e1fc86d58bAndy Hung            ALOGE("Invalid attributes: usage=%d content=%d flags=0x%x tags=[%s]",
29789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project                pAttributes->usage, pAttributes->content_type, pAttributes->flags,
298bce50bfc3846ab008bafa75c5d3f29fd7b5395f7Glenn Kasten                pAttributes->tags);
299ea38ee7742e799b23bd8675f5801ef72f94de0f4Glenn Kasten        }
300bce50bfc3846ab008bafa75c5d3f29fd7b5395f7Glenn Kasten        // stream type shouldn't be looked at, this track has audio attributes
3014c36d6f48f4eecacc148317f775f65961a4f03d2Glenn Kasten        memcpy(&mAttributes, pAttributes, sizeof(audio_attributes_t));
30286f04663032ddaa25110149d709bbf896ad83b02Glenn Kasten        setStreamTypeFromAttributes(mAttributes);
30333ff89ba94a527e4293ee5349da01483252d5c83Phil Burk        ALOGV("Building AudioTrack with attributes: usage=%d content=%d flags=0x%x tags=[%s]",
30433ff89ba94a527e4293ee5349da01483252d5c83Phil Burk                mAttributes.usage, mAttributes.content_type, mAttributes.flags, mAttributes.tags);
3059f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
3069f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
3079f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    // these below should probably come from the audioFlinger too...
3089f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (format == AUDIO_FORMAT_DEFAULT) {
3099f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        format = AUDIO_FORMAT_PCM_16_BIT;
3109f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
3119f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
3129f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    // validate parameters
3139f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (!audio_is_valid_format(format)) {
3149f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        ALOGE("Invalid format %#x", format);
3159f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        return BAD_VALUE;
3169f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
3179f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    mFormat = format;
3189f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
3199f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (!audio_is_output_channel(channelMask)) {
3209f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        ALOGE("Invalid channel mask %#x", channelMask);
3219f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        return BAD_VALUE;
3229f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
3239f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    mChannelMask = channelMask;
3249f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    uint32_t channelCount = audio_channel_count_from_out_mask(channelMask);
3259f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    mChannelCount = channelCount;
3269f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
3279f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    // AudioFlinger does not currently support 8-bit data in shared memory
3289f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (format == AUDIO_FORMAT_PCM_8_BIT && sharedBuffer != 0) {
3299f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        ALOGE("8-bit data in shared memory is not supported");
3309f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        return BAD_VALUE;
3319f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
3329f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
3339f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    // force direct flag if format is not linear PCM
3349f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    // or offload was requested
3359f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
3369f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            || !audio_is_linear_pcm(format)) {
3379f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        ALOGV( (flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)
338dd5f4c8c4059f890e81b28b026a688febb4e1dd9Glenn Kasten                    ? "Offload request, forcing to Direct Output"
3399f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten                    : "Not linear PCM, forcing to Direct Output");
340faeb0f291330134dc4468359a36e099aae508449Ronghua Wu        flags = (audio_output_flags_t)
3419f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten                // FIXME why can't we allow direct AND fast?
34297c9f4fd7bc31e2968d816402659ba1c64f10b42Eric Laurent                ((flags | AUDIO_OUTPUT_FLAG_DIRECT) & ~AUDIO_OUTPUT_FLAG_FAST);
34385ab62c4b433df3f1a9826bed1c9bec07a86c750Glenn Kasten    }
34489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    // only allow deep buffering for music stream type
34534fb29696b0f3abf61b10f8d053b1f33d501de0aMark Salyzyn    if (mStreamType != AUDIO_STREAM_MUSIC) {
3461a9ed11a472493cac7f6dfcbfac2064526a493edEric Laurent        flags = (audio_output_flags_t)(flags &~AUDIO_OUTPUT_FLAG_DEEP_BUFFER);
34753cec22821072719ee02c856e9ac2dda2496c570Glenn Kasten    }
3481dd70b9f04961a06fcb73a97fca10a53b3245d3cEric Laurent
34929357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block    if (flags & AUDIO_OUTPUT_FLAG_DIRECT) {
35089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        if (audio_is_linear_pcm(format)) {
35189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project            mFrameSize = channelCount * audio_bytes_per_sample(format);
35289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        } else {
35389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project            mFrameSize = sizeof(uint8_t);
354e83b55dc29ca16092ba02f36f55fa6e0e37fd78cEric Laurent        }
355fce7a473248381cc83a01855f92581077d3c9ee2Dima Zavin        mFrameSizeAF = mFrameSize;
35689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    } else {
357faabb51ceef13bf1e3f692219ac410c1cd75d0deJean-Michel Trivi        ALOG_ASSERT(audio_is_linear_pcm(format));
358223fd5c9738e9665e495904d37d4632414b68c1eEric Laurent        mFrameSize = channelCount * audio_bytes_per_sample(format);
359faabb51ceef13bf1e3f692219ac410c1cd75d0deJean-Michel Trivi        mFrameSizeAF = channelCount * audio_bytes_per_sample(
360faabb51ceef13bf1e3f692219ac410c1cd75d0deJean-Michel Trivi                format == AUDIO_FORMAT_PCM_8_BIT ? AUDIO_FORMAT_PCM_16_BIT : format);
361faabb51ceef13bf1e3f692219ac410c1cd75d0deJean-Michel Trivi        // createTrack will return an error if PCM format is not supported by server,
362faabb51ceef13bf1e3f692219ac410c1cd75d0deJean-Michel Trivi        // so no need to check for specific PCM formats here
363e83b55dc29ca16092ba02f36f55fa6e0e37fd78cEric Laurent    }
364faabb51ceef13bf1e3f692219ac410c1cd75d0deJean-Michel Trivi
365faabb51ceef13bf1e3f692219ac410c1cd75d0deJean-Michel Trivi    // sampling rate must be specified for direct outputs
366faabb51ceef13bf1e3f692219ac410c1cd75d0deJean-Michel Trivi    if (sampleRate == 0 && (flags & AUDIO_OUTPUT_FLAG_DIRECT) != 0) {
367faabb51ceef13bf1e3f692219ac410c1cd75d0deJean-Michel Trivi        return BAD_VALUE;
368faabb51ceef13bf1e3f692219ac410c1cd75d0deJean-Michel Trivi    }
369e83b55dc29ca16092ba02f36f55fa6e0e37fd78cEric Laurent    mSampleRate = sampleRate;
370c6bd5db9d9cf4bba1649b5b7ddea2d23f5de23a9Eric Laurent
371c6bd5db9d9cf4bba1649b5b7ddea2d23f5de23a9Eric Laurent    // Make copy of input parameter offloadInfo so that in the future:
372c6bd5db9d9cf4bba1649b5b7ddea2d23f5de23a9Eric Laurent    //  (a) createTrack_l doesn't need it as an input parameter
37333ff89ba94a527e4293ee5349da01483252d5c83Phil Burk    //  (b) we can support re-creation of offloaded tracks
37433ff89ba94a527e4293ee5349da01483252d5c83Phil Burk    if (offloadInfo != NULL) {
37533ff89ba94a527e4293ee5349da01483252d5c83Phil Burk        mOffloadInfoCopy = *offloadInfo;
376dd5f4c8c4059f890e81b28b026a688febb4e1dd9Glenn Kasten        mOffloadInfo = &mOffloadInfoCopy;
377ea7939a079b3600cab955760839b021326f8cfc3Glenn Kasten    } else {
37889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        mOffloadInfo = NULL;
379e1c3962e268ffc12bfd1bd9ea84da1f135f36960Glenn Kasten    }
380fce7a473248381cc83a01855f92581077d3c9ee2Dima Zavin
381fdb3c07db5d44535eb8c3ec46dc78ad8446c01ebPhil Burk    mVolume[AUDIO_INTERLEAVE_LEFT] = 1.0f;
382fdb3c07db5d44535eb8c3ec46dc78ad8446c01ebPhil Burk    mVolume[AUDIO_INTERLEAVE_RIGHT] = 1.0f;
38389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    mSendLevel = 0.0f;
38489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    // mFrameCount is initialized in createTrack_l
38589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    mReqFrameCount = frameCount;
386fce7a473248381cc83a01855f92581077d3c9ee2Dima Zavin    mNotificationFramesReq = notificationFrames;
387cac3daa6332bf6d1f7d26adc4a9915f3d7992dd9Glenn Kasten    mNotificationFramesAct = 0;
38889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    mSessionId = sessionId;
38989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    int callingpid = IPCThreadState::self()->getCallingPid();
390dd5f4c8c4059f890e81b28b026a688febb4e1dd9Glenn Kasten    int mypid = getpid();
391c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent    if (uid == -1 || (callingpid != mypid)) {
3928ba90326d683b035d99e24db669093e4602a7149Glenn Kasten        mClientUid = IPCThreadState::self()->getCallingUid();
3938ba90326d683b035d99e24db669093e4602a7149Glenn Kasten    } else {
3948ba90326d683b035d99e24db669093e4602a7149Glenn Kasten        mClientUid = uid;
3958ba90326d683b035d99e24db669093e4602a7149Glenn Kasten    }
396e3247bf8dd4f8fa8dfa3a108260241ae4a967569Glenn Kasten    if (pid == -1 || (callingpid != mypid)) {
397e541269be94f3a1072932d51537905b120ef4733Andy Hung        mClientPid = callingpid;
398e3247bf8dd4f8fa8dfa3a108260241ae4a967569Glenn Kasten    } else {
3998ba90326d683b035d99e24db669093e4602a7149Glenn Kasten        mClientPid = pid;
400c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent    }
401b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald    mAuxEffectId = 0;
402b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald    mFlags = flags;
403b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald    mCbf = cbf;
404b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald
405b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald    if (cbf != NULL) {
406b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald        mAudioTrackThread = new AudioTrackThread(*this, threadCanCallJava);
4070ca3cf94c0dfc173ad7886ae162c4b67067539f6Eric Laurent        mAudioTrackThread->run("AudioTrack", ANDROID_PRIORITY_AUDIO, 0 /*stack*/);
4083acbd053c842e76e1a40fc8a0bf62de87eebf00fGlenn Kasten    }
4090ca3cf94c0dfc173ad7886ae162c4b67067539f6Eric Laurent
410c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent    // create the IAudioTrack
411c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent    status_t status = createTrack_l();
412d1f69b0b17acbd96987ecb2f3378abd394d05903Eric Laurent
413d1f69b0b17acbd96987ecb2f3378abd394d05903Eric Laurent    if (status != NO_ERROR) {
414d1f69b0b17acbd96987ecb2f3378abd394d05903Eric Laurent        if (mAudioTrackThread != 0) {
415d1f69b0b17acbd96987ecb2f3378abd394d05903Eric Laurent            mAudioTrackThread->requestExit();   // see comment in AudioTrack.h
416d1f69b0b17acbd96987ecb2f3378abd394d05903Eric Laurent            mAudioTrackThread->requestExitAndWait();
417b773038277ba328696832b690b91ce6e95bd1a6cGlenn Kasten            mAudioTrackThread.clear();
418fdb3c07db5d44535eb8c3ec46dc78ad8446c01ebPhil Burk        }
419b773038277ba328696832b690b91ce6e95bd1a6cGlenn Kasten        return status;
420b773038277ba328696832b690b91ce6e95bd1a6cGlenn Kasten    }
421b773038277ba328696832b690b91ce6e95bd1a6cGlenn Kasten
422b773038277ba328696832b690b91ce6e95bd1a6cGlenn Kasten    mStatus = NO_ERROR;
423e3aa659e9cee7df5c12a80d285cc29ab3b2cbb39Glenn Kasten    mState = STATE_STOPPED;
424fdb3c07db5d44535eb8c3ec46dc78ad8446c01ebPhil Burk    mUserData = user;
425b773038277ba328696832b690b91ce6e95bd1a6cGlenn Kasten    mLoopPeriod = 0;
426b773038277ba328696832b690b91ce6e95bd1a6cGlenn Kasten    mMarkerPosition = 0;
427b773038277ba328696832b690b91ce6e95bd1a6cGlenn Kasten    mMarkerReached = false;
428e3aa659e9cee7df5c12a80d285cc29ab3b2cbb39Glenn Kasten    mNewPosition = 0;
429e3aa659e9cee7df5c12a80d285cc29ab3b2cbb39Glenn Kasten    mUpdatePeriod = 0;
4300d6db582f2ccc9f8943c5f3965e2994b7d137158Eric Laurent    mServer = 0;
4310d6db582f2ccc9f8943c5f3965e2994b7d137158Eric Laurent    mPosition = 0;
4320d6db582f2ccc9f8943c5f3965e2994b7d137158Eric Laurent    mReleased = 0;
4330d6db582f2ccc9f8943c5f3965e2994b7d137158Eric Laurent    mStartUs = 0;
4340d6db582f2ccc9f8943c5f3965e2994b7d137158Eric Laurent    AudioSystem::acquireAudioSessionId(mSessionId, mClientPid);
4353a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar    mSequence = 1;
4365a8a95de6dad1a3bcf3da5a37b35766e89086e13Ricardo Garcia    mObservedSequence = mSequence;
437ff874dc957f9ea70d87f4d627bf903e1fc86d58bAndy Hung    mInUnderrun = false;
438ff874dc957f9ea70d87f4d627bf903e1fc86d58bAndy Hung
4390d6db582f2ccc9f8943c5f3965e2994b7d137158Eric Laurent    return NO_ERROR;
440b5ccb2d99b2af400c70777a6452f090ac14f5a96Glenn Kasten}
441b5ccb2d99b2af400c70777a6452f090ac14f5a96Glenn Kasten
442b5ccb2d99b2af400c70777a6452f090ac14f5a96Glenn Kasten// -------------------------------------------------------------------------
443b5ccb2d99b2af400c70777a6452f090ac14f5a96Glenn Kasten
444b5ccb2d99b2af400c70777a6452f090ac14f5a96Glenn Kastenstatus_t AudioTrack::start()
445b5ccb2d99b2af400c70777a6452f090ac14f5a96Glenn Kasten{
446b5ccb2d99b2af400c70777a6452f090ac14f5a96Glenn Kasten    AutoMutex lock(mLock);
447b5ccb2d99b2af400c70777a6452f090ac14f5a96Glenn Kasten
448b5ccb2d99b2af400c70777a6452f090ac14f5a96Glenn Kasten    if (mState == STATE_ACTIVE) {
449b5ccb2d99b2af400c70777a6452f090ac14f5a96Glenn Kasten        return INVALID_OPERATION;
45066e4635cb09fadcaccf912f37c387396c428378aGlenn Kasten    }
45166e4635cb09fadcaccf912f37c387396c428378aGlenn Kasten
45205632a5fa4b88ca474294887fc92a9fcdf0e2352Glenn Kasten    mInUnderrun = true;
453396fabdb6efcdac5aea3d9f559d1beedf6a4cedcGlenn Kasten
454b603744e96b07b1d5bf745bde593fb2c025cefcfGlenn Kasten    State previousState = mState;
455ea38ee7742e799b23bd8675f5801ef72f94de0f4Glenn Kasten    if (previousState == STATE_PAUSED_STOPPING) {
456ea38ee7742e799b23bd8675f5801ef72f94de0f4Glenn Kasten        mState = STATE_STOPPING;
457ea38ee7742e799b23bd8675f5801ef72f94de0f4Glenn Kasten    } else {
458ea38ee7742e799b23bd8675f5801ef72f94de0f4Glenn Kasten        mState = STATE_ACTIVE;
459ea38ee7742e799b23bd8675f5801ef72f94de0f4Glenn Kasten    }
460ea38ee7742e799b23bd8675f5801ef72f94de0f4Glenn Kasten    (void) updateAndGetPosition_l();
461ea38ee7742e799b23bd8675f5801ef72f94de0f4Glenn Kasten    if (previousState == STATE_STOPPED || previousState == STATE_FLUSHED) {
462ea38ee7742e799b23bd8675f5801ef72f94de0f4Glenn Kasten        // reset current position as seen by client to 0
463ea38ee7742e799b23bd8675f5801ef72f94de0f4Glenn Kasten        mPosition = 0;
464ea38ee7742e799b23bd8675f5801ef72f94de0f4Glenn Kasten        // For offloaded tracks, we don't know if the hardware counters are really zero here,
465ea38ee7742e799b23bd8675f5801ef72f94de0f4Glenn Kasten        // since the flush is asynchronous and stop may not fully drain.
466ea38ee7742e799b23bd8675f5801ef72f94de0f4Glenn Kasten        // We save the time when the track is started to later verify whether
467ea38ee7742e799b23bd8675f5801ef72f94de0f4Glenn Kasten        // the counters are realistic (i.e. start from zero after this time).
468ea38ee7742e799b23bd8675f5801ef72f94de0f4Glenn Kasten        mStartUs = getNowUs();
469ea38ee7742e799b23bd8675f5801ef72f94de0f4Glenn Kasten
470ea38ee7742e799b23bd8675f5801ef72f94de0f4Glenn Kasten        // force refresh of remaining frames by processAudioBuffer() as last
471ea38ee7742e799b23bd8675f5801ef72f94de0f4Glenn Kasten        // write before stop could be partial.
472ea38ee7742e799b23bd8675f5801ef72f94de0f4Glenn Kasten        mRefreshRemaining = true;
473ea38ee7742e799b23bd8675f5801ef72f94de0f4Glenn Kasten    }
474ea38ee7742e799b23bd8675f5801ef72f94de0f4Glenn Kasten    mNewPosition = mPosition + mUpdatePeriod;
475ea38ee7742e799b23bd8675f5801ef72f94de0f4Glenn Kasten    int32_t flags = android_atomic_and(~CBLK_DISABLED, &mCblk->mFlags);
476ea38ee7742e799b23bd8675f5801ef72f94de0f4Glenn Kasten
477ea38ee7742e799b23bd8675f5801ef72f94de0f4Glenn Kasten    sp<AudioTrackThread> t = mAudioTrackThread;
4789f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (t != 0) {
479caf7f48a0ef558689d39aafd187c1571ff4128b4Eric Laurent        if (previousState == STATE_STOPPING) {
480d848eb48c121c119e8ba7583efc75415fe102570Glenn Kasten            mProxy->interrupt();
481caf7f48a0ef558689d39aafd187c1571ff4128b4Eric Laurent        } else {
482caf7f48a0ef558689d39aafd187c1571ff4128b4Eric Laurent            t->resume();
483caf7f48a0ef558689d39aafd187c1571ff4128b4Eric Laurent        }
484d457c970c8d08519cd77280a90b61ae1e342cfe3Marco Nelissen    } else {
485d457c970c8d08519cd77280a90b61ae1e342cfe3Marco Nelissen        mPreviousPriority = getpriority(PRIO_PROCESS, 0);
486d457c970c8d08519cd77280a90b61ae1e342cfe3Marco Nelissen        get_sched_policy(0, &mPreviousSchedulingGroup);
487462fd2fa9eef642b0574aa7409de0bde3fec8d43Marco Nelissen        androidSetThreadPriority(0, ANDROID_PRIORITY_AUDIO);
488462fd2fa9eef642b0574aa7409de0bde3fec8d43Marco Nelissen    }
489462fd2fa9eef642b0574aa7409de0bde3fec8d43Marco Nelissen
490462fd2fa9eef642b0574aa7409de0bde3fec8d43Marco Nelissen    status_t status = NO_ERROR;
491d457c970c8d08519cd77280a90b61ae1e342cfe3Marco Nelissen    if (!(flags & CBLK_INVALID)) {
492d457c970c8d08519cd77280a90b61ae1e342cfe3Marco Nelissen        status = mAudioTrack->start();
493d457c970c8d08519cd77280a90b61ae1e342cfe3Marco Nelissen        if (status == DEAD_OBJECT) {
494d457c970c8d08519cd77280a90b61ae1e342cfe3Marco Nelissen            flags |= CBLK_INVALID;
495d457c970c8d08519cd77280a90b61ae1e342cfe3Marco Nelissen        }
4962beeb50b1bba9e92f6cacfeca37fe9fa9d36ead1Eric Laurent    }
497ae34ed2bcc9fa49a22fe7497327adb689ef27e8dHaynes Mathew George    if (flags & CBLK_INVALID) {
4984a4a0959bca78e03e3c3f486ba17829c28314d8cGlenn Kasten        status = restoreTrack_l("start");
499be916aa1267e2e6b1c148f51d11bcbbc79cb864cEric Laurent    }
500a997e7a7c5aa2fc7e95316218316f8b7b98786baGlenn Kasten
501896adcd3ae6a1c7010e526327eff54e16179987bEric Laurent    if (status != NO_ERROR) {
502a997e7a7c5aa2fc7e95316218316f8b7b98786baGlenn Kasten        ALOGE("start() status %d", status);
503bfd318402924414fbde4d31c9d23cc423f10b630Glenn Kasten        mState = previousState;
504a997e7a7c5aa2fc7e95316218316f8b7b98786baGlenn Kasten        if (t != 0) {
505a997e7a7c5aa2fc7e95316218316f8b7b98786baGlenn Kasten            if (previousState != STATE_STOPPING) {
50634f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent                t->pause();
5070d6db582f2ccc9f8943c5f3965e2994b7d137158Eric Laurent            }
508a997e7a7c5aa2fc7e95316218316f8b7b98786baGlenn Kasten        } else {
50934f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent            setpriority(PRIO_PROCESS, 0, mPreviousPriority);
510a997e7a7c5aa2fc7e95316218316f8b7b98786baGlenn Kasten            set_sched_policy(0, mPreviousSchedulingGroup);
511b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald        }
512b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald    }
513a997e7a7c5aa2fc7e95316218316f8b7b98786baGlenn Kasten
514a997e7a7c5aa2fc7e95316218316f8b7b98786baGlenn Kasten    return status;
51589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
51689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
51734f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurentvoid AudioTrack::stop()
51889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project{
51989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    AutoMutex lock(mLock);
5204ede21d9c1f957baf5e561849ff9bbe4bcbefc20Andy Hung    if (mState != STATE_ACTIVE && mState != STATE_PAUSED) {
5214ede21d9c1f957baf5e561849ff9bbe4bcbefc20Andy Hung        return;
5224ede21d9c1f957baf5e561849ff9bbe4bcbefc20Andy Hung    }
52353c3b5fc1afe162a8669cb3d27d6bb14e1847e39Andy Hung
52489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    if (isOffloaded_l()) {
5252c22aeb65e801f663a754d043062f85e49f77739Jean-Michel Trivi        mState = STATE_STOPPING;
52689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    } else {
52789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        mState = STATE_STOPPED;
528200092b7f21d2b98f30b800e79d152636f9ba225Glenn Kasten        mReleased = 0;
529200092b7f21d2b98f30b800e79d152636f9ba225Glenn Kasten    }
5307f1bc8af1c46695191bf7e2aba6467f3616629c0Andy Hung
531d457c970c8d08519cd77280a90b61ae1e342cfe3Marco Nelissen    mProxy->interrupt();
5329f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    mAudioTrack->stop();
5339f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    // the playback head position will reset to 0, so if a marker is set, we need
5349f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    // to activate it again
5351b42097f38e72574ed853a35f4e8a66e4739c421Phil Burk    mMarkerReached = false;
536c8e09c610fabc7390297ecb48e939acbdfe27325Andy Hung#if 0
537c8e09c610fabc7390297ecb48e939acbdfe27325Andy Hung    // Force flush if a shared buffer is used otherwise audioflinger
5382812d9ea3a3a33142dd8e23c9d949c498d6f7a12Phil Burk    // will not stop before end of buffer is reached.
539ea2b9c07b34079f0dbd8610a511e006e69a15adcAndy Hung    // It may be needed to make sure that we stop playback, likely in case looping is on.
540ea2b9c07b34079f0dbd8610a511e006e69a15adcAndy Hung    if (mSharedBuffer != 0) {
5419f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        flush_l();
54289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
54389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project#endif
54489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
54589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    sp<AudioTrackThread> t = mAudioTrackThread;
54689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    if (t != 0) {
547b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald        if (!isOffloaded_l()) {
54889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project            t->pause();
549f5aafb209d01ba2ab6cb55d1a12cfc653e2b4be0Eric Laurent        }
550b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald    } else {
5519f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        setpriority(PRIO_PROCESS, 0, mPreviousPriority);
552b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald        set_sched_policy(0, mPreviousSchedulingGroup);
5539f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
5541703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent}
5559f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
5562b584244930c9de0e3bc46898a801e9ccb731900Eric Laurentbool AudioTrack::stopped() const
5579f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten{
558b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald    AutoMutex lock(mLock);
559b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald    return mState != STATE_ACTIVE;
560b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald}
561b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald
562b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgeraldvoid AudioTrack::flush()
563200092b7f21d2b98f30b800e79d152636f9ba225Glenn Kasten{
5649f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (mSharedBuffer != 0) {
5659f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        return;
566200092b7f21d2b98f30b800e79d152636f9ba225Glenn Kasten    }
5671b42097f38e72574ed853a35f4e8a66e4739c421Phil Burk    AutoMutex lock(mLock);
568c8e09c610fabc7390297ecb48e939acbdfe27325Andy Hung    if (mState == STATE_ACTIVE || mState == STATE_FLUSHED) {
569c8e09c610fabc7390297ecb48e939acbdfe27325Andy Hung        return;
5701b42097f38e72574ed853a35f4e8a66e4739c421Phil Burk    }
571e1e9846a786a0d77a13b44f8e798e03b4cba9d77Andy Hung    flush_l();
572e1e9846a786a0d77a13b44f8e798e03b4cba9d77Andy Hung}
573e1e9846a786a0d77a13b44f8e798e03b4cba9d77Andy Hung
574e1e9846a786a0d77a13b44f8e798e03b4cba9d77Andy Hungvoid AudioTrack::flush_l()
575e1e9846a786a0d77a13b44f8e798e03b4cba9d77Andy Hung{
576e1e9846a786a0d77a13b44f8e798e03b4cba9d77Andy Hung    ALOG_ASSERT(mState != STATE_ACTIVE);
577e1e9846a786a0d77a13b44f8e798e03b4cba9d77Andy Hung
578e1e9846a786a0d77a13b44f8e798e03b4cba9d77Andy Hung    // clear playback marker and periodic update counter
579e1e9846a786a0d77a13b44f8e798e03b4cba9d77Andy Hung    mMarkerPosition = 0;
580e1e9846a786a0d77a13b44f8e798e03b4cba9d77Andy Hung    mMarkerReached = false;
581e1e9846a786a0d77a13b44f8e798e03b4cba9d77Andy Hung    mUpdatePeriod = 0;
582e1e9846a786a0d77a13b44f8e798e03b4cba9d77Andy Hung    mRefreshRemaining = true;
583e1e9846a786a0d77a13b44f8e798e03b4cba9d77Andy Hung
58461be84167c1a11c8a030e00a2b79b2bc4fdf617fAndy Hung    mState = STATE_FLUSHED;
585e1e9846a786a0d77a13b44f8e798e03b4cba9d77Andy Hung    mReleased = 0;
586e1e9846a786a0d77a13b44f8e798e03b4cba9d77Andy Hung    if (isOffloaded_l()) {
587e1e9846a786a0d77a13b44f8e798e03b4cba9d77Andy Hung        mProxy->interrupt();
58861be84167c1a11c8a030e00a2b79b2bc4fdf617fAndy Hung    }
5897f1bc8af1c46695191bf7e2aba6467f3616629c0Andy Hung    mProxy->flush();
5907f1bc8af1c46695191bf7e2aba6467f3616629c0Andy Hung    mAudioTrack->flush();
5917f1bc8af1c46695191bf7e2aba6467f3616629c0Andy Hung}
5927f1bc8af1c46695191bf7e2aba6467f3616629c0Andy Hung
5937f1bc8af1c46695191bf7e2aba6467f3616629c0Andy Hungvoid AudioTrack::pause()
5947f1bc8af1c46695191bf7e2aba6467f3616629c0Andy Hung{
595ec9a032c2e104ab1e3b5bf73e69dab1408ced0adEric Laurent    AutoMutex lock(mLock);
596ec9a032c2e104ab1e3b5bf73e69dab1408ced0adEric Laurent    if (mState == STATE_ACTIVE) {
597ec9a032c2e104ab1e3b5bf73e69dab1408ced0adEric Laurent        mState = STATE_PAUSED;
59889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    } else if (mState == STATE_STOPPING) {
599200092b7f21d2b98f30b800e79d152636f9ba225Glenn Kasten        mState = STATE_PAUSED_STOPPING;
60096f60d8f04432a1ed503b3e24d5736d28c63c9a2Glenn Kasten    } else {
60189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        return;
6029f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
6039f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    mProxy->interrupt();
6049f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    mAudioTrack->pause();
6059f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
6069f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (isOffloaded_l()) {
60789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        if (mOutput != AUDIO_IO_HANDLE_NONE) {
6089f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            // An offload output can be re-used between two audio tracks having
6099f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            // the same configuration. A timestamp query for a paused track
6109f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            // while the other is running would return an incorrect time.
6119f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            // To fix this, cache the playback position on a pause() and return
6129f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            // this time when requested until the track is resumed.
61379629f0716f04e79064256362be56730077b8c50Andy Hung
61479629f0716f04e79064256362be56730077b8c50Andy Hung            // OffloadThread sends HAL pause in its threadLoop. Time saved
61579629f0716f04e79064256362be56730077b8c50Andy Hung            // here can be slightly off.
61679629f0716f04e79064256362be56730077b8c50Andy Hung
61779629f0716f04e79064256362be56730077b8c50Andy Hung            // TODO: check return code for getRenderPosition.
61879629f0716f04e79064256362be56730077b8c50Andy Hung
61979629f0716f04e79064256362be56730077b8c50Andy Hung            uint32_t halFrames;
62079629f0716f04e79064256362be56730077b8c50Andy Hung            AudioSystem::getRenderPosition(mOutput, &halFrames, &mPausedPosition);
62179629f0716f04e79064256362be56730077b8c50Andy Hung            ALOGV("AudioTrack::pause for offload, cache current position %u", mPausedPosition);
62279629f0716f04e79064256362be56730077b8c50Andy Hung        }
62379629f0716f04e79064256362be56730077b8c50Andy Hung    }
62479629f0716f04e79064256362be56730077b8c50Andy Hung}
62579629f0716f04e79064256362be56730077b8c50Andy Hung
62679629f0716f04e79064256362be56730077b8c50Andy Hungstatus_t AudioTrack::setVolume(float left, float right)
62779629f0716f04e79064256362be56730077b8c50Andy Hung{
6289f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    // This duplicates a test by AudioTrack JNI, but that is not the only caller
6299f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (isnanf(left) || left < GAIN_FLOAT_ZERO || left > GAIN_FLOAT_UNITY ||
63089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project            isnanf(right) || right < GAIN_FLOAT_ZERO || right > GAIN_FLOAT_UNITY) {
631b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald        return BAD_VALUE;
632b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald    }
633b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald
63489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    AutoMutex lock(mLock);
635879135196fd1c97deefc538c888037c56c2879a7Glenn Kasten    mVolume[AUDIO_INTERLEAVE_LEFT] = left;
636a636433cbd09c0708b85f337ef45c0cdef3bcb4dGlenn Kasten    mVolume[AUDIO_INTERLEAVE_RIGHT] = right;
63789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
63889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    mProxy->setVolumeLR(gain_minifloat_pack(gain_from_float(left), gain_from_float(right)));
63989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
640b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald    if (isOffloaded_l()) {
6419f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        mAudioTrack->signal();
6429f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
6439f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    return NO_ERROR;
6449f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten}
6459f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
646397edb3377e5775f4df60afb8bf6d4711e5adc0eGlenn Kastenstatus_t AudioTrack::setVolume(float volume)
6479f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten{
6489f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    return setVolume(volume, volume);
6499f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten}
65023a7545c4de71e989c2d8ebf1d5b9dcf463c36a9Glenn Kasten
651b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgeraldstatus_t AudioTrack::setAuxEffectSendLevel(float level)
652b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald{
653b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald    // This duplicates a test by AudioTrack JNI, but that is not the only caller
654c2813e568aa476e03d159529c0af28c99536db8dAndy Hung    if (isnanf(level) || level < GAIN_FLOAT_ZERO || level > GAIN_FLOAT_UNITY) {
655b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald        return BAD_VALUE;
656b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald    }
6579f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
6589f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    AutoMutex lock(mLock);
65961be84167c1a11c8a030e00a2b79b2bc4fdf617fAndy Hung    mSendLevel = level;
66061be84167c1a11c8a030e00a2b79b2bc4fdf617fAndy Hung    mProxy->setSendLevel(level);
66161be84167c1a11c8a030e00a2b79b2bc4fdf617fAndy Hung
6629b4615887c23548438fd0d8e3d8f04ac21912850Andy Hung    return NO_ERROR;
6639f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten}
6649b4615887c23548438fd0d8e3d8f04ac21912850Andy Hung
6659b4615887c23548438fd0d8e3d8f04ac21912850Andy Hungvoid AudioTrack::getAuxEffectSendLevel(float* level) const
6669b4615887c23548438fd0d8e3d8f04ac21912850Andy Hung{
6679f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (level != NULL) {
668b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald        *level = mSendLevel;
6699f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
6709f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten}
67123a7545c4de71e989c2d8ebf1d5b9dcf463c36a9Glenn Kasten
672b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgeraldstatus_t AudioTrack::setSampleRate(uint32_t rate)
673b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald{
6749f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (mIsTimed || isOffloadedOrDirect()) {
6759f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        return INVALID_OPERATION;
6769f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
6779f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
67889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    AutoMutex lock(mLock);
67989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    if (mOutput == AUDIO_IO_HANDLE_NONE) {
68089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        return NO_INIT;
68189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
6829a2aaf927e56a4b4acab23ef16b3f133a9f48a63Glenn Kasten    uint32_t afSamplingRate;
6839f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (AudioSystem::getSamplingRate(mOutput, &afSamplingRate) != NO_ERROR) {
68489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        return NO_INIT;
68589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
68689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    if (rate == 0 || rate > afSamplingRate * AUDIO_RESAMPLER_DOWN_RATIO_MAX) {
68789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        return BAD_VALUE;
6889f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
6899f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
6909f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    mSampleRate = rate;
6911703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent    mProxy->setSampleRate(rate);
6929f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
6939f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    return NO_ERROR;
6944bae3649d504d590a546717a8e49f96a30d9a745Glenn Kasten}
6959f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
6961703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurentuint32_t AudioTrack::getSampleRate() const
6971703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent{
6981703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent    if (mIsTimed) {
6991703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent        return 0;
7009f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
701c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent
7022c22aeb65e801f663a754d043062f85e49f77739Jean-Michel Trivi    AutoMutex lock(mLock);
7032c22aeb65e801f663a754d043062f85e49f77739Jean-Michel Trivi
7042c22aeb65e801f663a754d043062f85e49f77739Jean-Michel Trivi    // sample rate can be updated during playback by the offloaded decoder so we need to
7052c22aeb65e801f663a754d043062f85e49f77739Jean-Michel Trivi    // query the HAL and update if needed.
706b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald// FIXME use Proxy return channel to update the rate from server and avoid polling here
707c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent    if (isOffloadedOrDirect_l()) {
7089f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        if (mOutput != AUDIO_IO_HANDLE_NONE) {
709c2813e568aa476e03d159529c0af28c99536db8dAndy Hung            uint32_t sampleRate = 0;
71023a7545c4de71e989c2d8ebf1d5b9dcf463c36a9Glenn Kasten            status_t status = AudioSystem::getSamplingRate(mOutput, &sampleRate);
711b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald            if (status == NO_ERROR) {
712b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald                mSampleRate = sampleRate;
7139f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            }
7144bae3649d504d590a546717a8e49f96a30d9a745Glenn Kasten        }
71589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
71689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    return mSampleRate;
71789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
71889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
719f5aafb209d01ba2ab6cb55d1a12cfc653e2b4be0Eric Laurentstatus_t AudioTrack::setLoop(uint32_t loopStart, uint32_t loopEnd, int loopCount)
720b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald{
721b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald    if (mSharedBuffer == 0 || mIsTimed || isOffloadedOrDirect()) {
722b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald        return INVALID_OPERATION;
723b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald    }
724b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald
7259f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (loopCount == 0) {
72689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        ;
7279f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    } else if (loopCount >= -1 && loopStart < loopEnd && loopEnd <= mFrameCount &&
7289f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            loopEnd - loopStart >= MIN_LOOP) {
7297064fd2dcdfeafea53cd5a992bb78c413542f29fHaynes Mathew George        ;
7303a90f2849d49bf65f2d6257fd6da30ae46d745faMarco Nelissen    } else {
731142f519aa1acd5804d111e60d100f170fed28405Glenn Kasten        return BAD_VALUE;
7327f1bc8af1c46695191bf7e2aba6467f3616629c0Andy Hung    }
7337f1bc8af1c46695191bf7e2aba6467f3616629c0Andy Hung
7347f1bc8af1c46695191bf7e2aba6467f3616629c0Andy Hung    AutoMutex lock(mLock);
7357f1bc8af1c46695191bf7e2aba6467f3616629c0Andy Hung    // See setPosition() regarding setting parameters such as loop points or position while active
7367f1bc8af1c46695191bf7e2aba6467f3616629c0Andy Hung    if (mState == STATE_ACTIVE) {
7377f1bc8af1c46695191bf7e2aba6467f3616629c0Andy Hung        return INVALID_OPERATION;
7387f1bc8af1c46695191bf7e2aba6467f3616629c0Andy Hung    }
7397f1bc8af1c46695191bf7e2aba6467f3616629c0Andy Hung    setLoop_l(loopStart, loopEnd, loopCount);
7407f1bc8af1c46695191bf7e2aba6467f3616629c0Andy Hung    return NO_ERROR;
7417f1bc8af1c46695191bf7e2aba6467f3616629c0Andy Hung}
7427f1bc8af1c46695191bf7e2aba6467f3616629c0Andy Hung
7437064fd2dcdfeafea53cd5a992bb78c413542f29fHaynes Mathew Georgevoid AudioTrack::setLoop_l(uint32_t loopStart, uint32_t loopEnd, int loopCount)
7447064fd2dcdfeafea53cd5a992bb78c413542f29fHaynes Mathew George{
7457064fd2dcdfeafea53cd5a992bb78c413542f29fHaynes Mathew George    // FIXME If setting a loop also sets position to start of loop, then
7467064fd2dcdfeafea53cd5a992bb78c413542f29fHaynes Mathew George    //       this is correct.  Otherwise it should be removed.
7477064fd2dcdfeafea53cd5a992bb78c413542f29fHaynes Mathew George    mNewPosition = updateAndGetPosition_l() + mUpdatePeriod;
74889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    mLoopPeriod = loopCount != 0 ? loopEnd - loopStart : 0;
74989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    mStaticProxy->setLoop(loopStart, loopEnd, loopCount);
750be916aa1267e2e6b1c148f51d11bcbbc79cb864cEric Laurent}
75189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
752c56f3426099a3cf2d07ccff8886050c7fbce140fGlenn Kastenstatus_t AudioTrack::setMarkerPosition(uint32_t marker)
753c56f3426099a3cf2d07ccff8886050c7fbce140fGlenn Kasten{
754c56f3426099a3cf2d07ccff8886050c7fbce140fGlenn Kasten    // The only purpose of setting marker position is to get a callback
755be916aa1267e2e6b1c148f51d11bcbbc79cb864cEric Laurent    if (mCbf == NULL || isOffloadedOrDirect()) {
756be916aa1267e2e6b1c148f51d11bcbbc79cb864cEric Laurent        return INVALID_OPERATION;
757be916aa1267e2e6b1c148f51d11bcbbc79cb864cEric Laurent    }
7581703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent
75966e4635cb09fadcaccf912f37c387396c428378aGlenn Kasten    AutoMutex lock(mLock);
76066e4635cb09fadcaccf912f37c387396c428378aGlenn Kasten    mMarkerPosition = marker;
76189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    mMarkerReached = false;
762c56f3426099a3cf2d07ccff8886050c7fbce140fGlenn Kasten
763be916aa1267e2e6b1c148f51d11bcbbc79cb864cEric Laurent    return NO_ERROR;
76423a7545c4de71e989c2d8ebf1d5b9dcf463c36a9Glenn Kasten}
76559fe010bcc072597852454a2ec53d7b0a2002a3bEric Laurent
76659fe010bcc072597852454a2ec53d7b0a2002a3bEric Laurentstatus_t AudioTrack::getMarkerPosition(uint32_t *marker) const
767be916aa1267e2e6b1c148f51d11bcbbc79cb864cEric Laurent{
76889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    if (isOffloadedOrDirect()) {
76989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        return INVALID_OPERATION;
770b1c0993b215c5c3eebd1c6bafc22bba23d57a70bGlenn Kasten    }
77189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    if (marker == NULL) {
772b1c0993b215c5c3eebd1c6bafc22bba23d57a70bGlenn Kasten        return BAD_VALUE;
773be916aa1267e2e6b1c148f51d11bcbbc79cb864cEric Laurent    }
774be916aa1267e2e6b1c148f51d11bcbbc79cb864cEric Laurent
7752beeb50b1bba9e92f6cacfeca37fe9fa9d36ead1Eric Laurent    AutoMutex lock(mLock);
776be916aa1267e2e6b1c148f51d11bcbbc79cb864cEric Laurent    *marker = mMarkerPosition;
777c56f3426099a3cf2d07ccff8886050c7fbce140fGlenn Kasten
778c56f3426099a3cf2d07ccff8886050c7fbce140fGlenn Kasten    return NO_ERROR;
779be916aa1267e2e6b1c148f51d11bcbbc79cb864cEric Laurent}
780be916aa1267e2e6b1c148f51d11bcbbc79cb864cEric Laurent
781be916aa1267e2e6b1c148f51d11bcbbc79cb864cEric Laurentstatus_t AudioTrack::setPositionUpdatePeriod(uint32_t updatePeriod)
7829f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten{
783be916aa1267e2e6b1c148f51d11bcbbc79cb864cEric Laurent    // The only purpose of setting position update period is to get a callback
784e3aa659e9cee7df5c12a80d285cc29ab3b2cbb39Glenn Kasten    if (mCbf == NULL || isOffloadedOrDirect()) {
785be916aa1267e2e6b1c148f51d11bcbbc79cb864cEric Laurent        return INVALID_OPERATION;
786be916aa1267e2e6b1c148f51d11bcbbc79cb864cEric Laurent    }
787be916aa1267e2e6b1c148f51d11bcbbc79cb864cEric Laurent
788be916aa1267e2e6b1c148f51d11bcbbc79cb864cEric Laurent    AutoMutex lock(mLock);
789a5224f319e2ba4b51ddb4287705ccf8d4b8ecc51Glenn Kasten    mNewPosition = updateAndGetPosition_l() + updatePeriod;
790be916aa1267e2e6b1c148f51d11bcbbc79cb864cEric Laurent    mUpdatePeriod = updatePeriod;
791be916aa1267e2e6b1c148f51d11bcbbc79cb864cEric Laurent
7929f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    return NO_ERROR;
793be916aa1267e2e6b1c148f51d11bcbbc79cb864cEric Laurent}
79489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
79589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectstatus_t AudioTrack::getPositionUpdatePeriod(uint32_t *updatePeriod) const
7963b16c766d1ae2cfd8487e8ffb2b23936fc0a8e17Glenn Kasten{
79789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    if (isOffloadedOrDirect()) {
7985cbb5785a58655e21f5f7805274b8c78b986216bAndy Hung        return INVALID_OPERATION;
7995cbb5785a58655e21f5f7805274b8c78b986216bAndy Hung    }
8005cbb5785a58655e21f5f7805274b8c78b986216bAndy Hung    if (updatePeriod == NULL) {
8015cbb5785a58655e21f5f7805274b8c78b986216bAndy Hung        return BAD_VALUE;
802d79072e9dff59f767cce2cda1caab80ce5a0815bGlenn Kasten    }
8034ff14bae91075eb274eb1c2975982358946e7e63John Grossman
8044ff14bae91075eb274eb1c2975982358946e7e63John Grossman    AutoMutex lock(mLock);
8050d6db582f2ccc9f8943c5f3965e2994b7d137158Eric Laurent    *updatePeriod = mUpdatePeriod;
8060d6db582f2ccc9f8943c5f3965e2994b7d137158Eric Laurent
8070d6db582f2ccc9f8943c5f3965e2994b7d137158Eric Laurent    return NO_ERROR;
8085cbb5785a58655e21f5f7805274b8c78b986216bAndy Hung}
8095cbb5785a58655e21f5f7805274b8c78b986216bAndy Hung
8109f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kastenstatus_t AudioTrack::setPosition(uint32_t position)
8110d6db582f2ccc9f8943c5f3965e2994b7d137158Eric Laurent{
812573266210fb2b2e7d86fbd46d0dfe16763611d91Eric Laurent    if (mSharedBuffer == 0 || mIsTimed || isOffloadedOrDirect()) {
81389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        return INVALID_OPERATION;
81426145643ce22d797b3b1675c82c47a2d8c79ecaaAndy Hung    }
8155a8a95de6dad1a3bcf3da5a37b35766e89086e13Ricardo Garcia    if (position > mFrameCount) {
81626145643ce22d797b3b1675c82c47a2d8c79ecaaAndy Hung        return BAD_VALUE;
817d65d73c4ae74d084751b417615a78cbe7a51372aGlenn Kasten    }
818d65d73c4ae74d084751b417615a78cbe7a51372aGlenn Kasten
8198edb8dc44b8a2f81bdb5db645b6b708548771a31Andy Hung    AutoMutex lock(mLock);
82089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    // Currently we require that the player is inactive before setting parameters such as position
821e3aa659e9cee7df5c12a80d285cc29ab3b2cbb39Glenn Kasten    // or loop points.  Otherwise, there could be a race condition: the application could read the
82226145643ce22d797b3b1675c82c47a2d8c79ecaaAndy Hung    // current position, compute a new position or loop parameters, and then set that position or
823e3aa659e9cee7df5c12a80d285cc29ab3b2cbb39Glenn Kasten    // loop parameters but it would do the "wrong" thing since the position has continued to advance
824573266210fb2b2e7d86fbd46d0dfe16763611d91Eric Laurent    // in the mean time.  If we ever provide a sequencer in server, we could allow a way for the app
82589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    // to specify how it wants to handle such scenarios.
82689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    if (mState == STATE_ACTIVE) {
827a5224f319e2ba4b51ddb4287705ccf8d4b8ecc51Glenn Kasten        return INVALID_OPERATION;
82889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
8291703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent    mNewPosition = updateAndGetPosition_l() + mUpdatePeriod;
8306f59db12a64f4496866952a251122ccb77a36c6bEric Laurent    mLoopPeriod = 0;
8316f59db12a64f4496866952a251122ccb77a36c6bEric Laurent    // FIXME Check whether loops and setting position are incompatible in old code.
8326f59db12a64f4496866952a251122ccb77a36c6bEric Laurent    // If we use setLoop for both purposes we lose the capability to set the position while looping.
8336f59db12a64f4496866952a251122ccb77a36c6bEric Laurent    mStaticProxy->setLoop(position, mFrameCount, 0);
834ab5cdbaf65ca509681d2726aacdf3ac8bfb6b3faEric Laurent
835142f519aa1acd5804d111e60d100f170fed28405Glenn Kasten    return NO_ERROR;
8366f59db12a64f4496866952a251122ccb77a36c6bEric Laurent}
837b7f24b101d43139b4c747129bfbc4ecf5c468b86Jean-Michel Trivi
8386f59db12a64f4496866952a251122ccb77a36c6bEric Laurentstatus_t AudioTrack::getPosition(uint32_t *position)
8396f59db12a64f4496866952a251122ccb77a36c6bEric Laurent{
8406f59db12a64f4496866952a251122ccb77a36c6bEric Laurent    if (position == NULL) {
8416f59db12a64f4496866952a251122ccb77a36c6bEric Laurent        return BAD_VALUE;
8426f59db12a64f4496866952a251122ccb77a36c6bEric Laurent    }
843e3aa659e9cee7df5c12a80d285cc29ab3b2cbb39Glenn Kasten
84489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    AutoMutex lock(mLock);
84589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    if (isOffloadedOrDirect_l()) {
8463a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        uint32_t dspFrames = 0;
8473a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar
8483a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar        if (isOffloaded_l() && ((mState == STATE_PAUSED) || (mState == STATE_PAUSED_STOPPING))) {
8493a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            ALOGV("getPosition called in paused state, return cached position %u", mPausedPosition);
8503a474aa67fc31505740526dd249d96204c08bf79Lajos Molnar            *position = mPausedPosition;
8515a8a95de6dad1a3bcf3da5a37b35766e89086e13Ricardo Garcia            return NO_ERROR;
8528edb8dc44b8a2f81bdb5db645b6b708548771a31Andy Hung        }
8538edb8dc44b8a2f81bdb5db645b6b708548771a31Andy Hung
8545a8a95de6dad1a3bcf3da5a37b35766e89086e13Ricardo Garcia        if (mOutput != AUDIO_IO_HANDLE_NONE) {
8558edb8dc44b8a2f81bdb5db645b6b708548771a31Andy Hung            uint32_t halFrames;
8568edb8dc44b8a2f81bdb5db645b6b708548771a31Andy Hung            AudioSystem::getRenderPosition(mOutput, &halFrames, &dspFrames);
857d79072e9dff59f767cce2cda1caab80ce5a0815bGlenn Kasten        }
8588edb8dc44b8a2f81bdb5db645b6b708548771a31Andy Hung        // FIXME: dspFrames may not be zero in (mState == STATE_STOPPED || mState == STATE_FLUSHED)
8598edb8dc44b8a2f81bdb5db645b6b708548771a31Andy Hung        // due to hardware latency. We leave this behavior for now.
8608edb8dc44b8a2f81bdb5db645b6b708548771a31Andy Hung        *position = dspFrames;
8618edb8dc44b8a2f81bdb5db645b6b708548771a31Andy Hung    } else {
8628edb8dc44b8a2f81bdb5db645b6b708548771a31Andy Hung        // IAudioTrack::stop() isn't synchronous; we don't know when presentation completes
863ff874dc957f9ea70d87f4d627bf903e1fc86d58bAndy Hung        *position = (mState == STATE_STOPPED || mState == STATE_FLUSHED) ?
864ff874dc957f9ea70d87f4d627bf903e1fc86d58bAndy Hung                0 : updateAndGetPosition_l();
865ff874dc957f9ea70d87f4d627bf903e1fc86d58bAndy Hung    }
86626145643ce22d797b3b1675c82c47a2d8c79ecaaAndy Hung    return NO_ERROR;
8675a8a95de6dad1a3bcf3da5a37b35766e89086e13Ricardo Garcia}
8685a8a95de6dad1a3bcf3da5a37b35766e89086e13Ricardo Garcia
8695a8a95de6dad1a3bcf3da5a37b35766e89086e13Ricardo Garciastatus_t AudioTrack::getBufferPosition(uint32_t *position)
8706c7f062d3149d6890daaee64828959ad6f61ea54Ricardo Garcia{
8716c7f062d3149d6890daaee64828959ad6f61ea54Ricardo Garcia    if (mSharedBuffer == 0 || mIsTimed) {
8726c7f062d3149d6890daaee64828959ad6f61ea54Ricardo Garcia        return INVALID_OPERATION;
8736c7f062d3149d6890daaee64828959ad6f61ea54Ricardo Garcia    }
874ff874dc957f9ea70d87f4d627bf903e1fc86d58bAndy Hung    if (position == NULL) {
875ff874dc957f9ea70d87f4d627bf903e1fc86d58bAndy Hung        return BAD_VALUE;
876ff874dc957f9ea70d87f4d627bf903e1fc86d58bAndy Hung    }
8776c7f062d3149d6890daaee64828959ad6f61ea54Ricardo Garcia
878ff874dc957f9ea70d87f4d627bf903e1fc86d58bAndy Hung    AutoMutex lock(mLock);
879ff874dc957f9ea70d87f4d627bf903e1fc86d58bAndy Hung    *position = mStaticProxy->getBufferPosition();
88026145643ce22d797b3b1675c82c47a2d8c79ecaaAndy Hung    return NO_ERROR;
88126145643ce22d797b3b1675c82c47a2d8c79ecaaAndy Hung}
8828edb8dc44b8a2f81bdb5db645b6b708548771a31Andy Hung
88326145643ce22d797b3b1675c82c47a2d8c79ecaaAndy Hungstatus_t AudioTrack::reload()
884ff874dc957f9ea70d87f4d627bf903e1fc86d58bAndy Hung{
885ff874dc957f9ea70d87f4d627bf903e1fc86d58bAndy Hung    if (mSharedBuffer == 0 || mIsTimed || isOffloadedOrDirect()) {
8868edb8dc44b8a2f81bdb5db645b6b708548771a31Andy Hung        return INVALID_OPERATION;
8878edb8dc44b8a2f81bdb5db645b6b708548771a31Andy Hung    }
8885a8a95de6dad1a3bcf3da5a37b35766e89086e13Ricardo Garcia
8896c7f062d3149d6890daaee64828959ad6f61ea54Ricardo Garcia    AutoMutex lock(mLock);
890e34eae2de7bd6dcba5dea132dabb09f63ac46adcDan Austin    // See setPosition() regarding setting parameters such as loop points or position while active
8916c7f062d3149d6890daaee64828959ad6f61ea54Ricardo Garcia    if (mState == STATE_ACTIVE) {
8926c7f062d3149d6890daaee64828959ad6f61ea54Ricardo Garcia        return INVALID_OPERATION;
8936c7f062d3149d6890daaee64828959ad6f61ea54Ricardo Garcia    }
8946c7f062d3149d6890daaee64828959ad6f61ea54Ricardo Garcia    mNewPosition = mUpdatePeriod;
8956c7f062d3149d6890daaee64828959ad6f61ea54Ricardo Garcia    mLoopPeriod = 0;
896e34eae2de7bd6dcba5dea132dabb09f63ac46adcDan Austin    // FIXME The new code cannot reload while keeping a loop specified.
8976c7f062d3149d6890daaee64828959ad6f61ea54Ricardo Garcia    // Need to check how the old code handled this, and whether it's a significant change.
8986c7f062d3149d6890daaee64828959ad6f61ea54Ricardo Garcia    mStaticProxy->setLoop(0, mFrameCount, 0);
8996c7f062d3149d6890daaee64828959ad6f61ea54Ricardo Garcia    return NO_ERROR;
9006c7f062d3149d6890daaee64828959ad6f61ea54Ricardo Garcia}
9016c7f062d3149d6890daaee64828959ad6f61ea54Ricardo Garcia
9026c7f062d3149d6890daaee64828959ad6f61ea54Ricardo Garciaaudio_io_handle_t AudioTrack::getOutput() const
9035a8a95de6dad1a3bcf3da5a37b35766e89086e13Ricardo Garcia{
90426145643ce22d797b3b1675c82c47a2d8c79ecaaAndy Hung    AutoMutex lock(mLock);
9058edb8dc44b8a2f81bdb5db645b6b708548771a31Andy Hung    return mOutput;
9068edb8dc44b8a2f81bdb5db645b6b708548771a31Andy Hung}
9078edb8dc44b8a2f81bdb5db645b6b708548771a31Andy Hung
9085a8a95de6dad1a3bcf3da5a37b35766e89086e13Ricardo Garciastatus_t AudioTrack::attachAuxEffect(int effectId)
9098edb8dc44b8a2f81bdb5db645b6b708548771a31Andy Hung{
9108edb8dc44b8a2f81bdb5db645b6b708548771a31Andy Hung    AutoMutex lock(mLock);
9115a8a95de6dad1a3bcf3da5a37b35766e89086e13Ricardo Garcia    status_t status = mAudioTrack->attachAuxEffect(effectId);
9128edb8dc44b8a2f81bdb5db645b6b708548771a31Andy Hung    if (status == NO_ERROR) {
9138edb8dc44b8a2f81bdb5db645b6b708548771a31Andy Hung        mAuxEffectId = effectId;
914c0adecb800b197cb8c028513130ebabf2d0f37baPhil Burk    }
915c0adecb800b197cb8c028513130ebabf2d0f37baPhil Burk    return status;
916c0adecb800b197cb8c028513130ebabf2d0f37baPhil Burk}
917c0adecb800b197cb8c028513130ebabf2d0f37baPhil Burk
918c0adecb800b197cb8c028513130ebabf2d0f37baPhil Burk// -------------------------------------------------------------------------
919c0adecb800b197cb8c028513130ebabf2d0f37baPhil Burk
920e8972b0a27fac327c997fceb20d9abae1dc1d899Phil Burk// must be called with mLock held
921c0adecb800b197cb8c028513130ebabf2d0f37baPhil Burkstatus_t AudioTrack::createTrack_l()
922c0adecb800b197cb8c028513130ebabf2d0f37baPhil Burk{
923f2c87b3f88d987d2af6322e9763eb8224a2bae48Andy Hung    status_t status;
924f2c87b3f88d987d2af6322e9763eb8224a2bae48Andy Hung    const sp<IAudioFlinger>& audioFlinger = AudioSystem::get_audio_flinger();
925f2c87b3f88d987d2af6322e9763eb8224a2bae48Andy Hung    if (audioFlinger == 0) {
926f2c87b3f88d987d2af6322e9763eb8224a2bae48Andy Hung        ALOGE("Could not get audioflinger");
927f2c87b3f88d987d2af6322e9763eb8224a2bae48Andy Hung        return NO_INIT;
928f2c87b3f88d987d2af6322e9763eb8224a2bae48Andy Hung    }
929f2c87b3f88d987d2af6322e9763eb8224a2bae48Andy Hung
930f2c87b3f88d987d2af6322e9763eb8224a2bae48Andy Hung    audio_io_handle_t output = AudioSystem::getOutputForAttr(&mAttributes, mSampleRate, mFormat,
931f2c87b3f88d987d2af6322e9763eb8224a2bae48Andy Hung            mChannelMask, mFlags, mOffloadInfo);
932f2c87b3f88d987d2af6322e9763eb8224a2bae48Andy Hung    if (output == AUDIO_IO_HANDLE_NONE) {
933f2c87b3f88d987d2af6322e9763eb8224a2bae48Andy Hung        ALOGE("Could not get audio output for stream type %d, usage %d, sample rate %u, format %#x,"
934f2c87b3f88d987d2af6322e9763eb8224a2bae48Andy Hung              " channel mask %#x, flags %#x",
935f2c87b3f88d987d2af6322e9763eb8224a2bae48Andy Hung              mStreamType, mAttributes.usage, mSampleRate, mFormat, mChannelMask, mFlags);
936f2c87b3f88d987d2af6322e9763eb8224a2bae48Andy Hung        return BAD_VALUE;
937f2c87b3f88d987d2af6322e9763eb8224a2bae48Andy Hung    }
938f2c87b3f88d987d2af6322e9763eb8224a2bae48Andy Hung    {
939f2c87b3f88d987d2af6322e9763eb8224a2bae48Andy Hung    // Now that we have a reference to an I/O handle and have not yet handed it off to AudioFlinger,
940f2c87b3f88d987d2af6322e9763eb8224a2bae48Andy Hung    // we must release it ourselves if anything goes wrong.
941c0adecb800b197cb8c028513130ebabf2d0f37baPhil Burk
942c0adecb800b197cb8c028513130ebabf2d0f37baPhil Burk    // Not all of these values are needed under all conditions, but it is easier to get them all
943c0adecb800b197cb8c028513130ebabf2d0f37baPhil Burk
944c0adecb800b197cb8c028513130ebabf2d0f37baPhil Burk    uint32_t afLatency;
945c0adecb800b197cb8c028513130ebabf2d0f37baPhil Burk    status = AudioSystem::getLatency(output, &afLatency);
946c0adecb800b197cb8c028513130ebabf2d0f37baPhil Burk    if (status != NO_ERROR) {
947c0adecb800b197cb8c028513130ebabf2d0f37baPhil Burk        ALOGE("getLatency(%d) failed status %d", output, status);
948d79072e9dff59f767cce2cda1caab80ce5a0815bGlenn Kasten        goto release;
949c0adecb800b197cb8c028513130ebabf2d0f37baPhil Burk    }
950c0adecb800b197cb8c028513130ebabf2d0f37baPhil Burk
951e8972b0a27fac327c997fceb20d9abae1dc1d899Phil Burk    size_t afFrameCount;
952c0adecb800b197cb8c028513130ebabf2d0f37baPhil Burk    status = AudioSystem::getFrameCount(output, &afFrameCount);
953c0adecb800b197cb8c028513130ebabf2d0f37baPhil Burk    if (status != NO_ERROR) {
95489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        ALOGE("getFrameCount(output=%d) status %d", output, status);
95589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        goto release;
956d79072e9dff59f767cce2cda1caab80ce5a0815bGlenn Kasten    }
957083d1c1492d496960d5b28f4664ff02101736677Glenn Kasten
958083d1c1492d496960d5b28f4664ff02101736677Glenn Kasten    uint32_t afSampleRate;
959083d1c1492d496960d5b28f4664ff02101736677Glenn Kasten    status = AudioSystem::getSamplingRate(output, &afSampleRate);
96089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    if (status != NO_ERROR) {
9619f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        ALOGE("getSamplingRate(output=%d) status %d", output, status);
9629f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        goto release;
9639f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
9649f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (mSampleRate == 0) {
9659f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        mSampleRate = afSampleRate;
96689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
96789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    // Client decides whether the track is TIMED (see below), but can only express a preference
96889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    // for FAST.  Server will perform additional tests.
9699f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if ((mFlags & AUDIO_OUTPUT_FLAG_FAST) && !((
9709f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            // either of these use cases:
9719f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            // use case 1: shared buffer
9729f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            (mSharedBuffer != 0) ||
973c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent            // use case 2: callback transfer mode
9749f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            (mTransfer == TRANSFER_CALLBACK)) &&
97589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project            // matching sample rate
97689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project            (mSampleRate == afSampleRate))) {
97789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        ALOGW("AUDIO_OUTPUT_FLAG_FAST denied by client");
9789f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        // once denied, do not request again if IAudioTrack is re-created
9799f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        mFlags = (audio_output_flags_t) (mFlags & ~AUDIO_OUTPUT_FLAG_FAST);
9804ede21d9c1f957baf5e561849ff9bbe4bcbefc20Andy Hung    }
9814ede21d9c1f957baf5e561849ff9bbe4bcbefc20Andy Hung    ALOGV("createTrack_l() output %d afLatency %d", output, afLatency);
9824ede21d9c1f957baf5e561849ff9bbe4bcbefc20Andy Hung
9834ede21d9c1f957baf5e561849ff9bbe4bcbefc20Andy Hung    // The client's AudioTrack buffer is divided into n parts for purpose of wakeup by server, where
9844ede21d9c1f957baf5e561849ff9bbe4bcbefc20Andy Hung    //  n = 1   fast track with single buffering; nBuffering is ignored
98553c3b5fc1afe162a8669cb3d27d6bb14e1847e39Andy Hung    //  n = 2   fast track with double buffering
9869f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    //  n = 2   normal track, no sample rate conversion
9873c09c78aabcb9d314dfb400258fb99a37c7b50c9Andy Hung    //  n = 3   normal track, with sample rate conversion
9883c09c78aabcb9d314dfb400258fb99a37c7b50c9Andy Hung    //          (pessimistic; some non-1:1 conversion ratios don't actually need triple-buffering)
9899f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    //  n > 3   very high latency or very small notification interval; nBuffering is ignored
9909f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    const uint32_t nBuffering = (mSampleRate == afSampleRate) ? 2 : 3;
99189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
99289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    mNotificationFramesAct = mNotificationFramesReq;
993fb1fdc9d6603aa228362e7349451f6455c9849c2Glenn Kasten
994ab5cdbaf65ca509681d2726aacdf3ac8bfb6b3faEric Laurent    size_t frameCount = mReqFrameCount;
995d65d73c4ae74d084751b417615a78cbe7a51372aGlenn Kasten    if (!audio_is_linear_pcm(mFormat)) {
996d65d73c4ae74d084751b417615a78cbe7a51372aGlenn Kasten
99789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        if (mSharedBuffer != 0) {
9989f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            // Same comment as below about ignoring frameCount parameter for set()
99989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project            frameCount = mSharedBuffer->size();
10002c22aeb65e801f663a754d043062f85e49f77739Jean-Michel Trivi        } else if (frameCount == 0) {
100189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project            frameCount = afFrameCount;
10023c09c78aabcb9d314dfb400258fb99a37c7b50c9Andy Hung        }
10033c09c78aabcb9d314dfb400258fb99a37c7b50c9Andy Hung        if (mNotificationFramesAct != frameCount) {
10043c09c78aabcb9d314dfb400258fb99a37c7b50c9Andy Hung            mNotificationFramesAct = frameCount;
10053c09c78aabcb9d314dfb400258fb99a37c7b50c9Andy Hung        }
100689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    } else if (mSharedBuffer != 0) {
100789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
100889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        // Ensure that buffer alignment matches channel count
1009a5224f319e2ba4b51ddb4287705ccf8d4b8ecc51Glenn Kasten        // 8-bit data in shared memory is not currently supported by AudioFlinger
101089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        size_t alignment = audio_bytes_per_sample(
1011ab5cdbaf65ca509681d2726aacdf3ac8bfb6b3faEric Laurent                mFormat == AUDIO_FORMAT_PCM_8_BIT ? AUDIO_FORMAT_PCM_16_BIT : mFormat);
1012b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald        if (alignment & 1) {
1013b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald            alignment = 1;
1014d65d73c4ae74d084751b417615a78cbe7a51372aGlenn Kasten        }
1015d65d73c4ae74d084751b417615a78cbe7a51372aGlenn Kasten        if (mChannelCount > 1) {
1016d65d73c4ae74d084751b417615a78cbe7a51372aGlenn Kasten            // More than 2 channels does not require stronger alignment than stereo
101789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project            alignment <<= 1;
10189f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        }
101990e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung        if (((uintptr_t)mSharedBuffer->pointer() & (alignment - 1)) != 0) {
102089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project            ALOGE("Invalid buffer alignment: address %p, channel count %u",
102189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project                    mSharedBuffer->pointer(), mChannelCount);
102289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project            status = BAD_VALUE;
102389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project            goto release;
102489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        }
102589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
1026fb1fdc9d6603aa228362e7349451f6455c9849c2Glenn Kasten        // When initializing a shared buffer AudioTrack via constructors,
1027ab5cdbaf65ca509681d2726aacdf3ac8bfb6b3faEric Laurent        // there's no frameCount parameter.
1028d65d73c4ae74d084751b417615a78cbe7a51372aGlenn Kasten        // But when initializing a shared buffer AudioTrack via set(),
1029d65d73c4ae74d084751b417615a78cbe7a51372aGlenn Kasten        // there _is_ a frameCount parameter.  We silently ignore it.
103089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        frameCount = mSharedBuffer->size() / mFrameSizeAF;
10319f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
1032200092b7f21d2b98f30b800e79d152636f9ba225Glenn Kasten    } else if (!(mFlags & AUDIO_OUTPUT_FLAG_FAST)) {
103389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
10342b2165c75790050810460c8de3f414876bce4c0eGlenn Kasten        // FIXME move these calculations and associated checks to server
10353c09c78aabcb9d314dfb400258fb99a37c7b50c9Andy Hung
10363c09c78aabcb9d314dfb400258fb99a37c7b50c9Andy Hung        // Ensure that buffer depth covers at least audio hardware latency
10373c09c78aabcb9d314dfb400258fb99a37c7b50c9Andy Hung        uint32_t minBufCount = afLatency / ((1000 * afFrameCount)/afSampleRate);
10383c09c78aabcb9d314dfb400258fb99a37c7b50c9Andy Hung        ALOGV("afFrameCount=%zu, minBufCount=%d, afSampleRate=%u, afLatency=%d",
103989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project                afFrameCount, minBufCount, afSampleRate, afLatency);
104089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        if (minBufCount <= nBuffering) {
104189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project            minBufCount = nBuffering;
1042a5224f319e2ba4b51ddb4287705ccf8d4b8ecc51Glenn Kasten        }
104389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
1044ab5cdbaf65ca509681d2726aacdf3ac8bfb6b3faEric Laurent        size_t minFrameCount = afFrameCount * minBufCount * uint64_t(mSampleRate) / afSampleRate;
1045b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald        ALOGV("minFrameCount: %zu, afFrameCount=%zu, minBufCount=%d, sampleRate=%u, afSampleRate=%u"
1046b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald                ", afLatency=%d",
1047d65d73c4ae74d084751b417615a78cbe7a51372aGlenn Kasten                minFrameCount, afFrameCount, minBufCount, mSampleRate, afSampleRate, afLatency);
1048d65d73c4ae74d084751b417615a78cbe7a51372aGlenn Kasten
1049d65d73c4ae74d084751b417615a78cbe7a51372aGlenn Kasten        if (frameCount == 0) {
105089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project            frameCount = minFrameCount;
10519f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        } else if (frameCount < minFrameCount) {
105289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project            // not ALOGW because it happens all the time when playing key clicks over A2DP
105389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project            ALOGV("Minimum buffer size corrected from %zu to %zu",
105489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project                     frameCount, minFrameCount);
105589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project            frameCount = minFrameCount;
105689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        }
105789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        // Make sure that application is notified with sufficient margin before underrun
105889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        if (mNotificationFramesAct == 0 || mNotificationFramesAct > frameCount/nBuffering) {
1059d79072e9dff59f767cce2cda1caab80ce5a0815bGlenn Kasten            mNotificationFramesAct = frameCount/nBuffering;
1060d65d73c4ae74d084751b417615a78cbe7a51372aGlenn Kasten        }
1061d65d73c4ae74d084751b417615a78cbe7a51372aGlenn Kasten
10629f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    } else {
10639c6745f128648f6e0144b74ee593911a9fa10d51Glenn Kasten        // For fast tracks, the frame count calculations and checks are done by server
10649c6745f128648f6e0144b74ee593911a9fa10d51Glenn Kasten    }
10659c6745f128648f6e0144b74ee593911a9fa10d51Glenn Kasten
10669f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    IAudioFlinger::track_flags_t trackFlags = IAudioFlinger::TRACK_DEFAULT;
10679f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (mIsTimed) {
10689f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        trackFlags |= IAudioFlinger::TRACK_TIMED;
10699f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
10709f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
10719f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    pid_t tid = -1;
10729f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (mFlags & AUDIO_OUTPUT_FLAG_FAST) {
10739f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        trackFlags |= IAudioFlinger::TRACK_FAST;
10749f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        if (mAudioTrackThread != 0) {
1075d65d73c4ae74d084751b417615a78cbe7a51372aGlenn Kasten            tid = mAudioTrackThread->getTid();
10769b4615887c23548438fd0d8e3d8f04ac21912850Andy Hung        }
1077200092b7f21d2b98f30b800e79d152636f9ba225Glenn Kasten    }
10789b4615887c23548438fd0d8e3d8f04ac21912850Andy Hung
10793c09c78aabcb9d314dfb400258fb99a37c7b50c9Andy Hung    if (mFlags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
10803c09c78aabcb9d314dfb400258fb99a37c7b50c9Andy Hung        trackFlags |= IAudioFlinger::TRACK_OFFLOAD;
108189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
108289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
108389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    if (mFlags & AUDIO_OUTPUT_FLAG_DIRECT) {
1084200092b7f21d2b98f30b800e79d152636f9ba225Glenn Kasten        trackFlags |= IAudioFlinger::TRACK_DIRECT;
108589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
1086d65d73c4ae74d084751b417615a78cbe7a51372aGlenn Kasten
1087d65d73c4ae74d084751b417615a78cbe7a51372aGlenn Kasten    size_t temp = frameCount;   // temp may be replaced by a revised value of frameCount,
1088d65d73c4ae74d084751b417615a78cbe7a51372aGlenn Kasten                                // but we will still need the original value also
10899f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    sp<IAudioTrack> track = audioFlinger->createTrack(mStreamType,
10901703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent                                                      mSampleRate,
10917a490e7ab39ef0b22baf24b03f2463c46dc068edAndy Hung                                                      // AudioFlinger only sees 16-bit PCM
10927a490e7ab39ef0b22baf24b03f2463c46dc068edAndy Hung                                                      mFormat == AUDIO_FORMAT_PCM_8_BIT &&
10937a490e7ab39ef0b22baf24b03f2463c46dc068edAndy Hung                                                          !(mFlags & AUDIO_OUTPUT_FLAG_DIRECT) ?
10947a490e7ab39ef0b22baf24b03f2463c46dc068edAndy Hung                                                              AUDIO_FORMAT_PCM_16_BIT : mFormat,
10957a490e7ab39ef0b22baf24b03f2463c46dc068edAndy Hung                                                      mChannelMask,
1096b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald                                                      &temp,
109789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project                                                      &trackFlags,
1098ab5cdbaf65ca509681d2726aacdf3ac8bfb6b3faEric Laurent                                                      mSharedBuffer,
10997064fd2dcdfeafea53cd5a992bb78c413542f29fHaynes Mathew George                                                      output,
11007064fd2dcdfeafea53cd5a992bb78c413542f29fHaynes Mathew George                                                      tid,
11017064fd2dcdfeafea53cd5a992bb78c413542f29fHaynes Mathew George                                                      &mSessionId,
11027064fd2dcdfeafea53cd5a992bb78c413542f29fHaynes Mathew George                                                      mClientUid,
11037064fd2dcdfeafea53cd5a992bb78c413542f29fHaynes Mathew George                                                      &status);
1104142f519aa1acd5804d111e60d100f170fed28405Glenn Kasten
11051f1db8356b599bc40703c907fb69e6e539343532Andy Hung    if (status != NO_ERROR) {
11061f1db8356b599bc40703c907fb69e6e539343532Andy Hung        ALOGE("AudioFlinger could not create track, status: %d", status);
11071f1db8356b599bc40703c907fb69e6e539343532Andy Hung        goto release;
1108b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald    }
11097f1bc8af1c46695191bf7e2aba6467f3616629c0Andy Hung    ALOG_ASSERT(track != 0);
11107f1bc8af1c46695191bf7e2aba6467f3616629c0Andy Hung
1111b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald    // AudioFlinger now owns the reference to the I/O handle,
1112b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald    // so we are no longer responsible for releasing it.
1113275e8e9de2e11b4b344f5a201f1f0e51fda02d9cEric Laurent
11141f1db8356b599bc40703c907fb69e6e539343532Andy Hung    sp<IMemory> iMem = track->getCblk();
11151f1db8356b599bc40703c907fb69e6e539343532Andy Hung    if (iMem == 0) {
11161f1db8356b599bc40703c907fb69e6e539343532Andy Hung        ALOGE("Could not get control block");
1117275e8e9de2e11b4b344f5a201f1f0e51fda02d9cEric Laurent        return NO_INIT;
1118275e8e9de2e11b4b344f5a201f1f0e51fda02d9cEric Laurent    }
1119b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald    void *iMemPointer = iMem->pointer();
1120200092b7f21d2b98f30b800e79d152636f9ba225Glenn Kasten    if (iMemPointer == NULL) {
112190e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung        ALOGE("Could not get control block pointer");
1122b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald        return NO_INIT;
112389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
112489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    // invariant that mAudioTrack != 0 is true only after set() returns successfully
112589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    if (mAudioTrack != 0) {
1126377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT        mAudioTrack->asBinder()->unlinkToDeath(mDeathNotifier, this);
11279c6745f128648f6e0144b74ee593911a9fa10d51Glenn Kasten        mDeathNotifier.clear();
1128d79072e9dff59f767cce2cda1caab80ce5a0815bGlenn Kasten    }
11299c6745f128648f6e0144b74ee593911a9fa10d51Glenn Kasten    mAudioTrack = track;
11309c6745f128648f6e0144b74ee593911a9fa10d51Glenn Kasten    mCblkMemory = iMem;
11319c6745f128648f6e0144b74ee593911a9fa10d51Glenn Kasten    IPCThreadState::self()->flushCommands();
11329c6745f128648f6e0144b74ee593911a9fa10d51Glenn Kasten
11339c6745f128648f6e0144b74ee593911a9fa10d51Glenn Kasten    audio_track_cblk_t* cblk = static_cast<audio_track_cblk_t*>(iMemPointer);
11349c6745f128648f6e0144b74ee593911a9fa10d51Glenn Kasten    mCblk = cblk;
11359f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    // note that temp is the (possibly revised) value of frameCount
11369f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (temp < frameCount || (frameCount == 0 && temp == 0)) {
11379c6745f128648f6e0144b74ee593911a9fa10d51Glenn Kasten        // In current design, AudioTrack client checks and ensures frame count validity before
11389c6745f128648f6e0144b74ee593911a9fa10d51Glenn Kasten        // passing it to AudioFlinger so AudioFlinger should not return a different value except
11399c6745f128648f6e0144b74ee593911a9fa10d51Glenn Kasten        // for fast track as it uses a special method of assigning frame count.
114089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        ALOGW("Requested frameCount %zu but received frameCount %zu", frameCount, temp);
114189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
1142d79072e9dff59f767cce2cda1caab80ce5a0815bGlenn Kasten    frameCount = temp;
1143083d1c1492d496960d5b28f4664ff02101736677Glenn Kasten
1144083d1c1492d496960d5b28f4664ff02101736677Glenn Kasten    mAwaitBoost = false;
1145083d1c1492d496960d5b28f4664ff02101736677Glenn Kasten    if (mFlags & AUDIO_OUTPUT_FLAG_FAST) {
11461703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent        if (trackFlags & IAudioFlinger::TRACK_FAST) {
11479f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            ALOGV("AUDIO_OUTPUT_FLAG_FAST successful; frameCount %zu", frameCount);
11489f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            mAwaitBoost = true;
1149d65d73c4ae74d084751b417615a78cbe7a51372aGlenn Kasten            if (mSharedBuffer == 0) {
1150d65d73c4ae74d084751b417615a78cbe7a51372aGlenn Kasten                // Theoretically double-buffering is not required for fast tracks,
11519f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten                // due to tighter scheduling.  But in practice, to accommodate kernels with
11529b4615887c23548438fd0d8e3d8f04ac21912850Andy Hung                // scheduling jitter, and apps with computation jitter, we use double-buffering.
11539b4615887c23548438fd0d8e3d8f04ac21912850Andy Hung                if (mNotificationFramesAct == 0 || mNotificationFramesAct > frameCount/nBuffering) {
11541b42097f38e72574ed853a35f4e8a66e4739c421Phil Burk                    mNotificationFramesAct = frameCount/nBuffering;
115553c3b5fc1afe162a8669cb3d27d6bb14e1847e39Andy Hung                }
11569b4615887c23548438fd0d8e3d8f04ac21912850Andy Hung            }
115753c3b5fc1afe162a8669cb3d27d6bb14e1847e39Andy Hung        } else {
115853c3b5fc1afe162a8669cb3d27d6bb14e1847e39Andy Hung            ALOGV("AUDIO_OUTPUT_FLAG_FAST denied by server; frameCount %zu", frameCount);
115953c3b5fc1afe162a8669cb3d27d6bb14e1847e39Andy Hung            // once denied, do not request again if IAudioTrack is re-created
116053c3b5fc1afe162a8669cb3d27d6bb14e1847e39Andy Hung            mFlags = (audio_output_flags_t) (mFlags & ~AUDIO_OUTPUT_FLAG_FAST);
116153c3b5fc1afe162a8669cb3d27d6bb14e1847e39Andy Hung            if (mSharedBuffer == 0) {
116253c3b5fc1afe162a8669cb3d27d6bb14e1847e39Andy Hung                if (mNotificationFramesAct == 0 || mNotificationFramesAct > frameCount/nBuffering) {
116353c3b5fc1afe162a8669cb3d27d6bb14e1847e39Andy Hung                    mNotificationFramesAct = frameCount/nBuffering;
11649b4615887c23548438fd0d8e3d8f04ac21912850Andy Hung                }
116589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project            }
116689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        }
116789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
116838e905b3cbba4da443d799b16999989781afc6d8Glenn Kasten    if (mFlags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
1169c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent        if (trackFlags & IAudioFlinger::TRACK_OFFLOAD) {
11701703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent            ALOGV("AUDIO_OUTPUT_FLAG_OFFLOAD successful");
1171b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald        } else {
11721703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent            ALOGW("AUDIO_OUTPUT_FLAG_OFFLOAD denied by server");
11731703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent            mFlags = (audio_output_flags_t) (mFlags & ~AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD);
1174aa9811945f575614b3482d09e4d969792701cebbPaul McLean            // FIXME This is a warning, not an error, so don't return error status
1175aa9811945f575614b3482d09e4d969792701cebbPaul McLean            //return NO_INIT;
1176aa9811945f575614b3482d09e4d969792701cebbPaul McLean        }
1177aa9811945f575614b3482d09e4d969792701cebbPaul McLean    }
1178493404d8c396e15ed73455acd39aa0f1940996e2Eric Laurent    if (mFlags & AUDIO_OUTPUT_FLAG_DIRECT) {
1179aa9811945f575614b3482d09e4d969792701cebbPaul McLean        if (trackFlags & IAudioFlinger::TRACK_DIRECT) {
1180493404d8c396e15ed73455acd39aa0f1940996e2Eric Laurent            ALOGV("AUDIO_OUTPUT_FLAG_DIRECT successful");
1181aa9811945f575614b3482d09e4d969792701cebbPaul McLean        } else {
1182aa9811945f575614b3482d09e4d969792701cebbPaul McLean            ALOGW("AUDIO_OUTPUT_FLAG_DIRECT denied by server");
1183aa9811945f575614b3482d09e4d969792701cebbPaul McLean            mFlags = (audio_output_flags_t) (mFlags & ~AUDIO_OUTPUT_FLAG_DIRECT);
1184aa9811945f575614b3482d09e4d969792701cebbPaul McLean            // FIXME This is a warning, not an error, so don't return error status
1185aa9811945f575614b3482d09e4d969792701cebbPaul McLean            //return NO_INIT;
1186aa9811945f575614b3482d09e4d969792701cebbPaul McLean        }
1187aa9811945f575614b3482d09e4d969792701cebbPaul McLean    }
1188296fb13dd9b5e90d6a05cce897c3b1e7914a478aEric Laurent
1189296fb13dd9b5e90d6a05cce897c3b1e7914a478aEric Laurent    // We retain a copy of the I/O handle, but don't own the reference
1190296fb13dd9b5e90d6a05cce897c3b1e7914a478aEric Laurent    mOutput = output;
1191296fb13dd9b5e90d6a05cce897c3b1e7914a478aEric Laurent    mRefreshRemaining = true;
1192296fb13dd9b5e90d6a05cce897c3b1e7914a478aEric Laurent
1193296fb13dd9b5e90d6a05cce897c3b1e7914a478aEric Laurent    // Starting address of buffers in shared memory.  If there is a shared buffer, buffers
1194296fb13dd9b5e90d6a05cce897c3b1e7914a478aEric Laurent    // is the value of pointer() for the shared buffer, otherwise buffers points
1195296fb13dd9b5e90d6a05cce897c3b1e7914a478aEric Laurent    // immediately after the control block.  This address is for the mapping within client
1196be916aa1267e2e6b1c148f51d11bcbbc79cb864cEric Laurent    // address space.  AudioFlinger::TrackBase::mBuffer is for the server address space.
1197be916aa1267e2e6b1c148f51d11bcbbc79cb864cEric Laurent    void* buffers;
11989f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (mSharedBuffer == 0) {
11992beeb50b1bba9e92f6cacfeca37fe9fa9d36ead1Eric Laurent        buffers = (char*)cblk + sizeof(audio_track_cblk_t);
12002beeb50b1bba9e92f6cacfeca37fe9fa9d36ead1Eric Laurent    } else {
12012beeb50b1bba9e92f6cacfeca37fe9fa9d36ead1Eric Laurent        buffers = mSharedBuffer->pointer();
12022beeb50b1bba9e92f6cacfeca37fe9fa9d36ead1Eric Laurent    }
12032beeb50b1bba9e92f6cacfeca37fe9fa9d36ead1Eric Laurent
1204be916aa1267e2e6b1c148f51d11bcbbc79cb864cEric Laurent    mAudioTrack->attachAuxEffect(mAuxEffectId);
1205be916aa1267e2e6b1c148f51d11bcbbc79cb864cEric Laurent    // FIXME don't believe this lie
1206e83b55dc29ca16092ba02f36f55fa6e0e37fd78cEric Laurent    mLatency = afLatency + (1000*frameCount) / mSampleRate;
1207e83b55dc29ca16092ba02f36f55fa6e0e37fd78cEric Laurent
1208e83b55dc29ca16092ba02f36f55fa6e0e37fd78cEric Laurent    mFrameCount = frameCount;
1209e83b55dc29ca16092ba02f36f55fa6e0e37fd78cEric Laurent    // If IAudioTrack is re-created, don't let the requested frameCount
1210e83b55dc29ca16092ba02f36f55fa6e0e37fd78cEric Laurent    // decrease.  This can confuse clients that cache frameCount().
1211e83b55dc29ca16092ba02f36f55fa6e0e37fd78cEric Laurent    if (frameCount > mReqFrameCount) {
1212e83b55dc29ca16092ba02f36f55fa6e0e37fd78cEric Laurent        mReqFrameCount = frameCount;
1213e83b55dc29ca16092ba02f36f55fa6e0e37fd78cEric Laurent    }
121489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
121589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    // update proxy
12161703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent    if (mSharedBuffer == 0) {
1217200092b7f21d2b98f30b800e79d152636f9ba225Glenn Kasten        mStaticProxy.clear();
121834f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent        mProxy = new AudioTrackClientProxy(cblk, buffers, frameCount, mFrameSizeAF);
121934f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent    } else {
122034f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent        mStaticProxy = new StaticAudioTrackClientProxy(cblk, buffers, frameCount, mFrameSizeAF);
1221e53b9ead781c36e96d6b6f012ddffc93a3d80f0dGlenn Kasten        mProxy = mStaticProxy;
1222e53b9ead781c36e96d6b6f012ddffc93a3d80f0dGlenn Kasten    }
122334f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent    mProxy->setVolumeLR(GAIN_MINIFLOAT_PACKED_UNITY);
122434f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent    mProxy->setSendLevel(mSendLevel);
1225296fb13dd9b5e90d6a05cce897c3b1e7914a478aEric Laurent    mProxy->setSampleRate(mSampleRate);
1226296fb13dd9b5e90d6a05cce897c3b1e7914a478aEric Laurent    mProxy->setMinimum(mNotificationFramesAct);
1227296fb13dd9b5e90d6a05cce897c3b1e7914a478aEric Laurent
1228e83b55dc29ca16092ba02f36f55fa6e0e37fd78cEric Laurent    mDeathNotifier = new DeathNotifier(this);
1229e83b55dc29ca16092ba02f36f55fa6e0e37fd78cEric Laurent    mAudioTrack->asBinder()->linkToDeath(mDeathNotifier, this);
1230e83b55dc29ca16092ba02f36f55fa6e0e37fd78cEric Laurent
1231e83b55dc29ca16092ba02f36f55fa6e0e37fd78cEric Laurent    return NO_ERROR;
1232ae34ed2bcc9fa49a22fe7497327adb689ef27e8dHaynes Mathew George    }
1233ae34ed2bcc9fa49a22fe7497327adb689ef27e8dHaynes Mathew George
1234ae34ed2bcc9fa49a22fe7497327adb689ef27e8dHaynes Mathew Georgerelease:
1235aa9811945f575614b3482d09e4d969792701cebbPaul McLean    AudioSystem::releaseOutput(output);
1236aa9811945f575614b3482d09e4d969792701cebbPaul McLean    if (status == NO_ERROR) {
1237d848eb48c121c119e8ba7583efc75415fe102570Glenn Kasten        status = NO_INIT;
1238aa9811945f575614b3482d09e4d969792701cebbPaul McLean    }
1239aa9811945f575614b3482d09e4d969792701cebbPaul McLean    return status;
1240e83b55dc29ca16092ba02f36f55fa6e0e37fd78cEric Laurent}
1241e83b55dc29ca16092ba02f36f55fa6e0e37fd78cEric Laurent
12424c36d6f48f4eecacc148317f775f65961a4f03d2Glenn Kastenstatus_t AudioTrack::obtainBuffer(Buffer* audioBuffer, int32_t waitCount)
12435bd3f38638acab633d181359cc9ec27b80f84d43Jean-Michel Trivi{
12444c36d6f48f4eecacc148317f775f65961a4f03d2Glenn Kasten    if (audioBuffer == NULL) {
124538e905b3cbba4da443d799b16999989781afc6d8Glenn Kasten        return BAD_VALUE;
124638e905b3cbba4da443d799b16999989781afc6d8Glenn Kasten    }
124738e905b3cbba4da443d799b16999989781afc6d8Glenn Kasten    if (mTransfer != TRANSFER_OBTAIN) {
124838e905b3cbba4da443d799b16999989781afc6d8Glenn Kasten        audioBuffer->frameCount = 0;
124938e905b3cbba4da443d799b16999989781afc6d8Glenn Kasten        audioBuffer->size = 0;
125038e905b3cbba4da443d799b16999989781afc6d8Glenn Kasten        audioBuffer->raw = NULL;
1251ce8828a016b082f730152af2204b8ea3610dc1ecGlenn Kasten        return INVALID_OPERATION;
12529f9e21ed9a342e0ca945818bdc6c0c4fb3bfb9bdAndy Hung    }
1253ce8828a016b082f730152af2204b8ea3610dc1ecGlenn Kasten
12549f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    const struct timespec *requested;
125538e905b3cbba4da443d799b16999989781afc6d8Glenn Kasten    struct timespec timeout;
1256d1b449aad6c087a69f5ec66b7facb2845b73f1cbEric Laurent    if (waitCount == -1) {
12579f9e21ed9a342e0ca945818bdc6c0c4fb3bfb9bdAndy Hung        requested = &ClientProxy::kForever;
1258d1b449aad6c087a69f5ec66b7facb2845b73f1cbEric Laurent    } else if (waitCount == 0) {
12599f9e21ed9a342e0ca945818bdc6c0c4fb3bfb9bdAndy Hung        requested = &ClientProxy::kNonBlocking;
1260ce8828a016b082f730152af2204b8ea3610dc1ecGlenn Kasten    } else if (waitCount > 0) {
1261b7f24b101d43139b4c747129bfbc4ecf5c468b86Jean-Michel Trivi        long long ms = WAIT_PERIOD_MS * (long long) waitCount;
126238e905b3cbba4da443d799b16999989781afc6d8Glenn Kasten        timeout.tv_sec = ms / 1000;
1263ce8828a016b082f730152af2204b8ea3610dc1ecGlenn Kasten        timeout.tv_nsec = (int) (ms % 1000) * 1000000;
1264ce8828a016b082f730152af2204b8ea3610dc1ecGlenn Kasten        requested = &timeout;
1265ea38ee7742e799b23bd8675f5801ef72f94de0f4Glenn Kasten    } else {
1266ea38ee7742e799b23bd8675f5801ef72f94de0f4Glenn Kasten        ALOGE("%s invalid waitCount %d", __func__, waitCount);
1267ea38ee7742e799b23bd8675f5801ef72f94de0f4Glenn Kasten        requested = NULL;
1268ea38ee7742e799b23bd8675f5801ef72f94de0f4Glenn Kasten    }
1269ea38ee7742e799b23bd8675f5801ef72f94de0f4Glenn Kasten    return obtainBuffer(audioBuffer, requested);
1270ea38ee7742e799b23bd8675f5801ef72f94de0f4Glenn Kasten}
1271ea38ee7742e799b23bd8675f5801ef72f94de0f4Glenn Kasten
1272ea38ee7742e799b23bd8675f5801ef72f94de0f4Glenn Kastenstatus_t AudioTrack::obtainBuffer(Buffer* audioBuffer, const struct timespec *requested,
1273ea38ee7742e799b23bd8675f5801ef72f94de0f4Glenn Kasten        struct timespec *elapsed, size_t *nonContig)
12749f9e21ed9a342e0ca945818bdc6c0c4fb3bfb9bdAndy Hung{
1275ce8828a016b082f730152af2204b8ea3610dc1ecGlenn Kasten    // previous and new IAudioTrack sequence numbers are used to detect track re-creation
1276b7f24b101d43139b4c747129bfbc4ecf5c468b86Jean-Michel Trivi    uint32_t oldSequence = 0;
127738e905b3cbba4da443d799b16999989781afc6d8Glenn Kasten    uint32_t newSequence;
1278ce8828a016b082f730152af2204b8ea3610dc1ecGlenn Kasten
12790d6db582f2ccc9f8943c5f3965e2994b7d137158Eric Laurent    Proxy::Buffer buffer;
12809f9e21ed9a342e0ca945818bdc6c0c4fb3bfb9bdAndy Hung    status_t status = NO_ERROR;
12819f9e21ed9a342e0ca945818bdc6c0c4fb3bfb9bdAndy Hung
12820d6db582f2ccc9f8943c5f3965e2994b7d137158Eric Laurent    static const int32_t kMaxTries = 5;
12837fd0422fbd17af3b24eb04421d37fce50f3826e2Glenn Kasten    int32_t tryCounter = kMaxTries;
1284d79072e9dff59f767cce2cda1caab80ce5a0815bGlenn Kasten
128533ff89ba94a527e4293ee5349da01483252d5c83Phil Burk    do {
128633ff89ba94a527e4293ee5349da01483252d5c83Phil Burk        // obtainBuffer() is called with mutex unlocked, so keep extra references to these fields to
12874a4a0959bca78e03e3c3f486ba17829c28314d8cGlenn Kasten        // keep them from going away if another thread re-creates the track during obtainBuffer()
12884a4a0959bca78e03e3c3f486ba17829c28314d8cGlenn Kasten        sp<AudioTrackClientProxy> proxy;
1289363fb75db26698cbb50065506e0c80b61d1fbf92Glenn Kasten        sp<IMemory> iMem;
1290c6ba823a397abf865b02f4f48fe18231f94d8e87Glenn Kasten
12911dfe2f9c2d03fc8d0ed0cdfe0b9fb894bc0bcc11Glenn Kasten        {   // start of lock scope
12921dfe2f9c2d03fc8d0ed0cdfe0b9fb894bc0bcc11Glenn Kasten            AutoMutex lock(mLock);
129333ff89ba94a527e4293ee5349da01483252d5c83Phil Burk
129433ff89ba94a527e4293ee5349da01483252d5c83Phil Burk            newSequence = mSequence;
129533ff89ba94a527e4293ee5349da01483252d5c83Phil Burk            // did previous obtainBuffer() fail due to media server death or voluntary invalidation?
129633ff89ba94a527e4293ee5349da01483252d5c83Phil Burk            if (status == DEAD_OBJECT) {
129733ff89ba94a527e4293ee5349da01483252d5c83Phil Burk                // re-create track, unless someone else has already done so
129833ff89ba94a527e4293ee5349da01483252d5c83Phil Burk                if (newSequence == oldSequence) {
12997fd0422fbd17af3b24eb04421d37fce50f3826e2Glenn Kasten                    status = restoreTrack_l("obtainBuffer");
130033ff89ba94a527e4293ee5349da01483252d5c83Phil Burk                    if (status != NO_ERROR) {
13019f9e21ed9a342e0ca945818bdc6c0c4fb3bfb9bdAndy Hung                        buffer.mFrameCount = 0;
130233ff89ba94a527e4293ee5349da01483252d5c83Phil Burk                        buffer.mRaw = NULL;
130333ff89ba94a527e4293ee5349da01483252d5c83Phil Burk                        buffer.mNonContig = 0;
13044a4a0959bca78e03e3c3f486ba17829c28314d8cGlenn Kasten                        break;
13054a4a0959bca78e03e3c3f486ba17829c28314d8cGlenn Kasten                    }
1306d1b449aad6c087a69f5ec66b7facb2845b73f1cbEric Laurent                }
1307e0fa467e1150c65a7b1b1ed904c579b40f97c9dfGlenn Kasten            }
1308363fb75db26698cbb50065506e0c80b61d1fbf92Glenn Kasten            oldSequence = newSequence;
1309fdb3c07db5d44535eb8c3ec46dc78ad8446c01ebPhil Burk
1310e0fa467e1150c65a7b1b1ed904c579b40f97c9dfGlenn Kasten            // Keep the extra references
1311363fb75db26698cbb50065506e0c80b61d1fbf92Glenn Kasten            proxy = mProxy;
1312e0fa467e1150c65a7b1b1ed904c579b40f97c9dfGlenn Kasten            iMem = mCblkMemory;
1313363fb75db26698cbb50065506e0c80b61d1fbf92Glenn Kasten
1314e0fa467e1150c65a7b1b1ed904c579b40f97c9dfGlenn Kasten            if (mState == STATE_STOPPING) {
13159f9e21ed9a342e0ca945818bdc6c0c4fb3bfb9bdAndy Hung                status = -EINTR;
1316d1b449aad6c087a69f5ec66b7facb2845b73f1cbEric Laurent                buffer.mFrameCount = 0;
1317b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald                buffer.mRaw = NULL;
1318b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald                buffer.mNonContig = 0;
1319b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald                break;
1320363fb75db26698cbb50065506e0c80b61d1fbf92Glenn Kasten            }
1321abdb990953ffe94a9dc544aea0bed17ef7d5f484Andy Hung
1322abdb990953ffe94a9dc544aea0bed17ef7d5f484Andy Hung            // Non-blocking if track is stopped or paused
1323abdb990953ffe94a9dc544aea0bed17ef7d5f484Andy Hung            if (mState != STATE_ACTIVE) {
1324abdb990953ffe94a9dc544aea0bed17ef7d5f484Andy Hung                requested = &ClientProxy::kNonBlocking;
1325b773038277ba328696832b690b91ce6e95bd1a6cGlenn Kasten            }
1326abdb990953ffe94a9dc544aea0bed17ef7d5f484Andy Hung
1327b773038277ba328696832b690b91ce6e95bd1a6cGlenn Kasten        }   // end of lock scope
1328b773038277ba328696832b690b91ce6e95bd1a6cGlenn Kasten
1329a42ff007a17d63df22c60dd5e5fd811ee45ca1b3Glenn Kasten        buffer.mFrameCount = audioBuffer->frameCount;
1330e0fa467e1150c65a7b1b1ed904c579b40f97c9dfGlenn Kasten        // FIXME starts the requested timeout and elapsed over from scratch
1331e0fa467e1150c65a7b1b1ed904c579b40f97c9dfGlenn Kasten        status = proxy->obtainBuffer(&buffer, requested, elapsed);
1332e0fa467e1150c65a7b1b1ed904c579b40f97c9dfGlenn Kasten
13331d6fa7af1288b550faabe4ec2cf98684236723dbNarayan Kamath    } while ((status == DEAD_OBJECT) && (tryCounter-- > 0));
1334a42ff007a17d63df22c60dd5e5fd811ee45ca1b3Glenn Kasten
1335363fb75db26698cbb50065506e0c80b61d1fbf92Glenn Kasten    audioBuffer->frameCount = buffer.mFrameCount;
133638e905b3cbba4da443d799b16999989781afc6d8Glenn Kasten    audioBuffer->size = buffer.mFrameCount * mFrameSizeAF;
133738e905b3cbba4da443d799b16999989781afc6d8Glenn Kasten    audioBuffer->raw = buffer.mRaw;
1338e0fa467e1150c65a7b1b1ed904c579b40f97c9dfGlenn Kasten    if (nonContig != NULL) {
1339e0fa467e1150c65a7b1b1ed904c579b40f97c9dfGlenn Kasten        *nonContig = buffer.mNonContig;
1340e0fa467e1150c65a7b1b1ed904c579b40f97c9dfGlenn Kasten    }
1341e0fa467e1150c65a7b1b1ed904c579b40f97c9dfGlenn Kasten    return status;
1342e0fa467e1150c65a7b1b1ed904c579b40f97c9dfGlenn Kasten}
1343e0fa467e1150c65a7b1b1ed904c579b40f97c9dfGlenn Kasten
1344abdb990953ffe94a9dc544aea0bed17ef7d5f484Andy Hungvoid AudioTrack::releaseBuffer(Buffer* audioBuffer)
1345e0fa467e1150c65a7b1b1ed904c579b40f97c9dfGlenn Kasten{
1346ea38ee7742e799b23bd8675f5801ef72f94de0f4Glenn Kasten    if (mTransfer == TRANSFER_SHARED) {
1347ea38ee7742e799b23bd8675f5801ef72f94de0f4Glenn Kasten        return;
1348ea38ee7742e799b23bd8675f5801ef72f94de0f4Glenn Kasten    }
1349ea38ee7742e799b23bd8675f5801ef72f94de0f4Glenn Kasten
1350ea38ee7742e799b23bd8675f5801ef72f94de0f4Glenn Kasten    size_t stepCount = audioBuffer->size / mFrameSizeAF;
1351ea38ee7742e799b23bd8675f5801ef72f94de0f4Glenn Kasten    if (stepCount == 0) {
1352ea38ee7742e799b23bd8675f5801ef72f94de0f4Glenn Kasten        return;
1353ea38ee7742e799b23bd8675f5801ef72f94de0f4Glenn Kasten    }
1354ea38ee7742e799b23bd8675f5801ef72f94de0f4Glenn Kasten
1355ea38ee7742e799b23bd8675f5801ef72f94de0f4Glenn Kasten    Proxy::Buffer buffer;
1356ea38ee7742e799b23bd8675f5801ef72f94de0f4Glenn Kasten    buffer.mFrameCount = stepCount;
1357ea38ee7742e799b23bd8675f5801ef72f94de0f4Glenn Kasten    buffer.mRaw = audioBuffer->raw;
1358ea38ee7742e799b23bd8675f5801ef72f94de0f4Glenn Kasten
1359ea38ee7742e799b23bd8675f5801ef72f94de0f4Glenn Kasten    AutoMutex lock(mLock);
1360ea38ee7742e799b23bd8675f5801ef72f94de0f4Glenn Kasten    mReleased += stepCount;
13618edb8dc44b8a2f81bdb5db645b6b708548771a31Andy Hung    mInUnderrun = false;
1362ff874dc957f9ea70d87f4d627bf903e1fc86d58bAndy Hung    mProxy->releaseBuffer(&buffer);
1363ff874dc957f9ea70d87f4d627bf903e1fc86d58bAndy Hung
1364ea38ee7742e799b23bd8675f5801ef72f94de0f4Glenn Kasten    // restart track if it was disabled by audioflinger due to previous underrun
13659f9e21ed9a342e0ca945818bdc6c0c4fb3bfb9bdAndy Hung    if (mState == STATE_ACTIVE) {
1366ea38ee7742e799b23bd8675f5801ef72f94de0f4Glenn Kasten        audio_track_cblk_t* cblk = mCblk;
1367ea38ee7742e799b23bd8675f5801ef72f94de0f4Glenn Kasten        if (android_atomic_and(~CBLK_DISABLED, &cblk->mFlags) & CBLK_DISABLED) {
1368ea38ee7742e799b23bd8675f5801ef72f94de0f4Glenn Kasten            ALOGW("releaseBuffer() track %p disabled due to previous underrun, restarting", this);
1369ea38ee7742e799b23bd8675f5801ef72f94de0f4Glenn Kasten            // FIXME ignoring status
13708edb8dc44b8a2f81bdb5db645b6b708548771a31Andy Hung            mAudioTrack->start();
1371d1b449aad6c087a69f5ec66b7facb2845b73f1cbEric Laurent        }
1372d1b449aad6c087a69f5ec66b7facb2845b73f1cbEric Laurent    }
1373a075db4ff9b086ac2885df77bb6da0869293df92Glenn Kasten}
13743acbd053c842e76e1a40fc8a0bf62de87eebf00fGlenn Kasten
13753acbd053c842e76e1a40fc8a0bf62de87eebf00fGlenn Kasten// -------------------------------------------------------------------------
1376363fb75db26698cbb50065506e0c80b61d1fbf92Glenn Kasten
13774a4a0959bca78e03e3c3f486ba17829c28314d8cGlenn Kastenssize_t AudioTrack::write(const void* buffer, size_t userSize, bool blocking)
137833ff89ba94a527e4293ee5349da01483252d5c83Phil Burk{
13793acbd053c842e76e1a40fc8a0bf62de87eebf00fGlenn Kasten    if (mTransfer != TRANSFER_SYNC || mIsTimed) {
13803acbd053c842e76e1a40fc8a0bf62de87eebf00fGlenn Kasten        return INVALID_OPERATION;
13814a4a0959bca78e03e3c3f486ba17829c28314d8cGlenn Kasten    }
13824a4a0959bca78e03e3c3f486ba17829c28314d8cGlenn Kasten
1383363fb75db26698cbb50065506e0c80b61d1fbf92Glenn Kasten    if (isDirect()) {
1384b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald        AutoMutex lock(mLock);
1385b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald        int32_t flags = android_atomic_and(
1386b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald                            ~(CBLK_UNDERRUN | CBLK_LOOP_CYCLE | CBLK_LOOP_FINAL | CBLK_BUFFER_END),
1387ab5cdbaf65ca509681d2726aacdf3ac8bfb6b3faEric Laurent                            &mCblk->mFlags);
1388ab5cdbaf65ca509681d2726aacdf3ac8bfb6b3faEric Laurent        if (flags & CBLK_INVALID) {
1389ab5cdbaf65ca509681d2726aacdf3ac8bfb6b3faEric Laurent            return DEAD_OBJECT;
1390ab5cdbaf65ca509681d2726aacdf3ac8bfb6b3faEric Laurent        }
139174935e44734c1ec235c2b6677db3e0dbefa5ddb8Glenn Kasten    }
139274935e44734c1ec235c2b6677db3e0dbefa5ddb8Glenn Kasten
1393d848eb48c121c119e8ba7583efc75415fe102570Glenn Kasten    if (ssize_t(userSize) < 0 || (buffer == NULL && userSize != 0)) {
1394e83b55dc29ca16092ba02f36f55fa6e0e37fd78cEric Laurent        // Sanity-check: user is most-likely passing an error code, and it would
1395363fb75db26698cbb50065506e0c80b61d1fbf92Glenn Kasten        // make the return value ambiguous (actualSize vs error).
1396abdb990953ffe94a9dc544aea0bed17ef7d5f484Andy Hung        ALOGE("AudioTrack::write(buffer=%p, size=%zu (%zd)", buffer, userSize, userSize);
1397a42ff007a17d63df22c60dd5e5fd811ee45ca1b3Glenn Kasten        return BAD_VALUE;
139874935e44734c1ec235c2b6677db3e0dbefa5ddb8Glenn Kasten    }
1399e0b07179a48ee50fda931d2aa1b3c751d167e4d7Glenn Kasten
1400363fb75db26698cbb50065506e0c80b61d1fbf92Glenn Kasten    size_t written = 0;
140134f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent    Buffer audioBuffer;
14023acbd053c842e76e1a40fc8a0bf62de87eebf00fGlenn Kasten
1403be916aa1267e2e6b1c148f51d11bcbbc79cb864cEric Laurent    while (userSize >= mFrameSize) {
1404462fd2fa9eef642b0574aa7409de0bde3fec8d43Marco Nelissen        audioBuffer.frameCount = userSize / mFrameSize;
140534f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent
1406138d6f9b0b77d94773a8a29d3c5bdb78f38ee142Glenn Kasten        status_t err = obtainBuffer(&audioBuffer,
1407138d6f9b0b77d94773a8a29d3c5bdb78f38ee142Glenn Kasten                blocking ? &ClientProxy::kForever : &ClientProxy::kNonBlocking);
140834f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent        if (err < 0) {
1409c08d20b6a37122ebf116262c9372509ed060d4c1Glenn Kasten            if (written > 0) {
141029357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block                break;
141138e905b3cbba4da443d799b16999989781afc6d8Glenn Kasten            }
141234f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent            return ssize_t(err);
1413c08d20b6a37122ebf116262c9372509ed060d4c1Glenn Kasten        }
1414c08d20b6a37122ebf116262c9372509ed060d4c1Glenn Kasten
141538e905b3cbba4da443d799b16999989781afc6d8Glenn Kasten        size_t toWrite;
141638e905b3cbba4da443d799b16999989781afc6d8Glenn Kasten        if (mFormat == AUDIO_FORMAT_PCM_8_BIT && !(mFlags & AUDIO_OUTPUT_FLAG_DIRECT)) {
141738e905b3cbba4da443d799b16999989781afc6d8Glenn Kasten            // Divide capacity by 2 to take expansion into account
14187fd0422fbd17af3b24eb04421d37fce50f3826e2Glenn Kasten            toWrite = audioBuffer.size >> 1;
1419d2c38fc4d5dc742d7441444316849510dd2b7363Glenn Kasten            memcpy_to_i16_from_u8(audioBuffer.i16, (const uint8_t *) buffer, toWrite);
1420d2c38fc4d5dc742d7441444316849510dd2b7363Glenn Kasten        } else {
142129357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block            toWrite = audioBuffer.size;
142234f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent            memcpy(audioBuffer.i8, buffer, toWrite);
142334f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent        }
14240cde076ddb283c84c3801a2df4cc3df99bd1577fGlenn Kasten        buffer = ((const char *) buffer) + toWrite;
14250cde076ddb283c84c3801a2df4cc3df99bd1577fGlenn Kasten        userSize -= toWrite;
14260cde076ddb283c84c3801a2df4cc3df99bd1577fGlenn Kasten        written += toWrite;
14270cde076ddb283c84c3801a2df4cc3df99bd1577fGlenn Kasten
14280cde076ddb283c84c3801a2df4cc3df99bd1577fGlenn Kasten        releaseBuffer(&audioBuffer);
142953cec22821072719ee02c856e9ac2dda2496c570Glenn Kasten    }
14309f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
1431f888020c6e2735624f2b2a30e72aca24e17b8b4dMarco Nelissen    return written;
14329f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten}
14339f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
143434f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent// -------------------------------------------------------------------------
1435d2c38fc4d5dc742d7441444316849510dd2b7363Glenn Kasten
14363bcffa136909c1fb6e88ee4efd12ccac18360a85Eric LaurentTimedAudioTrack::TimedAudioTrack() {
14373bcffa136909c1fb6e88ee4efd12ccac18360a85Eric Laurent    mIsTimed = true;
14380cde076ddb283c84c3801a2df4cc3df99bd1577fGlenn Kasten}
1439d2c38fc4d5dc742d7441444316849510dd2b7363Glenn Kasten
144074935e44734c1ec235c2b6677db3e0dbefa5ddb8Glenn Kastenstatus_t TimedAudioTrack::allocateTimedBuffer(size_t size, sp<IMemory>* buffer)
1441b603744e96b07b1d5bf745bde593fb2c025cefcfGlenn Kasten{
1442b603744e96b07b1d5bf745bde593fb2c025cefcfGlenn Kasten    AutoMutex lock(mLock);
1443b603744e96b07b1d5bf745bde593fb2c025cefcfGlenn Kasten    status_t result = UNKNOWN_ERROR;
1444b603744e96b07b1d5bf745bde593fb2c025cefcfGlenn Kasten
144534fb29696b0f3abf61b10f8d053b1f33d501de0aMark Salyzyn#if 1
1446b603744e96b07b1d5bf745bde593fb2c025cefcfGlenn Kasten    // acquire a strong reference on the IMemory and IAudioTrack so that they cannot be destroyed
1447b603744e96b07b1d5bf745bde593fb2c025cefcfGlenn Kasten    // while we are accessing the cblk
14485f631515d098c29603cda88f7a7e7580a2d55b57Glenn Kasten    sp<IAudioTrack> audioTrack = mAudioTrack;
1449a07f17ca46db04c9d5d9e7d6b2878db59ca2b9eaGlenn Kasten    sp<IMemory> iMem = mCblkMemory;
1450363fb75db26698cbb50065506e0c80b61d1fbf92Glenn Kasten#endif
1451e0b07179a48ee50fda931d2aa1b3c751d167e4d7Glenn Kasten
145234fb29696b0f3abf61b10f8d053b1f33d501de0aMark Salyzyn    // If the track is not invalid already, try to allocate a buffer.  alloc
145333ff89ba94a527e4293ee5349da01483252d5c83Phil Burk    // fails indicating that the server is dead, flag the track as invalid so
145433ff89ba94a527e4293ee5349da01483252d5c83Phil Burk    // we can attempt to restore in just a bit.
145533ff89ba94a527e4293ee5349da01483252d5c83Phil Burk    audio_track_cblk_t* cblk = mCblk;
14563acbd053c842e76e1a40fc8a0bf62de87eebf00fGlenn Kasten    if (!(cblk->mFlags & CBLK_INVALID)) {
1457ae34ed2bcc9fa49a22fe7497327adb689ef27e8dHaynes Mathew George        result = mAudioTrack->allocateTimedBuffer(size, buffer);
1458363fb75db26698cbb50065506e0c80b61d1fbf92Glenn Kasten        if (result == DEAD_OBJECT) {
1459e0fa467e1150c65a7b1b1ed904c579b40f97c9dfGlenn Kasten            android_atomic_or(CBLK_INVALID, &cblk->mFlags);
14603acbd053c842e76e1a40fc8a0bf62de87eebf00fGlenn Kasten        }
14617fd0422fbd17af3b24eb04421d37fce50f3826e2Glenn Kasten    }
14627fd0422fbd17af3b24eb04421d37fce50f3826e2Glenn Kasten
1463ea38ee7742e799b23bd8675f5801ef72f94de0f4Glenn Kasten    // If the track is invalid at this point, attempt to restore it. and try the
1464ea38ee7742e799b23bd8675f5801ef72f94de0f4Glenn Kasten    // allocation one more time.
14650e48d25606c82def035ad10a5b3923767a765cddAndy Hung    if (cblk->mFlags & CBLK_INVALID) {
1466ea38ee7742e799b23bd8675f5801ef72f94de0f4Glenn Kasten        result = restoreTrack_l("allocateTimedBuffer");
1467ea38ee7742e799b23bd8675f5801ef72f94de0f4Glenn Kasten
1468ea38ee7742e799b23bd8675f5801ef72f94de0f4Glenn Kasten        if (result == NO_ERROR) {
1469ea38ee7742e799b23bd8675f5801ef72f94de0f4Glenn Kasten            result = mAudioTrack->allocateTimedBuffer(size, buffer);
1470ea38ee7742e799b23bd8675f5801ef72f94de0f4Glenn Kasten        }
1471ea38ee7742e799b23bd8675f5801ef72f94de0f4Glenn Kasten    }
1472ea38ee7742e799b23bd8675f5801ef72f94de0f4Glenn Kasten
1473ea38ee7742e799b23bd8675f5801ef72f94de0f4Glenn Kasten    return result;
14747fd0422fbd17af3b24eb04421d37fce50f3826e2Glenn Kasten}
14757fd0422fbd17af3b24eb04421d37fce50f3826e2Glenn Kasten
1476ea38ee7742e799b23bd8675f5801ef72f94de0f4Glenn Kastenstatus_t TimedAudioTrack::queueTimedBuffer(const sp<IMemory>& buffer,
1477ea38ee7742e799b23bd8675f5801ef72f94de0f4Glenn Kasten                                           int64_t pts)
1478ea38ee7742e799b23bd8675f5801ef72f94de0f4Glenn Kasten{
1479ea38ee7742e799b23bd8675f5801ef72f94de0f4Glenn Kasten    status_t status = mAudioTrack->queueTimedBuffer(buffer, pts);
1480ea38ee7742e799b23bd8675f5801ef72f94de0f4Glenn Kasten    {
14817fd0422fbd17af3b24eb04421d37fce50f3826e2Glenn Kasten        AutoMutex lock(mLock);
1482ea38ee7742e799b23bd8675f5801ef72f94de0f4Glenn Kasten        audio_track_cblk_t* cblk = mCblk;
14837fd0422fbd17af3b24eb04421d37fce50f3826e2Glenn Kasten        // restart track if it was disabled by audioflinger due to previous underrun
14840e48d25606c82def035ad10a5b3923767a765cddAndy Hung        if (buffer->size() != 0 && status == NO_ERROR &&
14850e48d25606c82def035ad10a5b3923767a765cddAndy Hung                (mState == STATE_ACTIVE) && (cblk->mFlags & CBLK_DISABLED)) {
1486b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald            android_atomic_and(~CBLK_DISABLED, &cblk->mFlags);
148738e905b3cbba4da443d799b16999989781afc6d8Glenn Kasten            ALOGW("queueTimedBuffer() track %p disabled, restarting", this);
148838e905b3cbba4da443d799b16999989781afc6d8Glenn Kasten            // FIXME ignoring status
14899f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            mAudioTrack->start();
14909f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        }
14919f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
14929f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    return status;
14939f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten}
14949f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
14959f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kastenstatus_t TimedAudioTrack::setMediaTimeTransform(const LinearTransform& xform,
1496363fb75db26698cbb50065506e0c80b61d1fbf92Glenn Kasten                                                TargetTimeline target)
1497138d6f9b0b77d94773a8a29d3c5bdb78f38ee142Glenn Kasten{
149834f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent    return mAudioTrack->setMediaTimeTransform(xform, target);
1499363fb75db26698cbb50065506e0c80b61d1fbf92Glenn Kasten}
1500138d6f9b0b77d94773a8a29d3c5bdb78f38ee142Glenn Kasten
1501138d6f9b0b77d94773a8a29d3c5bdb78f38ee142Glenn Kasten// -------------------------------------------------------------------------
1502138d6f9b0b77d94773a8a29d3c5bdb78f38ee142Glenn Kasten
1503138d6f9b0b77d94773a8a29d3c5bdb78f38ee142Glenn Kastennsecs_t AudioTrack::processAudioBuffer()
150434f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent{
150534f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent    // Currently the AudioTrack thread is not created if there are no callbacks.
15062beeb50b1bba9e92f6cacfeca37fe9fa9d36ead1Eric Laurent    // Would it ever make sense to run the thread, even without callbacks?
15078edb8dc44b8a2f81bdb5db645b6b708548771a31Andy Hung    // If so, then replace this by checks at each use for mCbf != NULL.
1508e0fa467e1150c65a7b1b1ed904c579b40f97c9dfGlenn Kasten    LOG_ALWAYS_FATAL_IF(mCblk == NULL);
15099f9e21ed9a342e0ca945818bdc6c0c4fb3bfb9bdAndy Hung
15105f631515d098c29603cda88f7a7e7580a2d55b57Glenn Kasten    mLock.lock();
1511b603744e96b07b1d5bf745bde593fb2c025cefcfGlenn Kasten    if (mAwaitBoost) {
1512093000f7d11839b920e8dfaa42ed1d09f48e24b8Glenn Kasten        mAwaitBoost = false;
1513093000f7d11839b920e8dfaa42ed1d09f48e24b8Glenn Kasten        mLock.unlock();
1514b603744e96b07b1d5bf745bde593fb2c025cefcfGlenn Kasten        static const int32_t kMaxTries = 5;
1515b603744e96b07b1d5bf745bde593fb2c025cefcfGlenn Kasten        int32_t tryCounter = kMaxTries;
1516093000f7d11839b920e8dfaa42ed1d09f48e24b8Glenn Kasten        uint32_t pollUs = 10000;
1517e3aa659e9cee7df5c12a80d285cc29ab3b2cbb39Glenn Kasten        do {
1518d7bd69e4d1e74f25413721804d5290c53ea87f2bAndy Hung            int policy = sched_getscheduler(0);
1519d7bd69e4d1e74f25413721804d5290c53ea87f2bAndy Hung            if (policy == SCHED_FIFO || policy == SCHED_RR) {
1520d7bd69e4d1e74f25413721804d5290c53ea87f2bAndy Hung                break;
1521e3aa659e9cee7df5c12a80d285cc29ab3b2cbb39Glenn Kasten            }
1522363fb75db26698cbb50065506e0c80b61d1fbf92Glenn Kasten            usleep(pollUs);
15239f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            pollUs <<= 1;
1524abdb990953ffe94a9dc544aea0bed17ef7d5f484Andy Hung        } while (tryCounter-- > 0);
15259f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        if (tryCounter < 0) {
1526abdb990953ffe94a9dc544aea0bed17ef7d5f484Andy Hung            ALOGE("did not receive expected priority boost on time");
15279f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        }
15289f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        // Run again immediately
1529e6a9d65845032644b0865b6e3d0b5a820f35d9e4seunghak.han        return 0;
1530e6a9d65845032644b0865b6e3d0b5a820f35d9e4seunghak.han    }
1531e6a9d65845032644b0865b6e3d0b5a820f35d9e4seunghak.han
1532e6a9d65845032644b0865b6e3d0b5a820f35d9e4seunghak.han    // Can only reference mCblk while locked
1533e6a9d65845032644b0865b6e3d0b5a820f35d9e4seunghak.han    int32_t flags = android_atomic_and(
1534e3aa659e9cee7df5c12a80d285cc29ab3b2cbb39Glenn Kasten        ~(CBLK_UNDERRUN | CBLK_LOOP_CYCLE | CBLK_LOOP_FINAL | CBLK_BUFFER_END), &mCblk->mFlags);
15355a8a95de6dad1a3bcf3da5a37b35766e89086e13Ricardo Garcia
15365a8a95de6dad1a3bcf3da5a37b35766e89086e13Ricardo Garcia    // Check for track invalidation
15375a8a95de6dad1a3bcf3da5a37b35766e89086e13Ricardo Garcia    if (flags & CBLK_INVALID) {
153826145643ce22d797b3b1675c82c47a2d8c79ecaaAndy Hung        // for offloaded tracks restoreTrack_l() will just update the sequence and clear
15395a8a95de6dad1a3bcf3da5a37b35766e89086e13Ricardo Garcia        // AudioSystem cache. We should not exit here but after calling the callback so
15405a8a95de6dad1a3bcf3da5a37b35766e89086e13Ricardo Garcia        // that the upper layers can recreate the track
15415a8a95de6dad1a3bcf3da5a37b35766e89086e13Ricardo Garcia        if (!isOffloadedOrDirect_l() || (mSequence == mObservedSequence)) {
15425a8a95de6dad1a3bcf3da5a37b35766e89086e13Ricardo Garcia            status_t status = restoreTrack_l("processAudioBuffer");
15435a8a95de6dad1a3bcf3da5a37b35766e89086e13Ricardo Garcia            mLock.unlock();
15449f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            // Run again immediately, but with a new IAudioTrack
15459f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            return 0;
15469f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        }
1547f888020c6e2735624f2b2a30e72aca24e17b8b4dMarco Nelissen    }
1548e3aa659e9cee7df5c12a80d285cc29ab3b2cbb39Glenn Kasten
1549296fb13dd9b5e90d6a05cce897c3b1e7914a478aEric Laurent    bool waitStreamEnd = mState == STATE_STOPPING;
1550296fb13dd9b5e90d6a05cce897c3b1e7914a478aEric Laurent    bool active = mState == STATE_ACTIVE;
1551296fb13dd9b5e90d6a05cce897c3b1e7914a478aEric Laurent
1552296fb13dd9b5e90d6a05cce897c3b1e7914a478aEric Laurent    // Manage underrun callback, must be done under lock to avoid race with releaseBuffer()
155334f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent    bool newUnderrun = false;
155438e905b3cbba4da443d799b16999989781afc6d8Glenn Kasten    if (flags & CBLK_UNDERRUN) {
155538e905b3cbba4da443d799b16999989781afc6d8Glenn Kasten#if 0
155638e905b3cbba4da443d799b16999989781afc6d8Glenn Kasten        // Currently in shared buffer mode, when the server reaches the end of buffer,
1557d848eb48c121c119e8ba7583efc75415fe102570Glenn Kasten        // the track stays active in continuous underrun state.  It's up to the application
155838e905b3cbba4da443d799b16999989781afc6d8Glenn Kasten        // to pause or stop the track, or set the position to a new offset within buffer.
155938e905b3cbba4da443d799b16999989781afc6d8Glenn Kasten        // This was some experimental code to auto-pause on underrun.   Keeping it here
156038e905b3cbba4da443d799b16999989781afc6d8Glenn Kasten        // in "if 0" so we can re-visit this if we add a real sequencer for shared memory content.
156138e905b3cbba4da443d799b16999989781afc6d8Glenn Kasten        if (mTransfer == TRANSFER_SHARED) {
156234f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent            mState = STATE_PAUSED;
156334f1d8ecd23169a5f299937e3aaf1bd7937578a0Eric Laurent            active = false;
1564b46f394a85d704dd05287cf9bb77cf86e3c02a38Glenn Kasten        }
156589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project#endif
15669f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        if (!mInUnderrun) {
1567551b5355d34aa42890811fc3606d3b63429296cdGlenn Kasten            mInUnderrun = true;
1568551b5355d34aa42890811fc3606d3b63429296cdGlenn Kasten            newUnderrun = true;
1569551b5355d34aa42890811fc3606d3b63429296cdGlenn Kasten        }
15709f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
15719f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
15729f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    // Get current position of server
15739f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    size_t position = updateAndGetPosition_l();
15749f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
15759f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    // Manage marker callback
1576551b5355d34aa42890811fc3606d3b63429296cdGlenn Kasten    bool markerReached = false;
1577551b5355d34aa42890811fc3606d3b63429296cdGlenn Kasten    size_t markerPosition = mMarkerPosition;
1578551b5355d34aa42890811fc3606d3b63429296cdGlenn Kasten    // FIXME fails for wraparound, need 64 bits
15799f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (!mMarkerReached && (markerPosition > 0) && (position >= markerPosition)) {
15809f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        mMarkerReached = markerReached = true;
15819f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
15829f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
1583df576995a5aad3428aeeef765387d650945c161dEric Laurent    // Determine number of new position callback(s) that will be needed, while locked
15849f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    size_t newPosCount = 0;
15859f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    size_t newPosition = mNewPosition;
15869f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    size_t updatePeriod = mUpdatePeriod;
15879f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    // FIXME fails for wraparound, need 64 bits
15889f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (updatePeriod > 0 && position >= newPosition) {
15899f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        newPosCount = ((position - newPosition) / updatePeriod) + 1;
15909f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        mNewPosition += updatePeriod * newPosCount;
15919f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
15929f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
15939f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    // Cache other fields that will be needed soon
15949f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    uint32_t loopPeriod = mLoopPeriod;
15959f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    uint32_t sampleRate = mSampleRate;
15969f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    uint32_t notificationFrames = mNotificationFramesAct;
1597b46f394a85d704dd05287cf9bb77cf86e3c02a38Glenn Kasten    if (mRefreshRemaining) {
15989f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        mRefreshRemaining = false;
15999f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        mRemainingFrames = notificationFrames;
16009f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        mRetryOnPartialBuffer = false;
16019f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
16029f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    size_t misalignment = mProxy->getMisalignment();
16039f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    uint32_t sequence = mSequence;
16049f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    sp<AudioTrackClientProxy> proxy = mProxy;
16059f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
1606e3aa659e9cee7df5c12a80d285cc29ab3b2cbb39Glenn Kasten    // These fields don't need to be cached, because they are assigned only by set():
16079f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    //     mTransfer, mCbf, mUserData, mFormat, mFrameSize, mFrameSizeAF, mFlags
16089f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    // mFlags is also assigned by createTrack_l(), but not the bit we care about.
160989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
16109f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    mLock.unlock();
16119f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
161289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    if (waitStreamEnd) {
16139f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        struct timespec timeout;
16149f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        timeout.tv_sec = WAIT_STREAM_END_TIMEOUT_SEC;
16159f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        timeout.tv_nsec = 0;
16169f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
16179f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        status_t status = proxy->waitStreamEndDone(&timeout);
161889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        switch (status) {
16199f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        case NO_ERROR:
16209f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        case DEAD_OBJECT:
16211703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent        case TIMED_OUT:
16229f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            mCbf(EVENT_STREAM_END, mUserData, NULL);
16239f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            {
16249f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten                AutoMutex lock(mLock);
16259f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten                // The previously assigned value of waitStreamEnd is no longer valid,
16269f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten                // since the mutex has been unlocked and either the callback handler
16279f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten                // or another thread could have re-started the AudioTrack during that time.
16289f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten                waitStreamEnd = mState == STATE_STOPPING;
1629b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald                if (waitStreamEnd) {
1630b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald                    mState = STATE_STOPPED;
1631b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald                    mReleased = 0;
16329f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten                }
163389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project            }
163489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project            if (waitStreamEnd && status != DEAD_OBJECT) {
16359f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten               return NS_INACTIVE;
16369f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            }
1637c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent            break;
16384d231dc0ee34380956c71cbe18a750e487a69601Eric Laurent        }
16394d231dc0ee34380956c71cbe18a750e487a69601Eric Laurent        return 0;
16404d231dc0ee34380956c71cbe18a750e487a69601Eric Laurent    }
16414d231dc0ee34380956c71cbe18a750e487a69601Eric Laurent
16429f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    // perform callbacks while unlocked
16439f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (newUnderrun) {
16449f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        mCbf(EVENT_UNDERRUN, mUserData, NULL);
16459f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
1646b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald    // FIXME we will miss loops if loop cycle was signaled several times since last call
1647b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald    //       to processAudioBuffer()
1648b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald    if (flags & (CBLK_LOOP_CYCLE | CBLK_LOOP_FINAL)) {
1649b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald        mCbf(EVENT_LOOP_END, mUserData, NULL);
1650b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald    }
1651b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald    if (flags & CBLK_BUFFER_END) {
1652b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald        mCbf(EVENT_BUFFER_END, mUserData, NULL);
1653b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald    }
16549f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (markerReached) {
16559f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        mCbf(EVENT_MARKER, mUserData, &markerPosition);
16569f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
165789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    while (newPosCount > 0) {
165889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        size_t temp = newPosition;
16599f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        mCbf(EVENT_NEW_POS, mUserData, &temp);
1660c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent        newPosition += updatePeriod;
16619f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        newPosCount--;
16629f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
16639f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
16644d231dc0ee34380956c71cbe18a750e487a69601Eric Laurent    if (mObservedSequence != sequence) {
166589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        mObservedSequence = sequence;
16669f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        mCbf(EVENT_NEW_IAUDIOTRACK, mUserData, NULL);
1667abdb990953ffe94a9dc544aea0bed17ef7d5f484Andy Hung        // for offloaded tracks, just wait for the upper layers to recreate the track
16689f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        if (isOffloadedOrDirect()) {
16699f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            return NS_INACTIVE;
16709f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        }
167189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
16729f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
167389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    // if inactive, then don't run me again until re-started
167489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    if (!active) {
167554a8a456c2b4b382b3ffe3d99e40703df79c0717Glenn Kasten        return NS_INACTIVE;
167689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
16773f02be2ceeaa4b67dc0b1a81aebcfa049276fad8Glenn Kasten
16789f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    // Compute the estimated time until the next timed event (position, markers, loops)
16799f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    // FIXME only for non-compressed audio
16809f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    uint32_t minFrames = ~0;
16819f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (!markerReached && position < markerPosition) {
1682abdb990953ffe94a9dc544aea0bed17ef7d5f484Andy Hung        minFrames = markerPosition - position;
16839f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
16849f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (loopPeriod > 0 && loopPeriod < minFrames) {
16859f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        minFrames = loopPeriod;
16869f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
16879f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (updatePeriod > 0 && updatePeriod < minFrames) {
16889f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        minFrames = updatePeriod;
16899f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
1690e3aa659e9cee7df5c12a80d285cc29ab3b2cbb39Glenn Kasten
16911703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent    // If > 0, poll periodically to recover from a stuck server.  A good value is 2.
1692200092b7f21d2b98f30b800e79d152636f9ba225Glenn Kasten    static const uint32_t kPoll = 0;
16939f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (kPoll > 0 && mTransfer == TRANSFER_CALLBACK && kPoll * notificationFrames < minFrames) {
16949f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        minFrames = kPoll * notificationFrames;
16959f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
16969f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
16974d231dc0ee34380956c71cbe18a750e487a69601Eric Laurent    // Convert frame units to time units
16984d231dc0ee34380956c71cbe18a750e487a69601Eric Laurent    nsecs_t ns = NS_WHENEVER;
16994d231dc0ee34380956c71cbe18a750e487a69601Eric Laurent    if (minFrames != (uint32_t) ~0) {
17004d231dc0ee34380956c71cbe18a750e487a69601Eric Laurent        // This "fudge factor" avoids soaking CPU, and compensates for late progress by server
17014d231dc0ee34380956c71cbe18a750e487a69601Eric Laurent        static const nsecs_t kFudgeNs = 10000000LL; // 10 ms
17024d231dc0ee34380956c71cbe18a750e487a69601Eric Laurent        ns = ((minFrames * 1000000000LL) / sampleRate) + kFudgeNs;
17034d231dc0ee34380956c71cbe18a750e487a69601Eric Laurent    }
17044d231dc0ee34380956c71cbe18a750e487a69601Eric Laurent
17054d231dc0ee34380956c71cbe18a750e487a69601Eric Laurent    // If not supplying data by EVENT_MORE_DATA, then we're done
17064d231dc0ee34380956c71cbe18a750e487a69601Eric Laurent    if (mTransfer != TRANSFER_CALLBACK) {
1707df839841d2db4cb8e2acb10205b3942622b3e7a2Eric Laurent        return ns;
170889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
170989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
171089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    struct timespec timeout;
171189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    const struct timespec *requested = &ClientProxy::kForever;
1712720ad9ddb2ac6b55b0dfbfcd2d8360151d8ac427Jean-Michel Trivi    if (ns != NS_WHENEVER) {
171389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        timeout.tv_sec = ns / 1000000000LL;
1714d79072e9dff59f767cce2cda1caab80ce5a0815bGlenn Kasten        timeout.tv_nsec = ns % 1000000000LL;
1715d65d73c4ae74d084751b417615a78cbe7a51372aGlenn Kasten        ALOGV("timeout %ld.%03d", timeout.tv_sec, (int) timeout.tv_nsec / 1000000);
1716d65d73c4ae74d084751b417615a78cbe7a51372aGlenn Kasten        requested = &timeout;
171789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
1718ab5cdbaf65ca509681d2726aacdf3ac8bfb6b3faEric Laurent
1719ab5cdbaf65ca509681d2726aacdf3ac8bfb6b3faEric Laurent    while (mRemainingFrames > 0) {
1720ab5cdbaf65ca509681d2726aacdf3ac8bfb6b3faEric Laurent
1721ab5cdbaf65ca509681d2726aacdf3ac8bfb6b3faEric Laurent        Buffer audioBuffer;
1722ab5cdbaf65ca509681d2726aacdf3ac8bfb6b3faEric Laurent        audioBuffer.frameCount = mRemainingFrames;
1723ab5cdbaf65ca509681d2726aacdf3ac8bfb6b3faEric Laurent        size_t nonContig;
1724ab5cdbaf65ca509681d2726aacdf3ac8bfb6b3faEric Laurent        status_t err = obtainBuffer(&audioBuffer, requested, NULL, &nonContig);
1725ab5cdbaf65ca509681d2726aacdf3ac8bfb6b3faEric Laurent        LOG_ALWAYS_FATAL_IF((err != NO_ERROR) != (audioBuffer.frameCount == 0),
1726ab5cdbaf65ca509681d2726aacdf3ac8bfb6b3faEric Laurent                "obtainBuffer() err=%d frameCount=%zu", err, audioBuffer.frameCount);
1727ab5cdbaf65ca509681d2726aacdf3ac8bfb6b3faEric Laurent        requested = &ClientProxy::kNonBlocking;
17289f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        size_t avail = audioBuffer.frameCount + nonContig;
172999e53b86eebb605b70dd7591b89bf61a9414ed0eGlenn Kasten        ALOGV("obtainBuffer(%u) returned %zu = %zu + %zu err %d",
173099e53b86eebb605b70dd7591b89bf61a9414ed0eGlenn Kasten                mRemainingFrames, avail, audioBuffer.frameCount, nonContig, err);
1731377b2ec9a2885f9b6405b07ba900a9e3f4349c38Kévin PETIT        if (err != NO_ERROR) {
173289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project            if (err == TIMED_OUT || err == WOULD_BLOCK || err == -EINTR ||
173389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project                    (isOffloaded() && (err == DEAD_OBJECT))) {
173489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project                return 0;
17359f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            }
173689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project            ALOGE("Error %d obtaining an audio buffer, giving up.", err);
173789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project            return NS_NEVER;
17389f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        }
17399f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
1740c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent        if (mRetryOnPartialBuffer && !isOffloaded()) {
1741720ad9ddb2ac6b55b0dfbfcd2d8360151d8ac427Jean-Michel Trivi            mRetryOnPartialBuffer = false;
1742720ad9ddb2ac6b55b0dfbfcd2d8360151d8ac427Jean-Michel Trivi            if (avail < mRemainingFrames) {
174389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project                int64_t myns = ((mRemainingFrames - avail) * 1100000000LL) / sampleRate;
17449f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten                if (ns < 0 || myns < ns) {
174589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project                    ns = myns;
1746d65d73c4ae74d084751b417615a78cbe7a51372aGlenn Kasten                }
174789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project                return ns;
174889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project            }
174989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        }
1750ae4b879d04c4b07c62241a8f507c8dce11e628e4Glenn Kasten
1751abdb990953ffe94a9dc544aea0bed17ef7d5f484Andy Hung        // Divide buffer size by 2 to take into account the expansion
17529f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        // due to 8 to 16 bit conversion: the callback must fill only half
175389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        // of the destination buffer
175489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        if (mFormat == AUDIO_FORMAT_PCM_8_BIT && !(mFlags & AUDIO_OUTPUT_FLAG_DIRECT)) {
175589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project            audioBuffer.size >>= 1;
175689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        }
17579f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
175889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        size_t reqSize = audioBuffer.size;
1759ea2b9c07b34079f0dbd8610a511e006e69a15adcAndy Hung        mCbf(EVENT_MORE_DATA, mUserData, &audioBuffer);
1760ea2b9c07b34079f0dbd8610a511e006e69a15adcAndy Hung        size_t writtenSize = audioBuffer.size;
1761ea2b9c07b34079f0dbd8610a511e006e69a15adcAndy Hung
176289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        // Sanity check on returned size
176389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        if (ssize_t(writtenSize) < 0 || writtenSize > reqSize) {
176489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project            ALOGE("EVENT_MORE_DATA requested %zu bytes but callback returned %zd bytes",
176589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project                    reqSize, ssize_t(writtenSize));
176689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project            return NS_NEVER;
17677c7be1e05634d96d08210efb4bdeb012ffba440dGlenn Kasten        }
176889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
1769fb1fdc9d6603aa228362e7349451f6455c9849c2Glenn Kasten        if (writtenSize == 0) {
1770fb1fdc9d6603aa228362e7349451f6455c9849c2Glenn Kasten            // The callback is done filling buffers
1771fb1fdc9d6603aa228362e7349451f6455c9849c2Glenn Kasten            // Keep this thread going to handle timed events and
1772fb1fdc9d6603aa228362e7349451f6455c9849c2Glenn Kasten            // still try to get more data in intervals of WAIT_PERIOD_MS
1773fb1fdc9d6603aa228362e7349451f6455c9849c2Glenn Kasten            // but don't just loop and block the CPU, so wait
17741703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent            return WAIT_PERIOD_MS * 1000000LL;
1775a07f17ca46db04c9d5d9e7d6b2878db59ca2b9eaGlenn Kasten        }
1776a07f17ca46db04c9d5d9e7d6b2878db59ca2b9eaGlenn Kasten
1777a07f17ca46db04c9d5d9e7d6b2878db59ca2b9eaGlenn Kasten        if (mFormat == AUDIO_FORMAT_PCM_8_BIT && !(mFlags & AUDIO_OUTPUT_FLAG_DIRECT)) {
1778a07f17ca46db04c9d5d9e7d6b2878db59ca2b9eaGlenn Kasten            // 8 to 16 bit conversion, note that source and destination are the same address
1779a07f17ca46db04c9d5d9e7d6b2878db59ca2b9eaGlenn Kasten            memcpy_to_i16_from_u8(audioBuffer.i16, (const uint8_t *) audioBuffer.i8, writtenSize);
1780a07f17ca46db04c9d5d9e7d6b2878db59ca2b9eaGlenn Kasten            audioBuffer.size <<= 1;
1781a07f17ca46db04c9d5d9e7d6b2878db59ca2b9eaGlenn Kasten        }
1782a07f17ca46db04c9d5d9e7d6b2878db59ca2b9eaGlenn Kasten
1783a07f17ca46db04c9d5d9e7d6b2878db59ca2b9eaGlenn Kasten        size_t releasedFrames = audioBuffer.size / mFrameSizeAF;
1784a07f17ca46db04c9d5d9e7d6b2878db59ca2b9eaGlenn Kasten        audioBuffer.frameCount = releasedFrames;
1785a07f17ca46db04c9d5d9e7d6b2878db59ca2b9eaGlenn Kasten        mRemainingFrames -= releasedFrames;
1786a07f17ca46db04c9d5d9e7d6b2878db59ca2b9eaGlenn Kasten        if (misalignment >= releasedFrames) {
1787a07f17ca46db04c9d5d9e7d6b2878db59ca2b9eaGlenn Kasten            misalignment -= releasedFrames;
1788a07f17ca46db04c9d5d9e7d6b2878db59ca2b9eaGlenn Kasten        } else {
1789a07f17ca46db04c9d5d9e7d6b2878db59ca2b9eaGlenn Kasten            misalignment = 0;
1790a07f17ca46db04c9d5d9e7d6b2878db59ca2b9eaGlenn Kasten        }
1791a07f17ca46db04c9d5d9e7d6b2878db59ca2b9eaGlenn Kasten
1792b0dfd4613225a3b2a17bdf8d85e89a4b04d65ef3Glenn Kasten        releaseBuffer(&audioBuffer);
1793b0dfd4613225a3b2a17bdf8d85e89a4b04d65ef3Glenn Kasten
1794a07f17ca46db04c9d5d9e7d6b2878db59ca2b9eaGlenn Kasten        // FIXME here is where we would repeat EVENT_MORE_DATA again on same advanced buffer
17951703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent        // if callback doesn't like to accept the full chunk
17969f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        if (writtenSize < reqSize) {
17979f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            continue;
179896f60d8f04432a1ed503b3e24d5736d28c63c9a2Glenn Kasten        }
1799a47f3165f53c8e8fb8907a94de7417e2c3047eebGlenn Kasten
18009f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        // There could be enough non-contiguous frames available to satisfy the remaining request
18019f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        if (mRemainingFrames <= nonContig) {
1802b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald            continue;
1803b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald        }
1804b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald
1805ab5cdbaf65ca509681d2726aacdf3ac8bfb6b3faEric Laurent#if 0
1806f1063e2659cad01ec334a265c31734c63c319cc4Lajos Molnar        // This heuristic tries to collapse a series of EVENT_MORE_DATA that would total to a
1807f1063e2659cad01ec334a265c31734c63c319cc4Lajos Molnar        // sum <= notificationFrames.  It replaces that series by at most two EVENT_MORE_DATA
180853c3b5fc1afe162a8669cb3d27d6bb14e1847e39Andy Hung        // that total to a sum == notificationFrames.
180953c3b5fc1afe162a8669cb3d27d6bb14e1847e39Andy Hung        if (0 < misalignment && misalignment <= mRemainingFrames) {
1810b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald            mRemainingFrames = misalignment;
181189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project            return (mRemainingFrames * 1100000000LL) / sampleRate;
1812c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent        }
1813b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald#endif
18149f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
181589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    }
18169f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    mRemainingFrames = notificationFrames;
18179f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    mRetryOnPartialBuffer = true;
18189f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
18199f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    // A lot has transpired since ns was calculated, so run again immediately and re-calculate
18209f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    return 0;
18219f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten}
18229f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
18239f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kastenstatus_t AudioTrack::restoreTrack_l(const char *from)
18249f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten{
18259f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    ALOGW("dead IAudioTrack, %s, creating a new one from %s()",
18269f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten          isOffloadedOrDirect_l() ? "Offloaded or Direct" : "PCM", from);
18279f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    ++mSequence;
18289f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    status_t result;
18299f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
18309f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    // refresh the audio configuration cache in this process to make sure we get new
18319f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    // output parameters and new IAudioFlinger in createTrack_l()
18329f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    AudioSystem::clearAudioConfigCache();
18339f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
183489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    if (isOffloadedOrDirect_l()) {
183589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        // FIXME re-creation of offloaded tracks is not yet implemented
18369f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        return DEAD_OBJECT;
183790e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung    }
18389f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
183989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    // save the old static buffer position
18409f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    size_t bufferPosition = mStaticProxy != NULL ? mStaticProxy->getBufferPosition() : 0;
184190e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung
184290e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung    // If a new IAudioTrack is successfully created, createTrack_l() will modify the
184390e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung    // following member variables: mAudioTrack, mCblkMemory and mCblk.
18449f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    // It will also delete the strong references on previous IAudioTrack and IMemory.
18459f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    // If a new IAudioTrack cannot be created, the previous (dead) instance will be left intact.
18469f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    result = createTrack_l();
18479f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
18489f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    // take the frames that will be lost by track recreation into account in saved position
184990e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung    (void) updateAndGetPosition_l();
185090e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung    mPosition = mReleased;
18519f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
18529f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (result == NO_ERROR) {
185390e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung        // continue playback from last known position, but
18549f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        // don't attempt to restore loop after invalidation; it's difficult and not worthwhile
18559f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        if (mStaticProxy != NULL) {
18569f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            mLoopPeriod = 0;
18579f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            mStaticProxy->setLoop(bufferPosition, mFrameCount, 0);
18589f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        }
18595a8a95de6dad1a3bcf3da5a37b35766e89086e13Ricardo Garcia        // FIXME How do we simulate the fact that all frames present in the buffer at the time of
1860a7f03353d5f172016f324e2a01f301cca6794152Andy Hung        //       track destruction have been played? This is critical for SoundPool implementation
18619f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        //       This must be broken, and needs to be tested/debugged.
18629f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten#if 0
18639f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        // restore write index and set other indexes to reflect empty buffer status
18649f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        if (!strcmp(from, "start")) {
18659f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            // Make sure that a client relying on callback events indicating underrun or
18669f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            // the actual amount of audio frames played (e.g SoundPool) receives them.
1867b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald            if (mSharedBuffer == 0) {
186896f04886d1c1bfbc422e2be033ea66be83e42441Glenn Kasten                // restart playback even if buffer is not completely filled.
18699f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten                android_atomic_or(CBLK_FORCEREADY, &mCblk->mFlags);
187053c3b5fc1afe162a8669cb3d27d6bb14e1847e39Andy Hung            }
187153c3b5fc1afe162a8669cb3d27d6bb14e1847e39Andy Hung        }
187253c3b5fc1afe162a8669cb3d27d6bb14e1847e39Andy Hung#endif
187353c3b5fc1afe162a8669cb3d27d6bb14e1847e39Andy Hung        if (mState == STATE_ACTIVE) {
187453c3b5fc1afe162a8669cb3d27d6bb14e1847e39Andy Hung            result = mAudioTrack->start();
187553c3b5fc1afe162a8669cb3d27d6bb14e1847e39Andy Hung        }
187653c3b5fc1afe162a8669cb3d27d6bb14e1847e39Andy Hung    }
187753c3b5fc1afe162a8669cb3d27d6bb14e1847e39Andy Hung    if (result != NO_ERROR) {
187853c3b5fc1afe162a8669cb3d27d6bb14e1847e39Andy Hung        ALOGW("restoreTrack_l() failed status %d", result);
187953c3b5fc1afe162a8669cb3d27d6bb14e1847e39Andy Hung        mState = STATE_STOPPED;
188053c3b5fc1afe162a8669cb3d27d6bb14e1847e39Andy Hung        mReleased = 0;
188153c3b5fc1afe162a8669cb3d27d6bb14e1847e39Andy Hung    }
188253c3b5fc1afe162a8669cb3d27d6bb14e1847e39Andy Hung
188353c3b5fc1afe162a8669cb3d27d6bb14e1847e39Andy Hung    return result;
188453c3b5fc1afe162a8669cb3d27d6bb14e1847e39Andy Hung}
188553c3b5fc1afe162a8669cb3d27d6bb14e1847e39Andy Hung
188653c3b5fc1afe162a8669cb3d27d6bb14e1847e39Andy Hunguint32_t AudioTrack::updateAndGetPosition_l()
188753c3b5fc1afe162a8669cb3d27d6bb14e1847e39Andy Hung{
188853c3b5fc1afe162a8669cb3d27d6bb14e1847e39Andy Hung    // This is the sole place to read server consumed frames
188953c3b5fc1afe162a8669cb3d27d6bb14e1847e39Andy Hung    uint32_t newServer = mProxy->getPosition();
189053c3b5fc1afe162a8669cb3d27d6bb14e1847e39Andy Hung    int32_t delta = newServer - mServer;
189153c3b5fc1afe162a8669cb3d27d6bb14e1847e39Andy Hung    mServer = newServer;
18929f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    // TODO There is controversy about whether there can be "negative jitter" in server position.
1893abdb990953ffe94a9dc544aea0bed17ef7d5f484Andy Hung    //      This should be investigated further, and if possible, it should be addressed.
18949f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    //      A more definite failure mode is infrequent polling by client.
18959f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    //      One could call (void)getPosition_l() in releaseBuffer(),
18969f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    //      so mReleased and mPosition are always lock-step as best possible.
18979f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    //      That should ensure delta never goes negative for infrequent polling
1898a7f03353d5f172016f324e2a01f301cca6794152Andy Hung    //      unless the server has more than 2^31 frames in its buffer,
1899a7f03353d5f172016f324e2a01f301cca6794152Andy Hung    //      in which case the use of uint32_t for these counters has bigger issues.
1900a7f03353d5f172016f324e2a01f301cca6794152Andy Hung    if (delta < 0) {
1901b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald        ALOGE("detected illegal retrograde motion by the server: mServer advanced by %d", delta);
1902a7f03353d5f172016f324e2a01f301cca6794152Andy Hung        delta = 0;
1903a7f03353d5f172016f324e2a01f301cca6794152Andy Hung    }
1904a7f03353d5f172016f324e2a01f301cca6794152Andy Hung    return mPosition += (uint32_t) delta;
1905a7f03353d5f172016f324e2a01f301cca6794152Andy Hung}
1906b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald
1907b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgeraldstatus_t AudioTrack::setParameters(const String8& keyValuePairs)
1908b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald{
1909b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald    AutoMutex lock(mLock);
191096f04886d1c1bfbc422e2be033ea66be83e42441Glenn Kasten    return mAudioTrack->setParameters(keyValuePairs);
1911b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald}
1912b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald
1913b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgeraldstatus_t AudioTrack::getTimestamp(AudioTimestamp& timestamp)
1914b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald{
191539609a0a6d95d003b0f237e6c139b070b4df7071Andy Hung    AutoMutex lock(mLock);
191639609a0a6d95d003b0f237e6c139b070b4df7071Andy Hung    // FIXME not implemented for fast tracks; should use proxy and SSQ
191739609a0a6d95d003b0f237e6c139b070b4df7071Andy Hung    if (mFlags & AUDIO_OUTPUT_FLAG_FAST) {
191839609a0a6d95d003b0f237e6c139b070b4df7071Andy Hung        return INVALID_OPERATION;
191939609a0a6d95d003b0f237e6c139b070b4df7071Andy Hung    }
192096f04886d1c1bfbc422e2be033ea66be83e42441Glenn Kasten
192196f04886d1c1bfbc422e2be033ea66be83e42441Glenn Kasten    switch (mState) {
192296f04886d1c1bfbc422e2be033ea66be83e42441Glenn Kasten    case STATE_ACTIVE:
192396f04886d1c1bfbc422e2be033ea66be83e42441Glenn Kasten    case STATE_PAUSED:
192496f04886d1c1bfbc422e2be033ea66be83e42441Glenn Kasten        break; // handle below
192596f04886d1c1bfbc422e2be033ea66be83e42441Glenn Kasten    case STATE_FLUSHED:
192696f04886d1c1bfbc422e2be033ea66be83e42441Glenn Kasten    case STATE_STOPPED:
192796f04886d1c1bfbc422e2be033ea66be83e42441Glenn Kasten        return WOULD_BLOCK;
1928c2813e568aa476e03d159529c0af28c99536db8dAndy Hung    case STATE_STOPPING:
1929b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald    case STATE_PAUSED_STOPPING:
1930b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald        if (!isOffloaded_l()) {
193196f04886d1c1bfbc422e2be033ea66be83e42441Glenn Kasten            return INVALID_OPERATION;
193296f04886d1c1bfbc422e2be033ea66be83e42441Glenn Kasten        }
193396f04886d1c1bfbc422e2be033ea66be83e42441Glenn Kasten        break; // offloaded tracks handled below
193496f04886d1c1bfbc422e2be033ea66be83e42441Glenn Kasten    default:
1935b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald        LOG_ALWAYS_FATAL("Invalid mState in getTimestamp(): %d", mState);
193696f04886d1c1bfbc422e2be033ea66be83e42441Glenn Kasten        break;
1937b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald    }
1938b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald
19399f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    // The presented frame count must always lag behind the consumed frame count.
19409f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    // To avoid a race, read the presented frames first.  This ensures that presented <= consumed.
19419f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    status_t status = mAudioTrack->getTimestamp(timestamp);
19429f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (status != NO_ERROR) {
194353c3b5fc1afe162a8669cb3d27d6bb14e1847e39Andy Hung        ALOGV_IF(status != WOULD_BLOCK, "getTimestamp error:%#x", status);
19449f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        return status;
194553c3b5fc1afe162a8669cb3d27d6bb14e1847e39Andy Hung    }
19469f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (isOffloadedOrDirect_l()) {
19479f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        if (isOffloaded_l() && (mState == STATE_PAUSED || mState == STATE_PAUSED_STOPPING)) {
19489f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            // use cached paused position in case another offloaded track is running.
19499f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            timestamp.mPosition = mPausedPosition;
19509f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            clock_gettime(CLOCK_MONOTONIC, &timestamp.mTime);
19519f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            return NO_ERROR;
19529f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        }
19539f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
195490e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung        // Check whether a pending flush or stop has completed, as those commands may
19559f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        // be asynchronous or return near finish.
19569f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        if (mStartUs != 0 && mSampleRate != 0) {
19579f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            static const int kTimeJitterUs = 100000; // 100 ms
19589f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            static const int k1SecUs = 1000000;
1959b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald
19609f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            const int64_t timeNow = getNowUs();
19619f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
19629f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            if (timeNow < mStartUs + k1SecUs) { // within first second of starting
1963b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald                const int64_t timestampTimeUs = convertTimespecToUs(timestamp.mTime);
1964ab5cdbaf65ca509681d2726aacdf3ac8bfb6b3faEric Laurent                if (timestampTimeUs < mStartUs) {
1965b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald                    return WOULD_BLOCK;  // stale timestamp time, occurs before start.
1966b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald                }
196789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project                const int64_t deltaTimeUs = timestampTimeUs - mStartUs;
196889fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project                const int64_t deltaPositionByUs = timestamp.mPosition * 1000000LL / mSampleRate;
19699f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
19709f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten                if (deltaPositionByUs > deltaTimeUs + kTimeJitterUs) {
19719f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten                    // Verify that the counter can't count faster than the sample rate
197289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project                    // since the start time.  If greater, then that means we have failed
197389fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project                    // to completely flush or stop the previous playing track.
19749f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten                    ALOGW("incomplete flush or stop:"
19759f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten                            " deltaTimeUs(%lld) deltaPositionUs(%lld) tsmPosition(%u)",
19769f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten                            (long long)deltaTimeUs, (long long)deltaPositionByUs,
19779f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten                            timestamp.mPosition);
197890e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung                    return WOULD_BLOCK;
19799f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten                }
19809f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            }
19812d85f097d653b21d1ff2c34f0b732c674d20ccc2Andy Hung            mStartUs = 0; // no need to check again, start timestamp has either expired or unneeded.
19829f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        }
19839f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    } else {
19842d85f097d653b21d1ff2c34f0b732c674d20ccc2Andy Hung        // Update the mapping between local consumed (mPosition) and server consumed (mServer)
198590e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung        (void) updateAndGetPosition_l();
198689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        // Server consumed (mServer) and presented both use the same server time base,
198789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        // and server consumed is always >= presented.
19889f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        // The delta between these represents the number of frames in the buffer pipeline.
19899f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        // If this delta between these is greater than the client position, it means that
19909f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        // actually presented is still stuck at the starting line (figuratively speaking),
19919f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        // waiting for the first frame to go by.  So we can't report a valid timestamp yet.
19922267ba18d0d2b2d4bd7f5411821ad89ac2659a88Eric Laurent        if ((uint32_t) (mServer - timestamp.mPosition) > mPosition) {
19932267ba18d0d2b2d4bd7f5411821ad89ac2659a88Eric Laurent            return INVALID_OPERATION;
1994a7f03353d5f172016f324e2a01f301cca6794152Andy Hung        }
1995a7f03353d5f172016f324e2a01f301cca6794152Andy Hung        // Convert timestamp position from server time base to client time base.
1996a7f03353d5f172016f324e2a01f301cca6794152Andy Hung        // TODO The following code should work OK now because timestamp.mPosition is 32-bit.
1997a7f03353d5f172016f324e2a01f301cca6794152Andy Hung        // But if we change it to 64-bit then this could fail.
19989f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        // If (mPosition - mServer) can be negative then should use:
19999f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        //   (int32_t)(mPosition - mServer)
20009f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        timestamp.mPosition += mPosition - mServer;
2001a7f03353d5f172016f324e2a01f301cca6794152Andy Hung        // Immediately after a call to getPosition_l(), mPosition and
2002a7f03353d5f172016f324e2a01f301cca6794152Andy Hung        // mServer both represent the same frame position.  mPosition is
2003a7f03353d5f172016f324e2a01f301cca6794152Andy Hung        // in client's point of view, and mServer is in server's point of
2004a7f03353d5f172016f324e2a01f301cca6794152Andy Hung        // view.  So the difference between them is the "fudge factor"
20059f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        // between client and server views due to stop() and/or new
20069f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        // IAudioTrack.  And timestamp.mPosition is initially in server's
20079f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        // point of view, so we need to apply the same fudge factor to it.
20089f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
20099f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    return status;
20109f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten}
201189fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project
2012a7f03353d5f172016f324e2a01f301cca6794152Andy HungString8 AudioTrack::getParameters(const String8& keys)
2013a7f03353d5f172016f324e2a01f301cca6794152Andy Hung{
2014a7f03353d5f172016f324e2a01f301cca6794152Andy Hung    audio_io_handle_t output = getOutput();
2015a7f03353d5f172016f324e2a01f301cca6794152Andy Hung    if (output != AUDIO_IO_HANDLE_NONE) {
2016a7f03353d5f172016f324e2a01f301cca6794152Andy Hung        return AudioSystem::getParameters(output, keys);
2017a7f03353d5f172016f324e2a01f301cca6794152Andy Hung    } else {
2018a7f03353d5f172016f324e2a01f301cca6794152Andy Hung        return String8::empty();
20199f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
20209f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten}
20219f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
20229f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kastenbool AudioTrack::isOffloaded() const
20239f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten{
20249f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    AutoMutex lock(mLock);
20259f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    return isOffloaded_l();
20269f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten}
20279f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
2028ea2b9c07b34079f0dbd8610a511e006e69a15adcAndy Hungbool AudioTrack::isDirect() const
20299f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten{
2030c2f1f07084818942352c6bbfb36af9b6b330eb4eEric Laurent    AutoMutex lock(mLock);
20319f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    return isDirect_l();
20329f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten}
20339f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
20349f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kastenbool AudioTrack::isOffloadedOrDirect() const
20359f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten{
203634fb29696b0f3abf61b10f8d053b1f33d501de0aMark Salyzyn    AutoMutex lock(mLock);
20379f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    return isOffloadedOrDirect_l();
20389f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten}
203934fb29696b0f3abf61b10f8d053b1f33d501de0aMark Salyzyn
2040b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald
20419f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kastenstatus_t AudioTrack::dump(int fd, const Vector<String16>& args __unused) const
2042b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald{
2043b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald
2044606fbc1030d686bf1f8dc03d14a79342aca2ca41Glenn Kasten    const size_t SIZE = 256;
2045606fbc1030d686bf1f8dc03d14a79342aca2ca41Glenn Kasten    char buffer[SIZE];
204689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    String8 result;
20479f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
20489f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    result.append(" AudioTrack::dump\n");
204989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    snprintf(buffer, 255, "  stream type(%d), left - right volume(%f, %f)\n", mStreamType,
20509f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            mVolume[AUDIO_INTERLEAVE_LEFT], mVolume[AUDIO_INTERLEAVE_RIGHT]);
2051fdb3c07db5d44535eb8c3ec46dc78ad8446c01ebPhil Burk    result.append(buffer);
20529f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    snprintf(buffer, 255, "  format(%d), channel count(%d), frame count(%zu)\n", mFormat,
20539f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            mChannelCount, mFrameCount);
2054a7f03353d5f172016f324e2a01f301cca6794152Andy Hung    result.append(buffer);
2055a7f03353d5f172016f324e2a01f301cca6794152Andy Hung    snprintf(buffer, 255, "  sample rate(%u), status(%d)\n", mSampleRate, mStatus);
2056a7f03353d5f172016f324e2a01f301cca6794152Andy Hung    result.append(buffer);
2057a7f03353d5f172016f324e2a01f301cca6794152Andy Hung    snprintf(buffer, 255, "  state(%d), latency (%d)\n", mState, mLatency);
2058a7f03353d5f172016f324e2a01f301cca6794152Andy Hung    result.append(buffer);
2059a7f03353d5f172016f324e2a01f301cca6794152Andy Hung    ::write(fd, result.string(), result.size());
20609f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    return NO_ERROR;
20619f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten}
20629f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
20639f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kastenuint32_t AudioTrack::getUnderrunFrames() const
2064d65d73c4ae74d084751b417615a78cbe7a51372aGlenn Kasten{
206589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    AutoMutex lock(mLock);
206689fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    return mProxy->getUnderrunFrames();
206789fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project}
20689f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
206989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Projectvoid AudioTrack::setAttributesFromStreamType(audio_stream_type_t streamType) {
207089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    mAttributes.flags = 0x0;
20719f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
207234fb29696b0f3abf61b10f8d053b1f33d501de0aMark Salyzyn    switch(streamType) {
207334fb29696b0f3abf61b10f8d053b1f33d501de0aMark Salyzyn    case AUDIO_STREAM_DEFAULT:
20749f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    case AUDIO_STREAM_MUSIC:
20759f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        mAttributes.content_type = AUDIO_CONTENT_TYPE_MUSIC;
20769f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        mAttributes.usage = AUDIO_USAGE_MEDIA;
20779f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        break;
20788555d0867c3e8fe6cc5c7ad40af557fe6b92fa72The Android Open Source Project    case AUDIO_STREAM_VOICE_CALL:
20798555d0867c3e8fe6cc5c7ad40af557fe6b92fa72The Android Open Source Project        mAttributes.content_type = AUDIO_CONTENT_TYPE_SPEECH;
20808555d0867c3e8fe6cc5c7ad40af557fe6b92fa72The Android Open Source Project        mAttributes.usage = AUDIO_USAGE_VOICE_COMMUNICATION;
20818555d0867c3e8fe6cc5c7ad40af557fe6b92fa72The Android Open Source Project        break;
2082a7f03353d5f172016f324e2a01f301cca6794152Andy Hung    case AUDIO_STREAM_ENFORCED_AUDIBLE:
2083a7f03353d5f172016f324e2a01f301cca6794152Andy Hung        mAttributes.flags  |= AUDIO_FLAG_AUDIBILITY_ENFORCED;
2084a7f03353d5f172016f324e2a01f301cca6794152Andy Hung        // intended fall through, attributes in common with STREAM_SYSTEM
2085a7f03353d5f172016f324e2a01f301cca6794152Andy Hung    case AUDIO_STREAM_SYSTEM:
2086a7f03353d5f172016f324e2a01f301cca6794152Andy Hung        mAttributes.content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
2087a7f03353d5f172016f324e2a01f301cca6794152Andy Hung        mAttributes.usage = AUDIO_USAGE_ASSISTANCE_SONIFICATION;
2088a7f03353d5f172016f324e2a01f301cca6794152Andy Hung        break;
2089a7f03353d5f172016f324e2a01f301cca6794152Andy Hung    case AUDIO_STREAM_RING:
2090a7f03353d5f172016f324e2a01f301cca6794152Andy Hung        mAttributes.content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
2091a7f03353d5f172016f324e2a01f301cca6794152Andy Hung        mAttributes.usage = AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE;
2092a7f03353d5f172016f324e2a01f301cca6794152Andy Hung        break;
2093a7f03353d5f172016f324e2a01f301cca6794152Andy Hung    case AUDIO_STREAM_ALARM:
2094a7f03353d5f172016f324e2a01f301cca6794152Andy Hung        mAttributes.content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
2095a7f03353d5f172016f324e2a01f301cca6794152Andy Hung        mAttributes.usage = AUDIO_USAGE_ALARM;
2096a7f03353d5f172016f324e2a01f301cca6794152Andy Hung        break;
2097fdb3c07db5d44535eb8c3ec46dc78ad8446c01ebPhil Burk    case AUDIO_STREAM_NOTIFICATION:
2098a7f03353d5f172016f324e2a01f301cca6794152Andy Hung        mAttributes.content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
2099a7f03353d5f172016f324e2a01f301cca6794152Andy Hung        mAttributes.usage = AUDIO_USAGE_NOTIFICATION;
2100a7f03353d5f172016f324e2a01f301cca6794152Andy Hung        break;
2101a7f03353d5f172016f324e2a01f301cca6794152Andy Hung    case AUDIO_STREAM_BLUETOOTH_SCO:
2102ea38ee7742e799b23bd8675f5801ef72f94de0f4Glenn Kasten        mAttributes.content_type = AUDIO_CONTENT_TYPE_SPEECH;
2103a7f03353d5f172016f324e2a01f301cca6794152Andy Hung        mAttributes.usage = AUDIO_USAGE_VOICE_COMMUNICATION;
2104a7f03353d5f172016f324e2a01f301cca6794152Andy Hung        mAttributes.flags |= AUDIO_FLAG_SCO;
2105a7f03353d5f172016f324e2a01f301cca6794152Andy Hung        break;
2106a7f03353d5f172016f324e2a01f301cca6794152Andy Hung    case AUDIO_STREAM_DTMF:
2107a7f03353d5f172016f324e2a01f301cca6794152Andy Hung        mAttributes.content_type = AUDIO_CONTENT_TYPE_SONIFICATION;
2108a7f03353d5f172016f324e2a01f301cca6794152Andy Hung        mAttributes.usage = AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING;
2109a7f03353d5f172016f324e2a01f301cca6794152Andy Hung        break;
2110a7f03353d5f172016f324e2a01f301cca6794152Andy Hung    case AUDIO_STREAM_TTS:
2111a7f03353d5f172016f324e2a01f301cca6794152Andy Hung        mAttributes.content_type = AUDIO_CONTENT_TYPE_SPEECH;
2112a7f03353d5f172016f324e2a01f301cca6794152Andy Hung        mAttributes.usage = AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY;
2113a7f03353d5f172016f324e2a01f301cca6794152Andy Hung        break;
2114a7f03353d5f172016f324e2a01f301cca6794152Andy Hung    default:
2115a7f03353d5f172016f324e2a01f301cca6794152Andy Hung        ALOGE("invalid stream type %d when converting to attributes", streamType);
2116a7f03353d5f172016f324e2a01f301cca6794152Andy Hung    }
2117a7f03353d5f172016f324e2a01f301cca6794152Andy Hung}
2118a7f03353d5f172016f324e2a01f301cca6794152Andy Hung
2119d65d73c4ae74d084751b417615a78cbe7a51372aGlenn Kastenvoid AudioTrack::setStreamTypeFromAttributes(audio_attributes_t& aa) {
212089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    // flags to stream type mapping
2121138d6f9b0b77d94773a8a29d3c5bdb78f38ee142Glenn Kasten    if ((aa.flags & AUDIO_FLAG_AUDIBILITY_ENFORCED) == AUDIO_FLAG_AUDIBILITY_ENFORCED) {
21229f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        mStreamType = AUDIO_STREAM_ENFORCED_AUDIBLE;
21239f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        return;
21249f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
21259f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if ((aa.flags & AUDIO_FLAG_SCO) == AUDIO_FLAG_SCO) {
21269f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        mStreamType = AUDIO_STREAM_BLUETOOTH_SCO;
21279f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        return;
21289f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
212989fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    // TODO once AudioPolicyManager fully supports audio_attributes_t,
213089fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project    //   remove stream remap, the flag will be enough
2131ea2b9c07b34079f0dbd8610a511e006e69a15adcAndy Hung    if ((aa.flags & AUDIO_FLAG_BEACON) == AUDIO_FLAG_BEACON) {
213289fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        mStreamType = AUDIO_STREAM_TTS;
21339f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        return;
21349f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
21359f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
21369f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    // usage to stream type mapping
21379f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    switch (aa.usage) {
21389f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    case AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY: {
21399f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        // TODO once AudioPolicyManager fully supports audio_attributes_t,
21409f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        //   remove stream change based on stream activity
21419f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        bool active;
21429f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        status_t status = AudioSystem::isStreamActive(AUDIO_STREAM_RING, &active, 0);
21439f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        if (status == NO_ERROR && active == true) {
21449f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            mStreamType = AUDIO_STREAM_RING;
21459f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            break;
21469f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        }
21479f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        status = AudioSystem::isStreamActive(AUDIO_STREAM_ALARM, &active, 0);
21489f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        if (status == NO_ERROR && active == true) {
21499f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            mStreamType = AUDIO_STREAM_ALARM;
21508edb8dc44b8a2f81bdb5db645b6b708548771a31Andy Hung            break;
21519f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        }
21529f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        audio_mode_t phoneState = AudioSystem::getPhoneState();
21539f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        if (phoneState == AUDIO_MODE_IN_CALL || phoneState == AUDIO_MODE_IN_COMMUNICATION) {
215489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project            mStreamType = AUDIO_STREAM_VOICE_CALL;
2155ea2b9c07b34079f0dbd8610a511e006e69a15adcAndy Hung            break;
2156ea2b9c07b34079f0dbd8610a511e006e69a15adcAndy Hung        }
2157ea2b9c07b34079f0dbd8610a511e006e69a15adcAndy Hung    }    /// FALL THROUGH
2158ea2b9c07b34079f0dbd8610a511e006e69a15adcAndy Hung    case AUDIO_USAGE_MEDIA:
21599f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    case AUDIO_USAGE_GAME:
21609f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    case AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE:
21619f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        mStreamType = AUDIO_STREAM_MUSIC;
21629f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        return;
21639f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    case AUDIO_USAGE_ASSISTANCE_SONIFICATION:
216489fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        mStreamType = AUDIO_STREAM_SYSTEM;
216589fa4ad53f2f4d57adbc97ae1149fc00c9b6f3c5The Android Open Source Project        return;
21669f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    case AUDIO_USAGE_VOICE_COMMUNICATION:
21671703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent        mStreamType = AUDIO_STREAM_VOICE_CALL;
2168b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald        return;
2169ab5cdbaf65ca509681d2726aacdf3ac8bfb6b3faEric Laurent
21709f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    case AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING:
21711703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent        mStreamType = AUDIO_STREAM_DTMF;
2172a47f3165f53c8e8fb8907a94de7417e2c3047eebGlenn Kasten        return;
2173d2d089fc86c62843992e7d5b371ee9227189a1e6Glenn Kasten
2174a47f3165f53c8e8fb8907a94de7417e2c3047eebGlenn Kasten    case AUDIO_USAGE_ALARM:
2175a47f3165f53c8e8fb8907a94de7417e2c3047eebGlenn Kasten        mStreamType = AUDIO_STREAM_ALARM;
2176faeb0f291330134dc4468359a36e099aae508449Ronghua Wu        return;
21771f1db8356b599bc40703c907fb69e6e539343532Andy Hung    case AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE:
21781f1db8356b599bc40703c907fb69e6e539343532Andy Hung        mStreamType = AUDIO_STREAM_RING;
2179b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald        return;
2180b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald
2181b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald    case AUDIO_USAGE_NOTIFICATION:
21822812d9ea3a3a33142dd8e23c9d949c498d6f7a12Phil Burk    case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_REQUEST:
21832812d9ea3a3a33142dd8e23c9d949c498d6f7a12Phil Burk    case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_INSTANT:
21842812d9ea3a3a33142dd8e23c9d949c498d6f7a12Phil Burk    case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_DELAYED:
2185200092b7f21d2b98f30b800e79d152636f9ba225Glenn Kasten    case AUDIO_USAGE_NOTIFICATION_EVENT:
21864ede21d9c1f957baf5e561849ff9bbe4bcbefc20Andy Hung        mStreamType = AUDIO_STREAM_NOTIFICATION;
21874ede21d9c1f957baf5e561849ff9bbe4bcbefc20Andy Hung        return;
21884ede21d9c1f957baf5e561849ff9bbe4bcbefc20Andy Hung
21894ede21d9c1f957baf5e561849ff9bbe4bcbefc20Andy Hung    case AUDIO_USAGE_UNKNOWN:
21904ede21d9c1f957baf5e561849ff9bbe4bcbefc20Andy Hung    default:
2191200092b7f21d2b98f30b800e79d152636f9ba225Glenn Kasten        mStreamType = AUDIO_STREAM_MUSIC;
2192ae34ed2bcc9fa49a22fe7497327adb689ef27e8dHaynes Mathew George    }
2193ae34ed2bcc9fa49a22fe7497327adb689ef27e8dHaynes Mathew George}
2194200092b7f21d2b98f30b800e79d152636f9ba225Glenn Kasten
2195a47f3165f53c8e8fb8907a94de7417e2c3047eebGlenn Kastenbool AudioTrack::isValidAttributes(const audio_attributes_t *paa) {
2196200092b7f21d2b98f30b800e79d152636f9ba225Glenn Kasten    // has flags that map to a strategy?
2197200092b7f21d2b98f30b800e79d152636f9ba225Glenn Kasten    if ((paa->flags & (AUDIO_FLAG_AUDIBILITY_ENFORCED | AUDIO_FLAG_SCO | AUDIO_FLAG_BEACON)) != 0) {
2198ae4b879d04c4b07c62241a8f507c8dce11e628e4Glenn Kasten        return true;
2199cc21e4f1e41dfa17e7e2bef995fcd22c45f6bcd0Eric Laurent    }
2200a47f3165f53c8e8fb8907a94de7417e2c3047eebGlenn Kasten
2201d7bd69e4d1e74f25413721804d5290c53ea87f2bAndy Hung    // has known usage?
2202d7bd69e4d1e74f25413721804d5290c53ea87f2bAndy Hung    switch (paa->usage) {
2203d7bd69e4d1e74f25413721804d5290c53ea87f2bAndy Hung    case AUDIO_USAGE_UNKNOWN:
2204d7bd69e4d1e74f25413721804d5290c53ea87f2bAndy Hung    case AUDIO_USAGE_MEDIA:
2205d7bd69e4d1e74f25413721804d5290c53ea87f2bAndy Hung    case AUDIO_USAGE_VOICE_COMMUNICATION:
2206d7bd69e4d1e74f25413721804d5290c53ea87f2bAndy Hung    case AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING:
22074ede21d9c1f957baf5e561849ff9bbe4bcbefc20Andy Hung    case AUDIO_USAGE_ALARM:
22084ede21d9c1f957baf5e561849ff9bbe4bcbefc20Andy Hung    case AUDIO_USAGE_NOTIFICATION:
22094ede21d9c1f957baf5e561849ff9bbe4bcbefc20Andy Hung    case AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE:
22104ede21d9c1f957baf5e561849ff9bbe4bcbefc20Andy Hung    case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_REQUEST:
22114ede21d9c1f957baf5e561849ff9bbe4bcbefc20Andy Hung    case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_INSTANT:
22124ede21d9c1f957baf5e561849ff9bbe4bcbefc20Andy Hung    case AUDIO_USAGE_NOTIFICATION_COMMUNICATION_DELAYED:
22134ede21d9c1f957baf5e561849ff9bbe4bcbefc20Andy Hung    case AUDIO_USAGE_NOTIFICATION_EVENT:
221453c3b5fc1afe162a8669cb3d27d6bb14e1847e39Andy Hung    case AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY:
221553c3b5fc1afe162a8669cb3d27d6bb14e1847e39Andy Hung    case AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE:
221653c3b5fc1afe162a8669cb3d27d6bb14e1847e39Andy Hung    case AUDIO_USAGE_ASSISTANCE_SONIFICATION:
22171703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent    case AUDIO_USAGE_GAME:
22181703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent        break;
22199f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    default:
2220a47f3165f53c8e8fb8907a94de7417e2c3047eebGlenn Kasten        return false;
2221ea2b9c07b34079f0dbd8610a511e006e69a15adcAndy Hung    }
22221703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent    return true;
22231703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent}
22249f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten// =========================================================================
22259f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
22269f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kastenvoid AudioTrack::DeathNotifier::binderDied(const wp<IBinder>& who __unused)
2227c2813e568aa476e03d159529c0af28c99536db8dAndy Hung{
22281703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent    sp<AudioTrack> audioTrack = mAudioTrack.promote();
22291703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent    if (audioTrack != 0) {
22301703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent        AutoMutex lock(audioTrack->mLock);
22311703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent        audioTrack->mProxy->binderDied();
22321703cdfee717b1b312bf8979816a9e2f16a82e5dEric Laurent    }
223390e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung}
2234200092b7f21d2b98f30b800e79d152636f9ba225Glenn Kasten
2235200092b7f21d2b98f30b800e79d152636f9ba225Glenn Kasten// =========================================================================
223690e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung
223790e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy HungAudioTrack::AudioTrackThread::AudioTrackThread(AudioTrack& receiver, bool bCanCallJava)
2238200092b7f21d2b98f30b800e79d152636f9ba225Glenn Kasten    : Thread(bCanCallJava), mReceiver(receiver), mPaused(true), mPausedInt(false), mPausedNs(0LL),
2239200092b7f21d2b98f30b800e79d152636f9ba225Glenn Kasten      mIgnoreNextPausedInt(false)
2240200092b7f21d2b98f30b800e79d152636f9ba225Glenn Kasten{
2241200092b7f21d2b98f30b800e79d152636f9ba225Glenn Kasten}
2242200092b7f21d2b98f30b800e79d152636f9ba225Glenn Kasten
2243200092b7f21d2b98f30b800e79d152636f9ba225Glenn KastenAudioTrack::AudioTrackThread::~AudioTrackThread()
2244200092b7f21d2b98f30b800e79d152636f9ba225Glenn Kasten{
2245200092b7f21d2b98f30b800e79d152636f9ba225Glenn Kasten}
224690e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung
224790e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hungbool AudioTrack::AudioTrackThread::threadLoop()
224890e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung{
2249039c27aeaee809182fc1491311ca6dcbc1ec441bChad Brubaker    {
225090e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung        AutoMutex _l(mMyLock);
225190e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung        if (mPaused) {
225290e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung            mMyCond.wait(mMyLock);
225390e8a97dd5c9d391d7a2ea6a2290ed976f928379Andy Hung            // caller will check for exitPending()
2254200092b7f21d2b98f30b800e79d152636f9ba225Glenn Kasten            return true;
2255200092b7f21d2b98f30b800e79d152636f9ba225Glenn Kasten        }
22568edb8dc44b8a2f81bdb5db645b6b708548771a31Andy Hung        if (mIgnoreNextPausedInt) {
22578edb8dc44b8a2f81bdb5db645b6b708548771a31Andy Hung            mIgnoreNextPausedInt = false;
22588edb8dc44b8a2f81bdb5db645b6b708548771a31Andy Hung            mPausedInt = false;
22598edb8dc44b8a2f81bdb5db645b6b708548771a31Andy Hung        }
22608edb8dc44b8a2f81bdb5db645b6b708548771a31Andy Hung        if (mPausedInt) {
22618edb8dc44b8a2f81bdb5db645b6b708548771a31Andy Hung            if (mPausedNs > 0) {
22628edb8dc44b8a2f81bdb5db645b6b708548771a31Andy Hung                (void) mMyCond.waitRelative(mMyLock, mPausedNs);
2263ea38ee7742e799b23bd8675f5801ef72f94de0f4Glenn Kasten            } else {
2264ea38ee7742e799b23bd8675f5801ef72f94de0f4Glenn Kasten                mMyCond.wait(mMyLock);
22658edb8dc44b8a2f81bdb5db645b6b708548771a31Andy Hung            }
22668edb8dc44b8a2f81bdb5db645b6b708548771a31Andy Hung            mPausedInt = false;
22678edb8dc44b8a2f81bdb5db645b6b708548771a31Andy Hung            return true;
22688edb8dc44b8a2f81bdb5db645b6b708548771a31Andy Hung        }
22698edb8dc44b8a2f81bdb5db645b6b708548771a31Andy Hung    }
2270ad3af3305f024bcbbd55c894a4995e449498e1baRichard Fitzgerald    if (exitPending()) {
2271ad3af3305f024bcbbd55c894a4995e449498e1baRichard Fitzgerald        return false;
2272ad3af3305f024bcbbd55c894a4995e449498e1baRichard Fitzgerald    }
227353cec22821072719ee02c856e9ac2dda2496c570Glenn Kasten    nsecs_t ns = mReceiver.processAudioBuffer();
2274ad3af3305f024bcbbd55c894a4995e449498e1baRichard Fitzgerald    switch (ns) {
2275ad3af3305f024bcbbd55c894a4995e449498e1baRichard Fitzgerald    case 0:
2276ea2b9c07b34079f0dbd8610a511e006e69a15adcAndy Hung        return true;
2277ea2b9c07b34079f0dbd8610a511e006e69a15adcAndy Hung    case NS_INACTIVE:
2278ea2b9c07b34079f0dbd8610a511e006e69a15adcAndy Hung        pauseInternal();
2279ea2b9c07b34079f0dbd8610a511e006e69a15adcAndy Hung        return true;
2280ea2b9c07b34079f0dbd8610a511e006e69a15adcAndy Hung    case NS_NEVER:
2281ea2b9c07b34079f0dbd8610a511e006e69a15adcAndy Hung        return false;
2282e13f8a603867280de9b02ce4839202a182556416Andy Hung    case NS_WHENEVER:
2283e13f8a603867280de9b02ce4839202a182556416Andy Hung        // FIXME increase poll interval, or make event-driven
2284e13f8a603867280de9b02ce4839202a182556416Andy Hung        ns = 1000000000LL;
2285e13f8a603867280de9b02ce4839202a182556416Andy Hung        // fall through
2286e13f8a603867280de9b02ce4839202a182556416Andy Hung    default:
2287ea2b9c07b34079f0dbd8610a511e006e69a15adcAndy Hung        LOG_ALWAYS_FATAL_IF(ns < 0, "processAudioBuffer() returned %" PRId64, ns);
2288ea2b9c07b34079f0dbd8610a511e006e69a15adcAndy Hung        pauseInternal(ns);
2289ea2b9c07b34079f0dbd8610a511e006e69a15adcAndy Hung        return true;
2290ea2b9c07b34079f0dbd8610a511e006e69a15adcAndy Hung    }
2291ea2b9c07b34079f0dbd8610a511e006e69a15adcAndy Hung}
2292ea2b9c07b34079f0dbd8610a511e006e69a15adcAndy Hung
2293ea2b9c07b34079f0dbd8610a511e006e69a15adcAndy Hungvoid AudioTrack::AudioTrackThread::requestExit()
2294ea2b9c07b34079f0dbd8610a511e006e69a15adcAndy Hung{
2295ea2b9c07b34079f0dbd8610a511e006e69a15adcAndy Hung    // must be in this order to avoid a race condition
2296ea2b9c07b34079f0dbd8610a511e006e69a15adcAndy Hung    Thread::requestExit();
2297ea2b9c07b34079f0dbd8610a511e006e69a15adcAndy Hung    resume();
2298ea2b9c07b34079f0dbd8610a511e006e69a15adcAndy Hung}
2299ea2b9c07b34079f0dbd8610a511e006e69a15adcAndy Hung
2300e1e9846a786a0d77a13b44f8e798e03b4cba9d77Andy Hungvoid AudioTrack::AudioTrackThread::pause()
2301ea2b9c07b34079f0dbd8610a511e006e69a15adcAndy Hung{
2302e1e9846a786a0d77a13b44f8e798e03b4cba9d77Andy Hung    AutoMutex _l(mMyLock);
2303e1e9846a786a0d77a13b44f8e798e03b4cba9d77Andy Hung    mPaused = true;
2304e1e9846a786a0d77a13b44f8e798e03b4cba9d77Andy Hung}
2305e1e9846a786a0d77a13b44f8e798e03b4cba9d77Andy Hung
2306e1e9846a786a0d77a13b44f8e798e03b4cba9d77Andy Hungvoid AudioTrack::AudioTrackThread::resume()
2307e1e9846a786a0d77a13b44f8e798e03b4cba9d77Andy Hung{
2308e1e9846a786a0d77a13b44f8e798e03b4cba9d77Andy Hung    AutoMutex _l(mMyLock);
2309e1e9846a786a0d77a13b44f8e798e03b4cba9d77Andy Hung    mIgnoreNextPausedInt = true;
2310e1e9846a786a0d77a13b44f8e798e03b4cba9d77Andy Hung    if (mPaused || mPausedInt) {
2311e1e9846a786a0d77a13b44f8e798e03b4cba9d77Andy Hung        mPaused = false;
2312ea2b9c07b34079f0dbd8610a511e006e69a15adcAndy Hung        mPausedInt = false;
2313ea2b9c07b34079f0dbd8610a511e006e69a15adcAndy Hung        mMyCond.signal();
2314ea2b9c07b34079f0dbd8610a511e006e69a15adcAndy Hung    }
2315ea2b9c07b34079f0dbd8610a511e006e69a15adcAndy Hung}
2316ea2b9c07b34079f0dbd8610a511e006e69a15adcAndy Hung
2317ce70374bf105f8a6160bf5dd70affea012b2a464Glenn Kastenvoid AudioTrack::AudioTrackThread::pauseInternal(nsecs_t ns)
2318ce70374bf105f8a6160bf5dd70affea012b2a464Glenn Kasten{
231953cec22821072719ee02c856e9ac2dda2496c570Glenn Kasten    AutoMutex _l(mMyLock);
23201b42097f38e72574ed853a35f4e8a66e4739c421Phil Burk    mPausedInt = true;
23211b42097f38e72574ed853a35f4e8a66e4739c421Phil Burk    mPausedNs = ns;
23221b42097f38e72574ed853a35f4e8a66e4739c421Phil Burk}
23231b42097f38e72574ed853a35f4e8a66e4739c421Phil Burk
23241b42097f38e72574ed853a35f4e8a66e4739c421Phil Burk}; // namespace android
23257f1bc8af1c46695191bf7e2aba6467f3616629c0Andy Hung