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, ×tamp.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