AudioTrackShared.cpp revision 6d8018f0b7be9deec6b0acab10a0dca6e91d0fb8
1a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten/* 2a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten * Copyright (C) 2007 The Android Open Source Project 3a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten * 4a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten * Licensed under the Apache License, Version 2.0 (the "License"); 5a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten * you may not use this file except in compliance with the License. 6a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten * You may obtain a copy of the License at 7a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten * 8a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten * http://www.apache.org/licenses/LICENSE-2.0 9a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten * 10a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten * Unless required by applicable law or agreed to in writing, software 11a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten * distributed under the License is distributed on an "AS IS" BASIS, 12a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten * See the License for the specific language governing permissions and 14a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten * limitations under the License. 15a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten */ 16a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten 17a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten#define LOG_TAG "AudioTrackShared" 18a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten//#define LOG_NDEBUG 0 19a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten 20a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten#include <private/media/AudioTrackShared.h> 21a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten#include <utils/Log.h> 22ee499291404a192b059f2e04c5afc65aa6cdd74cElliott Hughes 23ee499291404a192b059f2e04c5afc65aa6cdd74cElliott Hughes#include <linux/futex.h> 24ee499291404a192b059f2e04c5afc65aa6cdd74cElliott Hughes#include <sys/syscall.h> 25a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten 26a8190fc518b6769257896605f3aee091aeb60b50Glenn Kastennamespace android { 27a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten 28cb2129b3b568a4e31bcbda3545a468024bc972feAndy Hung// used to clamp a value to size_t. TODO: move to another file. 29cb2129b3b568a4e31bcbda3545a468024bc972feAndy Hungtemplate <typename T> 30cb2129b3b568a4e31bcbda3545a468024bc972feAndy Hungsize_t clampToSize(T x) { 31486a7135593b4b40c067e9b06f393577abfef482Andy Hung return sizeof(T) > sizeof(size_t) && x > (T) SIZE_MAX ? SIZE_MAX : x < 0 ? 0 : (size_t) x; 32cb2129b3b568a4e31bcbda3545a468024bc972feAndy Hung} 33cb2129b3b568a4e31bcbda3545a468024bc972feAndy Hung 349b4615887c23548438fd0d8e3d8f04ac21912850Andy Hung// incrementSequence is used to determine the next sequence value 359b4615887c23548438fd0d8e3d8f04ac21912850Andy Hung// for the loop and position sequence counters. It should return 369b4615887c23548438fd0d8e3d8f04ac21912850Andy Hung// a value between "other" + 1 and "other" + INT32_MAX, the choice of 379b4615887c23548438fd0d8e3d8f04ac21912850Andy Hung// which needs to be the "least recently used" sequence value for "self". 389b4615887c23548438fd0d8e3d8f04ac21912850Andy Hung// In general, this means (new_self) returned is max(self, other) + 1. 399b4615887c23548438fd0d8e3d8f04ac21912850Andy Hung 409b4615887c23548438fd0d8e3d8f04ac21912850Andy Hungstatic uint32_t incrementSequence(uint32_t self, uint32_t other) { 41cb50c54b31a83ac598530780fa8c145a3cb4a2deChad Brubaker int32_t diff = (int32_t) self - (int32_t) other; 429b4615887c23548438fd0d8e3d8f04ac21912850Andy Hung if (diff >= 0 && diff < INT32_MAX) { 439b4615887c23548438fd0d8e3d8f04ac21912850Andy Hung return self + 1; // we're already ahead of other. 449b4615887c23548438fd0d8e3d8f04ac21912850Andy Hung } 459b4615887c23548438fd0d8e3d8f04ac21912850Andy Hung return other + 1; // we're behind, so move just ahead of other. 469b4615887c23548438fd0d8e3d8f04ac21912850Andy Hung} 479b4615887c23548438fd0d8e3d8f04ac21912850Andy Hung 48a8190fc518b6769257896605f3aee091aeb60b50Glenn Kastenaudio_track_cblk_t::audio_track_cblk_t() 49e8972b0a27fac327c997fceb20d9abae1dc1d899Phil Burk : mServer(0), mFutex(0), mMinimum(0) 50e8972b0a27fac327c997fceb20d9abae1dc1d899Phil Burk , mVolumeLR(GAIN_MINIFLOAT_PACKED_UNITY), mSampleRate(0), mSendLevel(0) 51e8972b0a27fac327c997fceb20d9abae1dc1d899Phil Burk , mBufferSizeInFrames(0) 52e8972b0a27fac327c997fceb20d9abae1dc1d899Phil Burk , mFlags(0) 53a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten{ 549f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten memset(&u, 0, sizeof(u)); 55a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten} 56a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten 579f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten// --------------------------------------------------------------------------- 589f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 599f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn KastenProxy::Proxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount, size_t frameSize, 609f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten bool isOut, bool clientInServer) 619f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten : mCblk(cblk), mBuffers(buffers), mFrameCount(frameCount), mFrameSize(frameSize), 629f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mFrameCountP2(roundup(frameCount)), mIsOut(isOut), mClientInServer(clientInServer), 637db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kasten mIsShutdown(false), mUnreleased(0) 64a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten{ 659f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten} 66a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten 679f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten// --------------------------------------------------------------------------- 689f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 699f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn KastenClientProxy::ClientProxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount, 709f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten size_t frameSize, bool isOut, bool clientInServer) 71c0adecb800b197cb8c028513130ebabf2d0f37baPhil Burk : Proxy(cblk, buffers, frameCount, frameSize, isOut, clientInServer) 72c0adecb800b197cb8c028513130ebabf2d0f37baPhil Burk , mEpoch(0) 736ae5843c281301a9ffd1059d185620a9337e15a2Andy Hung , mTimestampObserver(&cblk->mExtendedTimestampQueue) 749f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten{ 75e8972b0a27fac327c997fceb20d9abae1dc1d899Phil Burk setBufferSizeInFrames(frameCount); 769f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten} 779f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 789f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kastenconst struct timespec ClientProxy::kForever = {INT_MAX /*tv_sec*/, 0 /*tv_nsec*/}; 799f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kastenconst struct timespec ClientProxy::kNonBlocking = {0 /*tv_sec*/, 0 /*tv_nsec*/}; 809f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 819f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten#define MEASURE_NS 10000000 // attempt to provide accurate timeouts if requested >= MEASURE_NS 829f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 839f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten// To facilitate quicker recovery from server failure, this value limits the timeout per each futex 849f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten// wait. However it does not protect infinite timeouts. If defined to be zero, there is no limit. 859f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten// FIXME May not be compatible with audio tunneling requirements where timeout should be in the 869f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten// order of minutes. 879f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten#define MAX_SEC 5 889f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 89e8972b0a27fac327c997fceb20d9abae1dc1d899Phil Burkuint32_t ClientProxy::setBufferSizeInFrames(uint32_t size) 90e8972b0a27fac327c997fceb20d9abae1dc1d899Phil Burk{ 91e8972b0a27fac327c997fceb20d9abae1dc1d899Phil Burk // The minimum should be greater than zero and less than the size 92e8972b0a27fac327c997fceb20d9abae1dc1d899Phil Burk // at which underruns will occur. 9326760d1a1105b6b318c837a491cdb96f6901804ePhil Burk const uint32_t minimum = 16; // based on AudioMixer::BLOCKSIZE 94e8972b0a27fac327c997fceb20d9abae1dc1d899Phil Burk const uint32_t maximum = frameCount(); 95e8972b0a27fac327c997fceb20d9abae1dc1d899Phil Burk uint32_t clippedSize = size; 9626760d1a1105b6b318c837a491cdb96f6901804ePhil Burk if (maximum < minimum) { 9726760d1a1105b6b318c837a491cdb96f6901804ePhil Burk clippedSize = maximum; 9826760d1a1105b6b318c837a491cdb96f6901804ePhil Burk } else if (clippedSize < minimum) { 99e8972b0a27fac327c997fceb20d9abae1dc1d899Phil Burk clippedSize = minimum; 100e8972b0a27fac327c997fceb20d9abae1dc1d899Phil Burk } else if (clippedSize > maximum) { 101e8972b0a27fac327c997fceb20d9abae1dc1d899Phil Burk clippedSize = maximum; 102e8972b0a27fac327c997fceb20d9abae1dc1d899Phil Burk } 103e8972b0a27fac327c997fceb20d9abae1dc1d899Phil Burk // for server to read 104e8972b0a27fac327c997fceb20d9abae1dc1d899Phil Burk android_atomic_release_store(clippedSize, (int32_t *)&mCblk->mBufferSizeInFrames); 105e8972b0a27fac327c997fceb20d9abae1dc1d899Phil Burk // for client to read 106e8972b0a27fac327c997fceb20d9abae1dc1d899Phil Burk mBufferSizeInFrames = clippedSize; 107e8972b0a27fac327c997fceb20d9abae1dc1d899Phil Burk return clippedSize; 108e8972b0a27fac327c997fceb20d9abae1dc1d899Phil Burk} 109e8972b0a27fac327c997fceb20d9abae1dc1d899Phil Burk 110926b82fa9e22739686602f7ae8cf24105f14d82eilewis__attribute__((no_sanitize("integer"))) 1119f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kastenstatus_t ClientProxy::obtainBuffer(Buffer* buffer, const struct timespec *requested, 1129f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten struct timespec *elapsed) 1139f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten{ 1147db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kasten LOG_ALWAYS_FATAL_IF(buffer == NULL || buffer->mFrameCount == 0); 1159f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten struct timespec total; // total elapsed time spent waiting 1169f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten total.tv_sec = 0; 1179f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten total.tv_nsec = 0; 1189f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten bool measure = elapsed != NULL; // whether to measure total elapsed time spent waiting 119a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten 1209f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten status_t status; 1219f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten enum { 1229f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten TIMEOUT_ZERO, // requested == NULL || *requested == 0 1239f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten TIMEOUT_INFINITE, // *requested == infinity 1249f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten TIMEOUT_FINITE, // 0 < *requested < infinity 1259f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten TIMEOUT_CONTINUE, // additional chances after TIMEOUT_FINITE 1269f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } timeout; 1279f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (requested == NULL) { 1289f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten timeout = TIMEOUT_ZERO; 1299f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } else if (requested->tv_sec == 0 && requested->tv_nsec == 0) { 1309f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten timeout = TIMEOUT_ZERO; 1319f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } else if (requested->tv_sec == INT_MAX) { 1329f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten timeout = TIMEOUT_INFINITE; 1339f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } else { 1349f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten timeout = TIMEOUT_FINITE; 1359f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (requested->tv_sec > 0 || requested->tv_nsec >= MEASURE_NS) { 1369f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten measure = true; 1379f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 1389f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 1399f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten struct timespec before; 1409f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten bool beforeIsValid = false; 1419f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten audio_track_cblk_t* cblk = mCblk; 1429f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten bool ignoreInitialPendingInterrupt = true; 1439f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // check for shared memory corruption 1449f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (mIsShutdown) { 1459f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten status = NO_INIT; 1469f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten goto end; 1479f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 1489f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten for (;;) { 14996f60d8f04432a1ed503b3e24d5736d28c63c9a2Glenn Kasten int32_t flags = android_atomic_and(~CBLK_INTERRUPT, &cblk->mFlags); 1509f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // check for track invalidation by server, or server death detection 1519f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (flags & CBLK_INVALID) { 1529f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten ALOGV("Track invalidated"); 1539f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten status = DEAD_OBJECT; 1549f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten goto end; 1559f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 1564d231dc0ee34380956c71cbe18a750e487a69601Eric Laurent if (flags & CBLK_DISABLED) { 1574d231dc0ee34380956c71cbe18a750e487a69601Eric Laurent ALOGV("Track disabled"); 1584d231dc0ee34380956c71cbe18a750e487a69601Eric Laurent status = NOT_ENOUGH_DATA; 1594d231dc0ee34380956c71cbe18a750e487a69601Eric Laurent goto end; 1604d231dc0ee34380956c71cbe18a750e487a69601Eric Laurent } 1619f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // check for obtainBuffer interrupted by client 1629f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (!ignoreInitialPendingInterrupt && (flags & CBLK_INTERRUPT)) { 1639f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten ALOGV("obtainBuffer() interrupted by client"); 1649f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten status = -EINTR; 1659f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten goto end; 1669f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 1679f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten ignoreInitialPendingInterrupt = false; 1689f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // compute number of frames available to write (AudioTrack) or read (AudioRecord) 1699f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten int32_t front; 1709f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten int32_t rear; 1719f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (mIsOut) { 1729f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // The barrier following the read of mFront is probably redundant. 1739f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // We're about to perform a conditional branch based on 'filled', 1749f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // which will force the processor to observe the read of mFront 1759f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // prior to allowing data writes starting at mRaw. 1769f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // However, the processor may support speculative execution, 1779f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // and be unable to undo speculative writes into shared memory. 1789f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // The barrier will prevent such speculative execution. 1799f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten front = android_atomic_acquire_load(&cblk->u.mStreaming.mFront); 1809f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten rear = cblk->u.mStreaming.mRear; 1819f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } else { 1829f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // On the other hand, this barrier is required. 1839f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten rear = android_atomic_acquire_load(&cblk->u.mStreaming.mRear); 1849f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten front = cblk->u.mStreaming.mFront; 1859f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 186c0adecb800b197cb8c028513130ebabf2d0f37baPhil Burk // write to rear, read from front 1879f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten ssize_t filled = rear - front; 1889f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // pipe should not be overfull 1899f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (!(0 <= filled && (size_t) filled <= mFrameCount)) { 1906dbb5e3336cfff1ad51d429fcb847307c06efd61Glenn Kasten if (mIsOut) { 19134fb29696b0f3abf61b10f8d053b1f33d501de0aMark Salyzyn ALOGE("Shared memory control block is corrupt (filled=%zd, mFrameCount=%zu); " 1926dbb5e3336cfff1ad51d429fcb847307c06efd61Glenn Kasten "shutting down", filled, mFrameCount); 1936dbb5e3336cfff1ad51d429fcb847307c06efd61Glenn Kasten mIsShutdown = true; 1946dbb5e3336cfff1ad51d429fcb847307c06efd61Glenn Kasten status = NO_INIT; 1956dbb5e3336cfff1ad51d429fcb847307c06efd61Glenn Kasten goto end; 1966dbb5e3336cfff1ad51d429fcb847307c06efd61Glenn Kasten } 1976dbb5e3336cfff1ad51d429fcb847307c06efd61Glenn Kasten // for input, sync up on overrun 1986dbb5e3336cfff1ad51d429fcb847307c06efd61Glenn Kasten filled = 0; 1996dbb5e3336cfff1ad51d429fcb847307c06efd61Glenn Kasten cblk->u.mStreaming.mFront = rear; 2006dbb5e3336cfff1ad51d429fcb847307c06efd61Glenn Kasten (void) android_atomic_or(CBLK_OVERRUN, &cblk->mFlags); 2019f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 202c0adecb800b197cb8c028513130ebabf2d0f37baPhil Burk // Don't allow filling pipe beyond the user settable size. 203c0adecb800b197cb8c028513130ebabf2d0f37baPhil Burk // The calculation for avail can go negative if the buffer size 204c0adecb800b197cb8c028513130ebabf2d0f37baPhil Burk // is suddenly dropped below the amount already in the buffer. 205c0adecb800b197cb8c028513130ebabf2d0f37baPhil Burk // So use a signed calculation to prevent a numeric overflow abort. 206e8972b0a27fac327c997fceb20d9abae1dc1d899Phil Burk ssize_t adjustableSize = (ssize_t) getBufferSizeInFrames(); 207c0adecb800b197cb8c028513130ebabf2d0f37baPhil Burk ssize_t avail = (mIsOut) ? adjustableSize - filled : filled; 208c0adecb800b197cb8c028513130ebabf2d0f37baPhil Burk if (avail < 0) { 209c0adecb800b197cb8c028513130ebabf2d0f37baPhil Burk avail = 0; 210c0adecb800b197cb8c028513130ebabf2d0f37baPhil Burk } else if (avail > 0) { 2119f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // 'avail' may be non-contiguous, so return only the first contiguous chunk 212bdd8101cd487cdfe36726aa0d78c24008c35d605Eric Laurent size_t part1; 2139f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (mIsOut) { 2149f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten rear &= mFrameCountP2 - 1; 2159f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten part1 = mFrameCountP2 - rear; 2169f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } else { 2179f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten front &= mFrameCountP2 - 1; 2189f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten part1 = mFrameCountP2 - front; 2199f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 220bdd8101cd487cdfe36726aa0d78c24008c35d605Eric Laurent if (part1 > (size_t)avail) { 2219f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten part1 = avail; 2229f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 223bdd8101cd487cdfe36726aa0d78c24008c35d605Eric Laurent if (part1 > buffer->mFrameCount) { 2249f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten part1 = buffer->mFrameCount; 2259f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 226bdd8101cd487cdfe36726aa0d78c24008c35d605Eric Laurent buffer->mFrameCount = part1; 2279f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten buffer->mRaw = part1 > 0 ? 2289f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten &((char *) mBuffers)[(mIsOut ? rear : front) * mFrameSize] : NULL; 2299f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten buffer->mNonContig = avail - part1; 2307db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kasten mUnreleased = part1; 2319f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten status = NO_ERROR; 2329f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten break; 2339f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 2349f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten struct timespec remaining; 2359f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten const struct timespec *ts; 2369f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten switch (timeout) { 2379f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten case TIMEOUT_ZERO: 2389f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten status = WOULD_BLOCK; 2399f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten goto end; 2409f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten case TIMEOUT_INFINITE: 2419f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten ts = NULL; 2429f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten break; 2439f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten case TIMEOUT_FINITE: 2449f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten timeout = TIMEOUT_CONTINUE; 2459f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (MAX_SEC == 0) { 2469f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten ts = requested; 2479f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten break; 2489f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 2499f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // fall through 2509f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten case TIMEOUT_CONTINUE: 2519f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // FIXME we do not retry if requested < 10ms? needs documentation on this state machine 2529f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (!measure || requested->tv_sec < total.tv_sec || 2539f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten (requested->tv_sec == total.tv_sec && requested->tv_nsec <= total.tv_nsec)) { 2549f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten status = TIMED_OUT; 2559f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten goto end; 2569f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 2579f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten remaining.tv_sec = requested->tv_sec - total.tv_sec; 2589f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if ((remaining.tv_nsec = requested->tv_nsec - total.tv_nsec) < 0) { 2599f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten remaining.tv_nsec += 1000000000; 2609f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten remaining.tv_sec++; 2619f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 2629f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (0 < MAX_SEC && MAX_SEC < remaining.tv_sec) { 2639f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten remaining.tv_sec = MAX_SEC; 2649f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten remaining.tv_nsec = 0; 2659f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 2669f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten ts = &remaining; 2679f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten break; 2689f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten default: 269adad3d7d935da176ff24941b4ae9edf7340e9b96Glenn Kasten LOG_ALWAYS_FATAL("obtainBuffer() timeout=%d", timeout); 2709f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten ts = NULL; 2719f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten break; 2729f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 2730d09a9bec07b3bec78bd473ff0bfcf0a261f3f25Glenn Kasten int32_t old = android_atomic_and(~CBLK_FUTEX_WAKE, &cblk->mFutex); 2740d09a9bec07b3bec78bd473ff0bfcf0a261f3f25Glenn Kasten if (!(old & CBLK_FUTEX_WAKE)) { 2759f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (measure && !beforeIsValid) { 2769f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten clock_gettime(CLOCK_MONOTONIC, &before); 2779f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten beforeIsValid = true; 2789f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 279ee499291404a192b059f2e04c5afc65aa6cdd74cElliott Hughes errno = 0; 280ee499291404a192b059f2e04c5afc65aa6cdd74cElliott Hughes (void) syscall(__NR_futex, &cblk->mFutex, 2810d09a9bec07b3bec78bd473ff0bfcf0a261f3f25Glenn Kasten mClientInServer ? FUTEX_WAIT_PRIVATE : FUTEX_WAIT, old & ~CBLK_FUTEX_WAKE, ts); 282b463da8e499149c7230b8dbd839bb7bc8ece602fLeena Winterrowd status_t error = errno; // clock_gettime can affect errno 2839f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // update total elapsed time spent waiting 2849f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (measure) { 2859f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten struct timespec after; 2869f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten clock_gettime(CLOCK_MONOTONIC, &after); 2879f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten total.tv_sec += after.tv_sec - before.tv_sec; 2889f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten long deltaNs = after.tv_nsec - before.tv_nsec; 2899f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (deltaNs < 0) { 2909f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten deltaNs += 1000000000; 2919f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten total.tv_sec--; 2929f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 2939f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if ((total.tv_nsec += deltaNs) >= 1000000000) { 2949f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten total.tv_nsec -= 1000000000; 2959f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten total.tv_sec++; 2969f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 2979f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten before = after; 2989f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten beforeIsValid = true; 2999f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 300b463da8e499149c7230b8dbd839bb7bc8ece602fLeena Winterrowd switch (error) { 301ee499291404a192b059f2e04c5afc65aa6cdd74cElliott Hughes case 0: // normal wakeup by server, or by binderDied() 302ee499291404a192b059f2e04c5afc65aa6cdd74cElliott Hughes case EWOULDBLOCK: // benign race condition with server 303ee499291404a192b059f2e04c5afc65aa6cdd74cElliott Hughes case EINTR: // wait was interrupted by signal or other spurious wakeup 304ee499291404a192b059f2e04c5afc65aa6cdd74cElliott Hughes case ETIMEDOUT: // time-out expired 3057db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kasten // FIXME these error/non-0 status are being dropped 3069f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten break; 3079f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten default: 308b463da8e499149c7230b8dbd839bb7bc8ece602fLeena Winterrowd status = error; 309ee499291404a192b059f2e04c5afc65aa6cdd74cElliott Hughes ALOGE("%s unexpected error %s", __func__, strerror(status)); 3109f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten goto end; 3119f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 312a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten } 313a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten } 314a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten 3159f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kastenend: 3169f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (status != NO_ERROR) { 3179f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten buffer->mFrameCount = 0; 3189f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten buffer->mRaw = NULL; 3199f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten buffer->mNonContig = 0; 3207db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kasten mUnreleased = 0; 3219f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 3229f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (elapsed != NULL) { 3239f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten *elapsed = total; 324a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten } 3259f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (requested == NULL) { 3269f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten requested = &kNonBlocking; 3279f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 3289f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (measure) { 329b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald ALOGV("requested %ld.%03ld elapsed %ld.%03ld", 330b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald requested->tv_sec, requested->tv_nsec / 1000000, 331b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald total.tv_sec, total.tv_nsec / 1000000); 3329f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 3339f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten return status; 3349f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten} 335a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten 336926b82fa9e22739686602f7ae8cf24105f14d82eilewis__attribute__((no_sanitize("integer"))) 3379f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kastenvoid ClientProxy::releaseBuffer(Buffer* buffer) 3389f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten{ 3397db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kasten LOG_ALWAYS_FATAL_IF(buffer == NULL); 3409f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten size_t stepCount = buffer->mFrameCount; 3417db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kasten if (stepCount == 0 || mIsShutdown) { 3427db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kasten // prevent accidental re-use of buffer 3437db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kasten buffer->mFrameCount = 0; 3447db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kasten buffer->mRaw = NULL; 3457db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kasten buffer->mNonContig = 0; 3469f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten return; 3479f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 3487db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kasten LOG_ALWAYS_FATAL_IF(!(stepCount <= mUnreleased && mUnreleased <= mFrameCount)); 3497db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kasten mUnreleased -= stepCount; 3509f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten audio_track_cblk_t* cblk = mCblk; 3519f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // Both of these barriers are required 3529f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (mIsOut) { 3539f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten int32_t rear = cblk->u.mStreaming.mRear; 3549f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten android_atomic_release_store(stepCount + rear, &cblk->u.mStreaming.mRear); 3559f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } else { 3569f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten int32_t front = cblk->u.mStreaming.mFront; 3579f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten android_atomic_release_store(stepCount + front, &cblk->u.mStreaming.mFront); 3589f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 359a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten} 360a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten 3619f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kastenvoid ClientProxy::binderDied() 362a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten{ 3639f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten audio_track_cblk_t* cblk = mCblk; 36496f60d8f04432a1ed503b3e24d5736d28c63c9a2Glenn Kasten if (!(android_atomic_or(CBLK_INVALID, &cblk->mFlags) & CBLK_INVALID)) { 36582a69ea8b090d57bff5e02774688b546a711bbb8zunkyu.lee android_atomic_or(CBLK_FUTEX_WAKE, &cblk->mFutex); 3669f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // it seems that a FUTEX_WAKE_PRIVATE will not wake a FUTEX_WAIT, even within same process 367ee499291404a192b059f2e04c5afc65aa6cdd74cElliott Hughes (void) syscall(__NR_futex, &cblk->mFutex, mClientInServer ? FUTEX_WAKE_PRIVATE : FUTEX_WAKE, 368ee499291404a192b059f2e04c5afc65aa6cdd74cElliott Hughes 1); 3699f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 3709f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten} 371a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten 3729f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kastenvoid ClientProxy::interrupt() 3739f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten{ 3749f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten audio_track_cblk_t* cblk = mCblk; 37596f60d8f04432a1ed503b3e24d5736d28c63c9a2Glenn Kasten if (!(android_atomic_or(CBLK_INTERRUPT, &cblk->mFlags) & CBLK_INTERRUPT)) { 37682a69ea8b090d57bff5e02774688b546a711bbb8zunkyu.lee android_atomic_or(CBLK_FUTEX_WAKE, &cblk->mFutex); 377ee499291404a192b059f2e04c5afc65aa6cdd74cElliott Hughes (void) syscall(__NR_futex, &cblk->mFutex, mClientInServer ? FUTEX_WAKE_PRIVATE : FUTEX_WAKE, 378ee499291404a192b059f2e04c5afc65aa6cdd74cElliott Hughes 1); 379a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten } 3809f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten} 381a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten 38265dda4f09425ad027e27a51a3108472448d3ab8bChad Brubaker__attribute__((no_sanitize("integer"))) 3839f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kastensize_t ClientProxy::getMisalignment() 3849f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten{ 3859f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten audio_track_cblk_t* cblk = mCblk; 3869f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten return (mFrameCountP2 - (mIsOut ? cblk->u.mStreaming.mRear : cblk->u.mStreaming.mFront)) & 3879f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten (mFrameCountP2 - 1); 3889f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten} 389a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten 3909f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten// --------------------------------------------------------------------------- 3919f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 3929f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kastenvoid AudioTrackClientProxy::flush() 3939f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten{ 39420f51b1ea04c410a25f214e37bcdb586e2a028ccGlenn Kasten // This works for mFrameCountP2 <= 2^30 39520f51b1ea04c410a25f214e37bcdb586e2a028ccGlenn Kasten size_t increment = mFrameCountP2 << 1; 39620f51b1ea04c410a25f214e37bcdb586e2a028ccGlenn Kasten size_t mask = increment - 1; 39720f51b1ea04c410a25f214e37bcdb586e2a028ccGlenn Kasten audio_track_cblk_t* cblk = mCblk; 398a2d75cdb1e389f2b4ce5992fb6652399b4d30966Andy Hung // mFlush is 32 bits concatenated as [ flush_counter ] [ newfront_offset ] 399a2d75cdb1e389f2b4ce5992fb6652399b4d30966Andy Hung // Should newFlush = cblk->u.mStreaming.mRear? Only problem is 400a2d75cdb1e389f2b4ce5992fb6652399b4d30966Andy Hung // if you want to flush twice to the same rear location after a 32 bit wrap. 40120f51b1ea04c410a25f214e37bcdb586e2a028ccGlenn Kasten int32_t newFlush = (cblk->u.mStreaming.mRear & mask) | 40220f51b1ea04c410a25f214e37bcdb586e2a028ccGlenn Kasten ((cblk->u.mStreaming.mFlush & ~mask) + increment); 40320f51b1ea04c410a25f214e37bcdb586e2a028ccGlenn Kasten android_atomic_release_store(newFlush, &cblk->u.mStreaming.mFlush); 4049f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten} 4059f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 406bfb1b832079bbb9426f72f3863199a54aefd02daEric Laurentbool AudioTrackClientProxy::clearStreamEndDone() { 40796f60d8f04432a1ed503b3e24d5736d28c63c9a2Glenn Kasten return (android_atomic_and(~CBLK_STREAM_END_DONE, &mCblk->mFlags) & CBLK_STREAM_END_DONE) != 0; 408bfb1b832079bbb9426f72f3863199a54aefd02daEric Laurent} 409bfb1b832079bbb9426f72f3863199a54aefd02daEric Laurent 410bfb1b832079bbb9426f72f3863199a54aefd02daEric Laurentbool AudioTrackClientProxy::getStreamEndDone() const { 41196f60d8f04432a1ed503b3e24d5736d28c63c9a2Glenn Kasten return (mCblk->mFlags & CBLK_STREAM_END_DONE) != 0; 412bfb1b832079bbb9426f72f3863199a54aefd02daEric Laurent} 413bfb1b832079bbb9426f72f3863199a54aefd02daEric Laurent 414b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgeraldstatus_t AudioTrackClientProxy::waitStreamEndDone(const struct timespec *requested) 415b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald{ 416b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald struct timespec total; // total elapsed time spent waiting 417b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald total.tv_sec = 0; 418b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald total.tv_nsec = 0; 419b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald audio_track_cblk_t* cblk = mCblk; 420b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald status_t status; 421b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald enum { 422b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald TIMEOUT_ZERO, // requested == NULL || *requested == 0 423b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald TIMEOUT_INFINITE, // *requested == infinity 424b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald TIMEOUT_FINITE, // 0 < *requested < infinity 425b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald TIMEOUT_CONTINUE, // additional chances after TIMEOUT_FINITE 426b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald } timeout; 427b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald if (requested == NULL) { 428b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald timeout = TIMEOUT_ZERO; 429b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald } else if (requested->tv_sec == 0 && requested->tv_nsec == 0) { 430b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald timeout = TIMEOUT_ZERO; 431b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald } else if (requested->tv_sec == INT_MAX) { 432b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald timeout = TIMEOUT_INFINITE; 433b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald } else { 434b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald timeout = TIMEOUT_FINITE; 435b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald } 436b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald for (;;) { 43796f60d8f04432a1ed503b3e24d5736d28c63c9a2Glenn Kasten int32_t flags = android_atomic_and(~(CBLK_INTERRUPT|CBLK_STREAM_END_DONE), &cblk->mFlags); 438b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald // check for track invalidation by server, or server death detection 439b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald if (flags & CBLK_INVALID) { 440b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald ALOGV("Track invalidated"); 441b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald status = DEAD_OBJECT; 442b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald goto end; 443b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald } 4444d231dc0ee34380956c71cbe18a750e487a69601Eric Laurent // a track is not supposed to underrun at this stage but consider it done 4454d231dc0ee34380956c71cbe18a750e487a69601Eric Laurent if (flags & (CBLK_STREAM_END_DONE | CBLK_DISABLED)) { 446b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald ALOGV("stream end received"); 447b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald status = NO_ERROR; 448b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald goto end; 449b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald } 450b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald // check for obtainBuffer interrupted by client 451b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald if (flags & CBLK_INTERRUPT) { 452b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald ALOGV("waitStreamEndDone() interrupted by client"); 453b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald status = -EINTR; 454b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald goto end; 455b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald } 456b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald struct timespec remaining; 457b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald const struct timespec *ts; 458b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald switch (timeout) { 459b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald case TIMEOUT_ZERO: 460b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald status = WOULD_BLOCK; 461b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald goto end; 462b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald case TIMEOUT_INFINITE: 463b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald ts = NULL; 464b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald break; 465b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald case TIMEOUT_FINITE: 466b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald timeout = TIMEOUT_CONTINUE; 467b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald if (MAX_SEC == 0) { 468b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald ts = requested; 469b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald break; 470b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald } 471b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald // fall through 472b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald case TIMEOUT_CONTINUE: 473b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald // FIXME we do not retry if requested < 10ms? needs documentation on this state machine 474b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald if (requested->tv_sec < total.tv_sec || 475b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald (requested->tv_sec == total.tv_sec && requested->tv_nsec <= total.tv_nsec)) { 476b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald status = TIMED_OUT; 477b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald goto end; 478b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald } 479b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald remaining.tv_sec = requested->tv_sec - total.tv_sec; 480b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald if ((remaining.tv_nsec = requested->tv_nsec - total.tv_nsec) < 0) { 481b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald remaining.tv_nsec += 1000000000; 482b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald remaining.tv_sec++; 483b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald } 484b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald if (0 < MAX_SEC && MAX_SEC < remaining.tv_sec) { 485b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald remaining.tv_sec = MAX_SEC; 486b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald remaining.tv_nsec = 0; 487b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald } 488b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald ts = &remaining; 489b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald break; 490b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald default: 491adad3d7d935da176ff24941b4ae9edf7340e9b96Glenn Kasten LOG_ALWAYS_FATAL("waitStreamEndDone() timeout=%d", timeout); 492b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald ts = NULL; 493b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald break; 494b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald } 495b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald int32_t old = android_atomic_and(~CBLK_FUTEX_WAKE, &cblk->mFutex); 496b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald if (!(old & CBLK_FUTEX_WAKE)) { 497ee499291404a192b059f2e04c5afc65aa6cdd74cElliott Hughes errno = 0; 498ee499291404a192b059f2e04c5afc65aa6cdd74cElliott Hughes (void) syscall(__NR_futex, &cblk->mFutex, 499b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald mClientInServer ? FUTEX_WAIT_PRIVATE : FUTEX_WAIT, old & ~CBLK_FUTEX_WAKE, ts); 500ee499291404a192b059f2e04c5afc65aa6cdd74cElliott Hughes switch (errno) { 501ee499291404a192b059f2e04c5afc65aa6cdd74cElliott Hughes case 0: // normal wakeup by server, or by binderDied() 502ee499291404a192b059f2e04c5afc65aa6cdd74cElliott Hughes case EWOULDBLOCK: // benign race condition with server 503ee499291404a192b059f2e04c5afc65aa6cdd74cElliott Hughes case EINTR: // wait was interrupted by signal or other spurious wakeup 504ee499291404a192b059f2e04c5afc65aa6cdd74cElliott Hughes case ETIMEDOUT: // time-out expired 505b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald break; 506b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald default: 507ee499291404a192b059f2e04c5afc65aa6cdd74cElliott Hughes status = errno; 508ee499291404a192b059f2e04c5afc65aa6cdd74cElliott Hughes ALOGE("%s unexpected error %s", __func__, strerror(status)); 509b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald goto end; 510b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald } 511b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald } 512b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald } 513b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald 514b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgeraldend: 515b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald if (requested == NULL) { 516b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald requested = &kNonBlocking; 517b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald } 518b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald return status; 519b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald} 520b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald 5219f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten// --------------------------------------------------------------------------- 5229f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 5239f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn KastenStaticAudioTrackClientProxy::StaticAudioTrackClientProxy(audio_track_cblk_t* cblk, void *buffers, 5249f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten size_t frameCount, size_t frameSize) 5259f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten : AudioTrackClientProxy(cblk, buffers, frameCount, frameSize), 5264ede21d9c1f957baf5e561849ff9bbe4bcbefc20Andy Hung mMutator(&cblk->u.mStatic.mSingleStateQueue), 5274ede21d9c1f957baf5e561849ff9bbe4bcbefc20Andy Hung mPosLoopObserver(&cblk->u.mStatic.mPosLoopQueue) 5289f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten{ 5299b4615887c23548438fd0d8e3d8f04ac21912850Andy Hung memset(&mState, 0, sizeof(mState)); 5304ede21d9c1f957baf5e561849ff9bbe4bcbefc20Andy Hung memset(&mPosLoop, 0, sizeof(mPosLoop)); 5319f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten} 5329f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 5339f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kastenvoid StaticAudioTrackClientProxy::flush() 5349f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten{ 535adad3d7d935da176ff24941b4ae9edf7340e9b96Glenn Kasten LOG_ALWAYS_FATAL("static flush"); 5369f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten} 5379f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 5389f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kastenvoid StaticAudioTrackClientProxy::setLoop(size_t loopStart, size_t loopEnd, int loopCount) 5399f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten{ 540fdac7c00f9201bb3a9862069145f01d37e39755bGlenn Kasten // This can only happen on a 64-bit client 541fdac7c00f9201bb3a9862069145f01d37e39755bGlenn Kasten if (loopStart > UINT32_MAX || loopEnd > UINT32_MAX) { 542fdac7c00f9201bb3a9862069145f01d37e39755bGlenn Kasten // FIXME Should return an error status 543fdac7c00f9201bb3a9862069145f01d37e39755bGlenn Kasten return; 544fdac7c00f9201bb3a9862069145f01d37e39755bGlenn Kasten } 5459b4615887c23548438fd0d8e3d8f04ac21912850Andy Hung mState.mLoopStart = (uint32_t) loopStart; 5469b4615887c23548438fd0d8e3d8f04ac21912850Andy Hung mState.mLoopEnd = (uint32_t) loopEnd; 5479b4615887c23548438fd0d8e3d8f04ac21912850Andy Hung mState.mLoopCount = loopCount; 5489b4615887c23548438fd0d8e3d8f04ac21912850Andy Hung mState.mLoopSequence = incrementSequence(mState.mLoopSequence, mState.mPositionSequence); 5499b4615887c23548438fd0d8e3d8f04ac21912850Andy Hung // set patch-up variables until the mState is acknowledged by the ServerProxy. 5509b4615887c23548438fd0d8e3d8f04ac21912850Andy Hung // observed buffer position and loop count will freeze until then to give the 5519b4615887c23548438fd0d8e3d8f04ac21912850Andy Hung // illusion of a synchronous change. 5524ede21d9c1f957baf5e561849ff9bbe4bcbefc20Andy Hung getBufferPositionAndLoopCount(NULL, NULL); 5539b4615887c23548438fd0d8e3d8f04ac21912850Andy Hung // preserve behavior to restart at mState.mLoopStart if position exceeds mState.mLoopEnd. 5544ede21d9c1f957baf5e561849ff9bbe4bcbefc20Andy Hung if (mState.mLoopCount != 0 && mPosLoop.mBufferPosition >= mState.mLoopEnd) { 5554ede21d9c1f957baf5e561849ff9bbe4bcbefc20Andy Hung mPosLoop.mBufferPosition = mState.mLoopStart; 5569b4615887c23548438fd0d8e3d8f04ac21912850Andy Hung } 5574ede21d9c1f957baf5e561849ff9bbe4bcbefc20Andy Hung mPosLoop.mLoopCount = mState.mLoopCount; 5589b4615887c23548438fd0d8e3d8f04ac21912850Andy Hung (void) mMutator.push(mState); 5599b4615887c23548438fd0d8e3d8f04ac21912850Andy Hung} 5609b4615887c23548438fd0d8e3d8f04ac21912850Andy Hung 5619b4615887c23548438fd0d8e3d8f04ac21912850Andy Hungvoid StaticAudioTrackClientProxy::setBufferPosition(size_t position) 5629b4615887c23548438fd0d8e3d8f04ac21912850Andy Hung{ 5639b4615887c23548438fd0d8e3d8f04ac21912850Andy Hung // This can only happen on a 64-bit client 5649b4615887c23548438fd0d8e3d8f04ac21912850Andy Hung if (position > UINT32_MAX) { 5659b4615887c23548438fd0d8e3d8f04ac21912850Andy Hung // FIXME Should return an error status 5669b4615887c23548438fd0d8e3d8f04ac21912850Andy Hung return; 567680b795435a5a501a56610258dce5eda40a1725dAndy Hung } 5689b4615887c23548438fd0d8e3d8f04ac21912850Andy Hung mState.mPosition = (uint32_t) position; 5699b4615887c23548438fd0d8e3d8f04ac21912850Andy Hung mState.mPositionSequence = incrementSequence(mState.mPositionSequence, mState.mLoopSequence); 5704ede21d9c1f957baf5e561849ff9bbe4bcbefc20Andy Hung // set patch-up variables until the mState is acknowledged by the ServerProxy. 5714ede21d9c1f957baf5e561849ff9bbe4bcbefc20Andy Hung // observed buffer position and loop count will freeze until then to give the 5724ede21d9c1f957baf5e561849ff9bbe4bcbefc20Andy Hung // illusion of a synchronous change. 5734ede21d9c1f957baf5e561849ff9bbe4bcbefc20Andy Hung if (mState.mLoopCount > 0) { // only check if loop count is changing 5744ede21d9c1f957baf5e561849ff9bbe4bcbefc20Andy Hung getBufferPositionAndLoopCount(NULL, NULL); // get last position 5754ede21d9c1f957baf5e561849ff9bbe4bcbefc20Andy Hung } 5764ede21d9c1f957baf5e561849ff9bbe4bcbefc20Andy Hung mPosLoop.mBufferPosition = position; 5774ede21d9c1f957baf5e561849ff9bbe4bcbefc20Andy Hung if (position >= mState.mLoopEnd) { 5784ede21d9c1f957baf5e561849ff9bbe4bcbefc20Andy Hung // no ongoing loop is possible if position is greater than loopEnd. 5794ede21d9c1f957baf5e561849ff9bbe4bcbefc20Andy Hung mPosLoop.mLoopCount = 0; 5804ede21d9c1f957baf5e561849ff9bbe4bcbefc20Andy Hung } 5819b4615887c23548438fd0d8e3d8f04ac21912850Andy Hung (void) mMutator.push(mState); 5829b4615887c23548438fd0d8e3d8f04ac21912850Andy Hung} 5839b4615887c23548438fd0d8e3d8f04ac21912850Andy Hung 5849b4615887c23548438fd0d8e3d8f04ac21912850Andy Hungvoid StaticAudioTrackClientProxy::setBufferPositionAndLoop(size_t position, size_t loopStart, 5859b4615887c23548438fd0d8e3d8f04ac21912850Andy Hung size_t loopEnd, int loopCount) 5869b4615887c23548438fd0d8e3d8f04ac21912850Andy Hung{ 5879b4615887c23548438fd0d8e3d8f04ac21912850Andy Hung setLoop(loopStart, loopEnd, loopCount); 5889b4615887c23548438fd0d8e3d8f04ac21912850Andy Hung setBufferPosition(position); 5899f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten} 5909f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 5919f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kastensize_t StaticAudioTrackClientProxy::getBufferPosition() 5929f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten{ 5934ede21d9c1f957baf5e561849ff9bbe4bcbefc20Andy Hung getBufferPositionAndLoopCount(NULL, NULL); 5944ede21d9c1f957baf5e561849ff9bbe4bcbefc20Andy Hung return mPosLoop.mBufferPosition; 5954ede21d9c1f957baf5e561849ff9bbe4bcbefc20Andy Hung} 5964ede21d9c1f957baf5e561849ff9bbe4bcbefc20Andy Hung 5974ede21d9c1f957baf5e561849ff9bbe4bcbefc20Andy Hungvoid StaticAudioTrackClientProxy::getBufferPositionAndLoopCount( 5984ede21d9c1f957baf5e561849ff9bbe4bcbefc20Andy Hung size_t *position, int *loopCount) 5994ede21d9c1f957baf5e561849ff9bbe4bcbefc20Andy Hung{ 6004ede21d9c1f957baf5e561849ff9bbe4bcbefc20Andy Hung if (mMutator.ack() == StaticAudioTrackSingleStateQueue::SSQ_DONE) { 6014ede21d9c1f957baf5e561849ff9bbe4bcbefc20Andy Hung if (mPosLoopObserver.poll(mPosLoop)) { 6024ede21d9c1f957baf5e561849ff9bbe4bcbefc20Andy Hung ; // a valid mPosLoop should be available if ackDone is true. 6034ede21d9c1f957baf5e561849ff9bbe4bcbefc20Andy Hung } 6044ede21d9c1f957baf5e561849ff9bbe4bcbefc20Andy Hung } 6054ede21d9c1f957baf5e561849ff9bbe4bcbefc20Andy Hung if (position != NULL) { 6064ede21d9c1f957baf5e561849ff9bbe4bcbefc20Andy Hung *position = mPosLoop.mBufferPosition; 6074ede21d9c1f957baf5e561849ff9bbe4bcbefc20Andy Hung } 6084ede21d9c1f957baf5e561849ff9bbe4bcbefc20Andy Hung if (loopCount != NULL) { 6094ede21d9c1f957baf5e561849ff9bbe4bcbefc20Andy Hung *loopCount = mPosLoop.mLoopCount; 610a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten } 6119f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten} 6129f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 6139f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten// --------------------------------------------------------------------------- 614a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten 6159f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn KastenServerProxy::ServerProxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount, 6169f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten size_t frameSize, bool isOut, bool clientInServer) 6177db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kasten : Proxy(cblk, buffers, frameCount, frameSize, isOut, clientInServer), 618ea2b9c07b34079f0dbd8610a511e006e69a15adcAndy Hung mAvailToClient(0), mFlush(0), mReleased(0), mFlushed(0) 6196ae5843c281301a9ffd1059d185620a9337e15a2Andy Hung , mTimestampMutator(&cblk->mExtendedTimestampQueue) 6209f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten{ 621e8972b0a27fac327c997fceb20d9abae1dc1d899Phil Burk cblk->mBufferSizeInFrames = frameCount; 6229f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten} 6239f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 624926b82fa9e22739686602f7ae8cf24105f14d82eilewis__attribute__((no_sanitize("integer"))) 6254bb650bb3c4f15789232f3f3cf778c5441122360Phil Burkvoid ServerProxy::flushBufferIfNeeded() 6264bb650bb3c4f15789232f3f3cf778c5441122360Phil Burk{ 6274bb650bb3c4f15789232f3f3cf778c5441122360Phil Burk audio_track_cblk_t* cblk = mCblk; 6284bb650bb3c4f15789232f3f3cf778c5441122360Phil Burk // The acquire_load is not really required. But since the write is a release_store in the 6294bb650bb3c4f15789232f3f3cf778c5441122360Phil Burk // client, using acquire_load here makes it easier for people to maintain the code, 6304bb650bb3c4f15789232f3f3cf778c5441122360Phil Burk // and the logic for communicating ipc variables seems somewhat standard, 6314bb650bb3c4f15789232f3f3cf778c5441122360Phil Burk // and there really isn't much penalty for 4 or 8 byte atomics. 6324bb650bb3c4f15789232f3f3cf778c5441122360Phil Burk int32_t flush = android_atomic_acquire_load(&cblk->u.mStreaming.mFlush); 6334bb650bb3c4f15789232f3f3cf778c5441122360Phil Burk if (flush != mFlush) { 6344bb650bb3c4f15789232f3f3cf778c5441122360Phil Burk ALOGV("ServerProxy::flushBufferIfNeeded() mStreaming.mFlush = 0x%x, mFlush = 0x%0x", 6354bb650bb3c4f15789232f3f3cf778c5441122360Phil Burk flush, mFlush); 6364bb650bb3c4f15789232f3f3cf778c5441122360Phil Burk int32_t rear = android_atomic_acquire_load(&cblk->u.mStreaming.mRear); 6374bb650bb3c4f15789232f3f3cf778c5441122360Phil Burk int32_t front = cblk->u.mStreaming.mFront; 6384bb650bb3c4f15789232f3f3cf778c5441122360Phil Burk 6394bb650bb3c4f15789232f3f3cf778c5441122360Phil Burk // effectively obtain then release whatever is in the buffer 6404bb650bb3c4f15789232f3f3cf778c5441122360Phil Burk const size_t overflowBit = mFrameCountP2 << 1; 6414bb650bb3c4f15789232f3f3cf778c5441122360Phil Burk const size_t mask = overflowBit - 1; 6424bb650bb3c4f15789232f3f3cf778c5441122360Phil Burk int32_t newFront = (front & ~mask) | (flush & mask); 6434bb650bb3c4f15789232f3f3cf778c5441122360Phil Burk ssize_t filled = rear - newFront; 6444bb650bb3c4f15789232f3f3cf778c5441122360Phil Burk if (filled >= (ssize_t)overflowBit) { 6454bb650bb3c4f15789232f3f3cf778c5441122360Phil Burk // front and rear offsets span the overflow bit of the p2 mask 6464bb650bb3c4f15789232f3f3cf778c5441122360Phil Burk // so rebasing newFront on the front offset is off by the overflow bit. 6474bb650bb3c4f15789232f3f3cf778c5441122360Phil Burk // adjust newFront to match rear offset. 6484bb650bb3c4f15789232f3f3cf778c5441122360Phil Burk ALOGV("flush wrap: filled %zx >= overflowBit %zx", filled, overflowBit); 6494bb650bb3c4f15789232f3f3cf778c5441122360Phil Burk newFront += overflowBit; 6504bb650bb3c4f15789232f3f3cf778c5441122360Phil Burk filled -= overflowBit; 6514bb650bb3c4f15789232f3f3cf778c5441122360Phil Burk } 6524bb650bb3c4f15789232f3f3cf778c5441122360Phil Burk // Rather than shutting down on a corrupt flush, just treat it as a full flush 6534bb650bb3c4f15789232f3f3cf778c5441122360Phil Burk if (!(0 <= filled && (size_t) filled <= mFrameCount)) { 6544bb650bb3c4f15789232f3f3cf778c5441122360Phil Burk ALOGE("mFlush %#x -> %#x, front %#x, rear %#x, mask %#x, newFront %#x, " 6554bb650bb3c4f15789232f3f3cf778c5441122360Phil Burk "filled %zd=%#x", 6564bb650bb3c4f15789232f3f3cf778c5441122360Phil Burk mFlush, flush, front, rear, 6574bb650bb3c4f15789232f3f3cf778c5441122360Phil Burk (unsigned)mask, newFront, filled, (unsigned)filled); 6584bb650bb3c4f15789232f3f3cf778c5441122360Phil Burk newFront = rear; 6594bb650bb3c4f15789232f3f3cf778c5441122360Phil Burk } 6604bb650bb3c4f15789232f3f3cf778c5441122360Phil Burk mFlush = flush; 6614bb650bb3c4f15789232f3f3cf778c5441122360Phil Burk android_atomic_release_store(newFront, &cblk->u.mStreaming.mFront); 6624bb650bb3c4f15789232f3f3cf778c5441122360Phil Burk // There is no danger from a false positive, so err on the side of caution 6634bb650bb3c4f15789232f3f3cf778c5441122360Phil Burk if (true /*front != newFront*/) { 6644bb650bb3c4f15789232f3f3cf778c5441122360Phil Burk int32_t old = android_atomic_or(CBLK_FUTEX_WAKE, &cblk->mFutex); 6654bb650bb3c4f15789232f3f3cf778c5441122360Phil Burk if (!(old & CBLK_FUTEX_WAKE)) { 6664bb650bb3c4f15789232f3f3cf778c5441122360Phil Burk (void) syscall(__NR_futex, &cblk->mFutex, 6674bb650bb3c4f15789232f3f3cf778c5441122360Phil Burk mClientInServer ? FUTEX_WAKE_PRIVATE : FUTEX_WAKE, 1); 6684bb650bb3c4f15789232f3f3cf778c5441122360Phil Burk } 6694bb650bb3c4f15789232f3f3cf778c5441122360Phil Burk } 6704bb650bb3c4f15789232f3f3cf778c5441122360Phil Burk mFlushed += (newFront - front) & mask; 6714bb650bb3c4f15789232f3f3cf778c5441122360Phil Burk } 6724bb650bb3c4f15789232f3f3cf778c5441122360Phil Burk} 6734bb650bb3c4f15789232f3f3cf778c5441122360Phil Burk 6744bb650bb3c4f15789232f3f3cf778c5441122360Phil Burk__attribute__((no_sanitize("integer"))) 6752e422c472c91aa7912befd0fc038d1e11f354bc1Glenn Kastenstatus_t ServerProxy::obtainBuffer(Buffer* buffer, bool ackFlush) 6769f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten{ 6777db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kasten LOG_ALWAYS_FATAL_IF(buffer == NULL || buffer->mFrameCount == 0); 6789f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (mIsShutdown) { 6797db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kasten goto no_init; 6809f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 6817db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kasten { 6829f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten audio_track_cblk_t* cblk = mCblk; 6839f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // compute number of frames available to write (AudioTrack) or read (AudioRecord), 6849f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // or use previous cached value from framesReady(), with added barrier if it omits. 6859f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten int32_t front; 6869f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten int32_t rear; 6879f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // See notes on barriers at ClientProxy::obtainBuffer() 6889f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (mIsOut) { 6894bb650bb3c4f15789232f3f3cf778c5441122360Phil Burk flushBufferIfNeeded(); // might modify mFront 6909f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten rear = android_atomic_acquire_load(&cblk->u.mStreaming.mRear); 691b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald front = cblk->u.mStreaming.mFront; 6929f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } else { 6939f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten front = android_atomic_acquire_load(&cblk->u.mStreaming.mFront); 6949f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten rear = cblk->u.mStreaming.mRear; 6959f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 6969f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten ssize_t filled = rear - front; 6979f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // pipe should not already be overfull 6989f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (!(0 <= filled && (size_t) filled <= mFrameCount)) { 6996d8018f0b7be9deec6b0acab10a0dca6e91d0fb8Glenn Kasten ALOGE("Shared memory control block is corrupt (filled=%zd, mFrameCount=%zu); shutting down", 7006d8018f0b7be9deec6b0acab10a0dca6e91d0fb8Glenn Kasten filled, mFrameCount); 7019f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mIsShutdown = true; 7029f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 7039f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (mIsShutdown) { 7047db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kasten goto no_init; 705a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten } 7069f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // don't allow filling pipe beyond the nominal size 7079f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten size_t availToServer; 7089f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (mIsOut) { 7099f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten availToServer = filled; 7109f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mAvailToClient = mFrameCount - filled; 7119f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } else { 7129f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten availToServer = mFrameCount - filled; 7139f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mAvailToClient = filled; 7149f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 7159f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // 'availToServer' may be non-contiguous, so return only the first contiguous chunk 7169f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten size_t part1; 7179f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (mIsOut) { 7189f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten front &= mFrameCountP2 - 1; 7199f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten part1 = mFrameCountP2 - front; 7209f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } else { 7219f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten rear &= mFrameCountP2 - 1; 7229f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten part1 = mFrameCountP2 - rear; 7239f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 7249f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (part1 > availToServer) { 7259f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten part1 = availToServer; 7269f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 7279f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten size_t ask = buffer->mFrameCount; 7289f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (part1 > ask) { 7299f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten part1 = ask; 7309f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 7319f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // is assignment redundant in some cases? 7329f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten buffer->mFrameCount = part1; 7339f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten buffer->mRaw = part1 > 0 ? 7349f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten &((char *) mBuffers)[(mIsOut ? front : rear) * mFrameSize] : NULL; 7359f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten buffer->mNonContig = availToServer - part1; 7362e422c472c91aa7912befd0fc038d1e11f354bc1Glenn Kasten // After flush(), allow releaseBuffer() on a previously obtained buffer; 7372e422c472c91aa7912befd0fc038d1e11f354bc1Glenn Kasten // see "Acknowledge any pending flush()" in audioflinger/Tracks.cpp. 7382e422c472c91aa7912befd0fc038d1e11f354bc1Glenn Kasten if (!ackFlush) { 7392e422c472c91aa7912befd0fc038d1e11f354bc1Glenn Kasten mUnreleased = part1; 7402e422c472c91aa7912befd0fc038d1e11f354bc1Glenn Kasten } 7419f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten return part1 > 0 ? NO_ERROR : WOULD_BLOCK; 7427db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kasten } 7437db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kastenno_init: 7447db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kasten buffer->mFrameCount = 0; 7457db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kasten buffer->mRaw = NULL; 7467db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kasten buffer->mNonContig = 0; 7477db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kasten mUnreleased = 0; 7487db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kasten return NO_INIT; 7499f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten} 750a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten 751926b82fa9e22739686602f7ae8cf24105f14d82eilewis__attribute__((no_sanitize("integer"))) 7529f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kastenvoid ServerProxy::releaseBuffer(Buffer* buffer) 7539f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten{ 7547db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kasten LOG_ALWAYS_FATAL_IF(buffer == NULL); 7559f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten size_t stepCount = buffer->mFrameCount; 7567db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kasten if (stepCount == 0 || mIsShutdown) { 7577db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kasten // prevent accidental re-use of buffer 7587db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kasten buffer->mFrameCount = 0; 7599f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten buffer->mRaw = NULL; 7609f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten buffer->mNonContig = 0; 7619f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten return; 7629f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 7637db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kasten LOG_ALWAYS_FATAL_IF(!(stepCount <= mUnreleased && mUnreleased <= mFrameCount)); 7649f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mUnreleased -= stepCount; 7659f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten audio_track_cblk_t* cblk = mCblk; 7669f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (mIsOut) { 7679f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten int32_t front = cblk->u.mStreaming.mFront; 7689f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten android_atomic_release_store(stepCount + front, &cblk->u.mStreaming.mFront); 7699f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } else { 7709f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten int32_t rear = cblk->u.mStreaming.mRear; 7719f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten android_atomic_release_store(stepCount + rear, &cblk->u.mStreaming.mRear); 772a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten } 773a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten 774844f88ccfcca95687e774bccb5e9065da61d33f8Glenn Kasten cblk->mServer += stepCount; 7753f0c902beb53a245c9db35e871607dba05b8d391Andy Hung mReleased += stepCount; 776a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten 7779f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten size_t half = mFrameCount / 2; 7789f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (half == 0) { 7799f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten half = 1; 7809f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 781fdac7c00f9201bb3a9862069145f01d37e39755bGlenn Kasten size_t minimum = (size_t) cblk->mMinimum; 7829f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (minimum == 0) { 7839f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten minimum = mIsOut ? half : 1; 7849f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } else if (minimum > half) { 7859f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten minimum = half; 7869f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 78793bb77da5481ab75c2cd6e3aa681839273c6e43dGlenn Kasten // FIXME AudioRecord wakeup needs to be optimized; it currently wakes up client every time 788ce8828a016b082f730152af2204b8ea3610dc1ecGlenn Kasten if (!mIsOut || (mAvailToClient + stepCount >= minimum)) { 78934fb29696b0f3abf61b10f8d053b1f33d501de0aMark Salyzyn ALOGV("mAvailToClient=%zu stepCount=%zu minimum=%zu", mAvailToClient, stepCount, minimum); 7900d09a9bec07b3bec78bd473ff0bfcf0a261f3f25Glenn Kasten int32_t old = android_atomic_or(CBLK_FUTEX_WAKE, &cblk->mFutex); 7910d09a9bec07b3bec78bd473ff0bfcf0a261f3f25Glenn Kasten if (!(old & CBLK_FUTEX_WAKE)) { 792ee499291404a192b059f2e04c5afc65aa6cdd74cElliott Hughes (void) syscall(__NR_futex, &cblk->mFutex, 793ee499291404a192b059f2e04c5afc65aa6cdd74cElliott Hughes mClientInServer ? FUTEX_WAKE_PRIVATE : FUTEX_WAKE, 1); 7949f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 795a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten } 7969f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 7979f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten buffer->mFrameCount = 0; 7989f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten buffer->mRaw = NULL; 7999f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten buffer->mNonContig = 0; 800a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten} 801a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten 8029f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten// --------------------------------------------------------------------------- 8039f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 804926b82fa9e22739686602f7ae8cf24105f14d82eilewis__attribute__((no_sanitize("integer"))) 8059f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kastensize_t AudioTrackServerProxy::framesReady() 806a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten{ 8079f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten LOG_ALWAYS_FATAL_IF(!mIsOut); 8089f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 8099f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (mIsShutdown) { 8109f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten return 0; 8119f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 8129f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten audio_track_cblk_t* cblk = mCblk; 813b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald 814b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald int32_t flush = cblk->u.mStreaming.mFlush; 815b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald if (flush != mFlush) { 81620f51b1ea04c410a25f214e37bcdb586e2a028ccGlenn Kasten // FIXME should return an accurate value, but over-estimate is better than under-estimate 817b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald return mFrameCount; 818b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald } 8199f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // the acquire might not be necessary since not doing a subsequent read 8209f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten int32_t rear = android_atomic_acquire_load(&cblk->u.mStreaming.mRear); 8219f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten ssize_t filled = rear - cblk->u.mStreaming.mFront; 8229f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // pipe should not already be overfull 8239f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (!(0 <= filled && (size_t) filled <= mFrameCount)) { 8246d8018f0b7be9deec6b0acab10a0dca6e91d0fb8Glenn Kasten ALOGE("Shared memory control block is corrupt (filled=%zd, mFrameCount=%zu); shutting down", 8256d8018f0b7be9deec6b0acab10a0dca6e91d0fb8Glenn Kasten filled, mFrameCount); 8269f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mIsShutdown = true; 8279f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten return 0; 8289f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 8299f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // cache this value for later use by obtainBuffer(), with added barrier 8309f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // and racy if called by normal mixer thread 8319f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // ignores flush(), so framesReady() may report a larger mFrameCount than obtainBuffer() 8329f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten return filled; 833a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten} 834a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten 835bfb1b832079bbb9426f72f3863199a54aefd02daEric Laurentbool AudioTrackServerProxy::setStreamEndDone() { 836844f88ccfcca95687e774bccb5e9065da61d33f8Glenn Kasten audio_track_cblk_t* cblk = mCblk; 837bfb1b832079bbb9426f72f3863199a54aefd02daEric Laurent bool old = 838844f88ccfcca95687e774bccb5e9065da61d33f8Glenn Kasten (android_atomic_or(CBLK_STREAM_END_DONE, &cblk->mFlags) & CBLK_STREAM_END_DONE) != 0; 839bfb1b832079bbb9426f72f3863199a54aefd02daEric Laurent if (!old) { 840e348c5b72ad889389c7c1c900c121f0fbee221b5Elliott Hughes (void) syscall(__NR_futex, &cblk->mFutex, mClientInServer ? FUTEX_WAKE_PRIVATE : FUTEX_WAKE, 841ee499291404a192b059f2e04c5afc65aa6cdd74cElliott Hughes 1); 842bfb1b832079bbb9426f72f3863199a54aefd02daEric Laurent } 843bfb1b832079bbb9426f72f3863199a54aefd02daEric Laurent return old; 844bfb1b832079bbb9426f72f3863199a54aefd02daEric Laurent} 845bfb1b832079bbb9426f72f3863199a54aefd02daEric Laurent 84682aaf94a5b18939e4d790bbc752031f3070704a3Glenn Kastenvoid AudioTrackServerProxy::tallyUnderrunFrames(uint32_t frameCount) 84782aaf94a5b18939e4d790bbc752031f3070704a3Glenn Kasten{ 848844f88ccfcca95687e774bccb5e9065da61d33f8Glenn Kasten audio_track_cblk_t* cblk = mCblk; 8492812d9ea3a3a33142dd8e23c9d949c498d6f7a12Phil Burk if (frameCount > 0) { 8502812d9ea3a3a33142dd8e23c9d949c498d6f7a12Phil Burk cblk->u.mStreaming.mUnderrunFrames += frameCount; 8512812d9ea3a3a33142dd8e23c9d949c498d6f7a12Phil Burk 8522812d9ea3a3a33142dd8e23c9d949c498d6f7a12Phil Burk if (!mUnderrunning) { // start of underrun? 8532812d9ea3a3a33142dd8e23c9d949c498d6f7a12Phil Burk mUnderrunCount++; 8542812d9ea3a3a33142dd8e23c9d949c498d6f7a12Phil Burk cblk->u.mStreaming.mUnderrunCount = mUnderrunCount; 8552812d9ea3a3a33142dd8e23c9d949c498d6f7a12Phil Burk mUnderrunning = true; 8562812d9ea3a3a33142dd8e23c9d949c498d6f7a12Phil Burk ALOGV("tallyUnderrunFrames(%3u) at uf = %u, bump mUnderrunCount = %u", 8572812d9ea3a3a33142dd8e23c9d949c498d6f7a12Phil Burk frameCount, cblk->u.mStreaming.mUnderrunFrames, mUnderrunCount); 8582812d9ea3a3a33142dd8e23c9d949c498d6f7a12Phil Burk } 85982aaf94a5b18939e4d790bbc752031f3070704a3Glenn Kasten 8602812d9ea3a3a33142dd8e23c9d949c498d6f7a12Phil Burk // FIXME also wake futex so that underrun is noticed more quickly 8612812d9ea3a3a33142dd8e23c9d949c498d6f7a12Phil Burk (void) android_atomic_or(CBLK_UNDERRUN, &cblk->mFlags); 8622812d9ea3a3a33142dd8e23c9d949c498d6f7a12Phil Burk } else { 8632812d9ea3a3a33142dd8e23c9d949c498d6f7a12Phil Burk ALOGV_IF(mUnderrunning, 8642812d9ea3a3a33142dd8e23c9d949c498d6f7a12Phil Burk "tallyUnderrunFrames(%3u) at uf = %u, underrun finished", 8652812d9ea3a3a33142dd8e23c9d949c498d6f7a12Phil Burk frameCount, cblk->u.mStreaming.mUnderrunFrames); 8662812d9ea3a3a33142dd8e23c9d949c498d6f7a12Phil Burk mUnderrunning = false; // so we can detect the next edge 8672812d9ea3a3a33142dd8e23c9d949c498d6f7a12Phil Burk } 86882aaf94a5b18939e4d790bbc752031f3070704a3Glenn Kasten} 86982aaf94a5b18939e4d790bbc752031f3070704a3Glenn Kasten 8705a8a95de6dad1a3bcf3da5a37b35766e89086e13Ricardo GarciaAudioPlaybackRate AudioTrackServerProxy::getPlaybackRate() 8718edb8dc44b8a2f81bdb5db645b6b708548771a31Andy Hung{ // do not call from multiple threads without holding lock 8725a8a95de6dad1a3bcf3da5a37b35766e89086e13Ricardo Garcia mPlaybackRateObserver.poll(mPlaybackRate); 8735a8a95de6dad1a3bcf3da5a37b35766e89086e13Ricardo Garcia return mPlaybackRate; 8748edb8dc44b8a2f81bdb5db645b6b708548771a31Andy Hung} 8758edb8dc44b8a2f81bdb5db645b6b708548771a31Andy Hung 8769f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten// --------------------------------------------------------------------------- 8779f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 8789f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn KastenStaticAudioTrackServerProxy::StaticAudioTrackServerProxy(audio_track_cblk_t* cblk, void *buffers, 8799f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten size_t frameCount, size_t frameSize) 8809f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten : AudioTrackServerProxy(cblk, buffers, frameCount, frameSize), 8814ede21d9c1f957baf5e561849ff9bbe4bcbefc20Andy Hung mObserver(&cblk->u.mStatic.mSingleStateQueue), 8824ede21d9c1f957baf5e561849ff9bbe4bcbefc20Andy Hung mPosLoopMutator(&cblk->u.mStatic.mPosLoopQueue), 883cb2129b3b568a4e31bcbda3545a468024bc972feAndy Hung mFramesReadySafe(frameCount), mFramesReady(frameCount), 884cb2129b3b568a4e31bcbda3545a468024bc972feAndy Hung mFramesReadyIsCalledByMultipleThreads(false) 885a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten{ 8869b4615887c23548438fd0d8e3d8f04ac21912850Andy Hung memset(&mState, 0, sizeof(mState)); 887a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten} 888a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten 8899f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kastenvoid StaticAudioTrackServerProxy::framesReadyIsCalledByMultipleThreads() 890a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten{ 8919f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mFramesReadyIsCalledByMultipleThreads = true; 8929f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten} 893a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten 8949f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kastensize_t StaticAudioTrackServerProxy::framesReady() 8959f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten{ 896cb2129b3b568a4e31bcbda3545a468024bc972feAndy Hung // Can't call pollPosition() from multiple threads. 8979f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (!mFramesReadyIsCalledByMultipleThreads) { 898cb2129b3b568a4e31bcbda3545a468024bc972feAndy Hung (void) pollPosition(); 899a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten } 900cb2129b3b568a4e31bcbda3545a468024bc972feAndy Hung return mFramesReadySafe; 901a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten} 902a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten 9039b4615887c23548438fd0d8e3d8f04ac21912850Andy Hungstatus_t StaticAudioTrackServerProxy::updateStateWithLoop( 9049b4615887c23548438fd0d8e3d8f04ac21912850Andy Hung StaticAudioTrackState *localState, const StaticAudioTrackState &update) const 905a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten{ 9069b4615887c23548438fd0d8e3d8f04ac21912850Andy Hung if (localState->mLoopSequence != update.mLoopSequence) { 9079f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten bool valid = false; 9089b4615887c23548438fd0d8e3d8f04ac21912850Andy Hung const size_t loopStart = update.mLoopStart; 9099b4615887c23548438fd0d8e3d8f04ac21912850Andy Hung const size_t loopEnd = update.mLoopEnd; 9109b4615887c23548438fd0d8e3d8f04ac21912850Andy Hung size_t position = localState->mPosition; 9119b4615887c23548438fd0d8e3d8f04ac21912850Andy Hung if (update.mLoopCount == 0) { 9129f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten valid = true; 9139b4615887c23548438fd0d8e3d8f04ac21912850Andy Hung } else if (update.mLoopCount >= -1) { 9149f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (loopStart < loopEnd && loopEnd <= mFrameCount && 9159f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten loopEnd - loopStart >= MIN_LOOP) { 916680b795435a5a501a56610258dce5eda40a1725dAndy Hung // If the current position is greater than the end of the loop 917680b795435a5a501a56610258dce5eda40a1725dAndy Hung // we "wrap" to the loop start. This might cause an audible pop. 918680b795435a5a501a56610258dce5eda40a1725dAndy Hung if (position >= loopEnd) { 9199b4615887c23548438fd0d8e3d8f04ac21912850Andy Hung position = loopStart; 920cb2129b3b568a4e31bcbda3545a468024bc972feAndy Hung } 9219f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten valid = true; 922a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten } 923a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten } 9249b4615887c23548438fd0d8e3d8f04ac21912850Andy Hung if (!valid || position > mFrameCount) { 9259b4615887c23548438fd0d8e3d8f04ac21912850Andy Hung return NO_INIT; 9269b4615887c23548438fd0d8e3d8f04ac21912850Andy Hung } 9279b4615887c23548438fd0d8e3d8f04ac21912850Andy Hung localState->mPosition = position; 9289b4615887c23548438fd0d8e3d8f04ac21912850Andy Hung localState->mLoopCount = update.mLoopCount; 9299b4615887c23548438fd0d8e3d8f04ac21912850Andy Hung localState->mLoopEnd = loopEnd; 9309b4615887c23548438fd0d8e3d8f04ac21912850Andy Hung localState->mLoopStart = loopStart; 9319b4615887c23548438fd0d8e3d8f04ac21912850Andy Hung localState->mLoopSequence = update.mLoopSequence; 9329b4615887c23548438fd0d8e3d8f04ac21912850Andy Hung } 9339b4615887c23548438fd0d8e3d8f04ac21912850Andy Hung return OK; 9349b4615887c23548438fd0d8e3d8f04ac21912850Andy Hung} 9359b4615887c23548438fd0d8e3d8f04ac21912850Andy Hung 9369b4615887c23548438fd0d8e3d8f04ac21912850Andy Hungstatus_t StaticAudioTrackServerProxy::updateStateWithPosition( 9379b4615887c23548438fd0d8e3d8f04ac21912850Andy Hung StaticAudioTrackState *localState, const StaticAudioTrackState &update) const 9389b4615887c23548438fd0d8e3d8f04ac21912850Andy Hung{ 9399b4615887c23548438fd0d8e3d8f04ac21912850Andy Hung if (localState->mPositionSequence != update.mPositionSequence) { 9409b4615887c23548438fd0d8e3d8f04ac21912850Andy Hung if (update.mPosition > mFrameCount) { 9419b4615887c23548438fd0d8e3d8f04ac21912850Andy Hung return NO_INIT; 9429b4615887c23548438fd0d8e3d8f04ac21912850Andy Hung } else if (localState->mLoopCount != 0 && update.mPosition >= localState->mLoopEnd) { 9439b4615887c23548438fd0d8e3d8f04ac21912850Andy Hung localState->mLoopCount = 0; // disable loop count if position is beyond loop end. 9449b4615887c23548438fd0d8e3d8f04ac21912850Andy Hung } 9459b4615887c23548438fd0d8e3d8f04ac21912850Andy Hung localState->mPosition = update.mPosition; 9469b4615887c23548438fd0d8e3d8f04ac21912850Andy Hung localState->mPositionSequence = update.mPositionSequence; 9479b4615887c23548438fd0d8e3d8f04ac21912850Andy Hung } 9489b4615887c23548438fd0d8e3d8f04ac21912850Andy Hung return OK; 9499b4615887c23548438fd0d8e3d8f04ac21912850Andy Hung} 9509b4615887c23548438fd0d8e3d8f04ac21912850Andy Hung 9519b4615887c23548438fd0d8e3d8f04ac21912850Andy Hungssize_t StaticAudioTrackServerProxy::pollPosition() 9529b4615887c23548438fd0d8e3d8f04ac21912850Andy Hung{ 9539b4615887c23548438fd0d8e3d8f04ac21912850Andy Hung StaticAudioTrackState state; 9549b4615887c23548438fd0d8e3d8f04ac21912850Andy Hung if (mObserver.poll(state)) { 9559b4615887c23548438fd0d8e3d8f04ac21912850Andy Hung StaticAudioTrackState trystate = mState; 9569b4615887c23548438fd0d8e3d8f04ac21912850Andy Hung bool result; 957cb50c54b31a83ac598530780fa8c145a3cb4a2deChad Brubaker const int32_t diffSeq = (int32_t) state.mLoopSequence - (int32_t) state.mPositionSequence; 9589b4615887c23548438fd0d8e3d8f04ac21912850Andy Hung 9599b4615887c23548438fd0d8e3d8f04ac21912850Andy Hung if (diffSeq < 0) { 9609b4615887c23548438fd0d8e3d8f04ac21912850Andy Hung result = updateStateWithLoop(&trystate, state) == OK && 9619b4615887c23548438fd0d8e3d8f04ac21912850Andy Hung updateStateWithPosition(&trystate, state) == OK; 9629b4615887c23548438fd0d8e3d8f04ac21912850Andy Hung } else { 9639b4615887c23548438fd0d8e3d8f04ac21912850Andy Hung result = updateStateWithPosition(&trystate, state) == OK && 9649b4615887c23548438fd0d8e3d8f04ac21912850Andy Hung updateStateWithLoop(&trystate, state) == OK; 9659b4615887c23548438fd0d8e3d8f04ac21912850Andy Hung } 9669b4615887c23548438fd0d8e3d8f04ac21912850Andy Hung if (!result) { 9674ede21d9c1f957baf5e561849ff9bbe4bcbefc20Andy Hung mObserver.done(); 9689b4615887c23548438fd0d8e3d8f04ac21912850Andy Hung // caution: no update occurs so server state will be inconsistent with client state. 9699f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten ALOGE("%s client pushed an invalid state, shutting down", __func__); 9709f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mIsShutdown = true; 9719f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten return (ssize_t) NO_INIT; 9729f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 9739b4615887c23548438fd0d8e3d8f04ac21912850Andy Hung mState = trystate; 9749b4615887c23548438fd0d8e3d8f04ac21912850Andy Hung if (mState.mLoopCount == -1) { 9759b4615887c23548438fd0d8e3d8f04ac21912850Andy Hung mFramesReady = INT64_MAX; 9769b4615887c23548438fd0d8e3d8f04ac21912850Andy Hung } else if (mState.mLoopCount == 0) { 9779b4615887c23548438fd0d8e3d8f04ac21912850Andy Hung mFramesReady = mFrameCount - mState.mPosition; 9789b4615887c23548438fd0d8e3d8f04ac21912850Andy Hung } else if (mState.mLoopCount > 0) { 9799b4615887c23548438fd0d8e3d8f04ac21912850Andy Hung // TODO: Later consider fixing overflow, but does not seem needed now 9809b4615887c23548438fd0d8e3d8f04ac21912850Andy Hung // as will not overflow if loopStart and loopEnd are Java "ints". 9819b4615887c23548438fd0d8e3d8f04ac21912850Andy Hung mFramesReady = int64_t(mState.mLoopCount) * (mState.mLoopEnd - mState.mLoopStart) 9829b4615887c23548438fd0d8e3d8f04ac21912850Andy Hung + mFrameCount - mState.mPosition; 9839b4615887c23548438fd0d8e3d8f04ac21912850Andy Hung } 984cb2129b3b568a4e31bcbda3545a468024bc972feAndy Hung mFramesReadySafe = clampToSize(mFramesReady); 985fdac7c00f9201bb3a9862069145f01d37e39755bGlenn Kasten // This may overflow, but client is not supposed to rely on it 9864ede21d9c1f957baf5e561849ff9bbe4bcbefc20Andy Hung StaticAudioTrackPosLoop posLoop; 9874ede21d9c1f957baf5e561849ff9bbe4bcbefc20Andy Hung 9884ede21d9c1f957baf5e561849ff9bbe4bcbefc20Andy Hung posLoop.mLoopCount = (int32_t) mState.mLoopCount; 9894ede21d9c1f957baf5e561849ff9bbe4bcbefc20Andy Hung posLoop.mBufferPosition = (uint32_t) mState.mPosition; 9904ede21d9c1f957baf5e561849ff9bbe4bcbefc20Andy Hung mPosLoopMutator.push(posLoop); 9914ede21d9c1f957baf5e561849ff9bbe4bcbefc20Andy Hung mObserver.done(); // safe to read mStatic variables. 992a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten } 9939b4615887c23548438fd0d8e3d8f04ac21912850Andy Hung return (ssize_t) mState.mPosition; 994a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten} 995a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten 996954ca45ac30539a49f179580b667b0ab1056d113Andy Hungstatus_t StaticAudioTrackServerProxy::obtainBuffer(Buffer* buffer, bool ackFlush) 997a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten{ 9989f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (mIsShutdown) { 9999f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten buffer->mFrameCount = 0; 10009f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten buffer->mRaw = NULL; 10019f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten buffer->mNonContig = 0; 10029f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mUnreleased = 0; 10039f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten return NO_INIT; 10049f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 10059f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten ssize_t positionOrStatus = pollPosition(); 10069f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (positionOrStatus < 0) { 10079f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten buffer->mFrameCount = 0; 10089f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten buffer->mRaw = NULL; 10099f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten buffer->mNonContig = 0; 10109f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mUnreleased = 0; 10119f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten return (status_t) positionOrStatus; 10129f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 10139f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten size_t position = (size_t) positionOrStatus; 1014cb2129b3b568a4e31bcbda3545a468024bc972feAndy Hung size_t end = mState.mLoopCount != 0 ? mState.mLoopEnd : mFrameCount; 10159f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten size_t avail; 1016cb2129b3b568a4e31bcbda3545a468024bc972feAndy Hung if (position < end) { 1017cb2129b3b568a4e31bcbda3545a468024bc972feAndy Hung avail = end - position; 10189f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten size_t wanted = buffer->mFrameCount; 10199f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (avail < wanted) { 10209f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten buffer->mFrameCount = avail; 10219f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } else { 10229f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten avail = wanted; 10239f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 10249f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten buffer->mRaw = &((char *) mBuffers)[position * mFrameSize]; 10259f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } else { 10269f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten avail = 0; 10279f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten buffer->mFrameCount = 0; 10289f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten buffer->mRaw = NULL; 10299f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 1030cb2129b3b568a4e31bcbda3545a468024bc972feAndy Hung // As mFramesReady is the total remaining frames in the static audio track, 1031cb2129b3b568a4e31bcbda3545a468024bc972feAndy Hung // it is always larger or equal to avail. 1032486a7135593b4b40c067e9b06f393577abfef482Andy Hung LOG_ALWAYS_FATAL_IF(mFramesReady < (int64_t) avail); 1033cb2129b3b568a4e31bcbda3545a468024bc972feAndy Hung buffer->mNonContig = mFramesReady == INT64_MAX ? SIZE_MAX : clampToSize(mFramesReady - avail); 1034954ca45ac30539a49f179580b667b0ab1056d113Andy Hung if (!ackFlush) { 1035954ca45ac30539a49f179580b667b0ab1056d113Andy Hung mUnreleased = avail; 1036954ca45ac30539a49f179580b667b0ab1056d113Andy Hung } 10379f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten return NO_ERROR; 10389f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten} 1039a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten 10409f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kastenvoid StaticAudioTrackServerProxy::releaseBuffer(Buffer* buffer) 10419f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten{ 10429f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten size_t stepCount = buffer->mFrameCount; 1043486a7135593b4b40c067e9b06f393577abfef482Andy Hung LOG_ALWAYS_FATAL_IF(!((int64_t) stepCount <= mFramesReady)); 10447db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kasten LOG_ALWAYS_FATAL_IF(!(stepCount <= mUnreleased)); 10459f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (stepCount == 0) { 10467db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kasten // prevent accidental re-use of buffer 10479f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten buffer->mRaw = NULL; 10489f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten buffer->mNonContig = 0; 10499f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten return; 1050a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten } 10519f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mUnreleased -= stepCount; 10529f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten audio_track_cblk_t* cblk = mCblk; 10539b4615887c23548438fd0d8e3d8f04ac21912850Andy Hung size_t position = mState.mPosition; 10549f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten size_t newPosition = position + stepCount; 10559f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten int32_t setFlags = 0; 10569f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (!(position <= newPosition && newPosition <= mFrameCount)) { 1057b187de1ada34a9023c05d020a4592686ba761278Glenn Kasten ALOGW("%s newPosition %zu outside [%zu, %zu]", __func__, newPosition, position, 1058b187de1ada34a9023c05d020a4592686ba761278Glenn Kasten mFrameCount); 10599f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten newPosition = mFrameCount; 10609f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } else if (mState.mLoopCount != 0 && newPosition == mState.mLoopEnd) { 1061cb2129b3b568a4e31bcbda3545a468024bc972feAndy Hung newPosition = mState.mLoopStart; 10629f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (mState.mLoopCount == -1 || --mState.mLoopCount != 0) { 10639f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten setFlags = CBLK_LOOP_CYCLE; 10649f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } else { 10659f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten setFlags = CBLK_LOOP_FINAL; 10669f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 1067a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten } 10689f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (newPosition == mFrameCount) { 10699f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten setFlags |= CBLK_BUFFER_END; 10709f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 10719b4615887c23548438fd0d8e3d8f04ac21912850Andy Hung mState.mPosition = newPosition; 1072cb2129b3b568a4e31bcbda3545a468024bc972feAndy Hung if (mFramesReady != INT64_MAX) { 1073cb2129b3b568a4e31bcbda3545a468024bc972feAndy Hung mFramesReady -= stepCount; 1074cb2129b3b568a4e31bcbda3545a468024bc972feAndy Hung } 1075cb2129b3b568a4e31bcbda3545a468024bc972feAndy Hung mFramesReadySafe = clampToSize(mFramesReady); 10769f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 1077f20e1d8df84c5fbeeace0052d100982ae39bb7a4Glenn Kasten cblk->mServer += stepCount; 10783f0c902beb53a245c9db35e871607dba05b8d391Andy Hung mReleased += stepCount; 10793f0c902beb53a245c9db35e871607dba05b8d391Andy Hung 1080fdac7c00f9201bb3a9862069145f01d37e39755bGlenn Kasten // This may overflow, but client is not supposed to rely on it 10814ede21d9c1f957baf5e561849ff9bbe4bcbefc20Andy Hung StaticAudioTrackPosLoop posLoop; 10824ede21d9c1f957baf5e561849ff9bbe4bcbefc20Andy Hung posLoop.mBufferPosition = mState.mPosition; 10834ede21d9c1f957baf5e561849ff9bbe4bcbefc20Andy Hung posLoop.mLoopCount = mState.mLoopCount; 10844ede21d9c1f957baf5e561849ff9bbe4bcbefc20Andy Hung mPosLoopMutator.push(posLoop); 10859f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (setFlags != 0) { 108696f60d8f04432a1ed503b3e24d5736d28c63c9a2Glenn Kasten (void) android_atomic_or(setFlags, &cblk->mFlags); 10879f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // this would be a good place to wake a futex 10889f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 10899f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 10909f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten buffer->mFrameCount = 0; 10919f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten buffer->mRaw = NULL; 10929f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten buffer->mNonContig = 0; 1093a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten} 1094a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten 10952812d9ea3a3a33142dd8e23c9d949c498d6f7a12Phil Burkvoid StaticAudioTrackServerProxy::tallyUnderrunFrames(uint32_t frameCount) 109682aaf94a5b18939e4d790bbc752031f3070704a3Glenn Kasten{ 109782aaf94a5b18939e4d790bbc752031f3070704a3Glenn Kasten // Unlike AudioTrackServerProxy::tallyUnderrunFrames() used for streaming tracks, 109882aaf94a5b18939e4d790bbc752031f3070704a3Glenn Kasten // we don't have a location to count underrun frames. The underrun frame counter 109982aaf94a5b18939e4d790bbc752031f3070704a3Glenn Kasten // only exists in AudioTrackSharedStreaming. Fortunately, underruns are not 110082aaf94a5b18939e4d790bbc752031f3070704a3Glenn Kasten // possible for static buffer tracks other than at end of buffer, so this is not a loss. 110182aaf94a5b18939e4d790bbc752031f3070704a3Glenn Kasten 110282aaf94a5b18939e4d790bbc752031f3070704a3Glenn Kasten // FIXME also wake futex so that underrun is noticed more quickly 11032812d9ea3a3a33142dd8e23c9d949c498d6f7a12Phil Burk if (frameCount > 0) { 11042812d9ea3a3a33142dd8e23c9d949c498d6f7a12Phil Burk (void) android_atomic_or(CBLK_UNDERRUN, &mCblk->mFlags); 11052812d9ea3a3a33142dd8e23c9d949c498d6f7a12Phil Burk } 110682aaf94a5b18939e4d790bbc752031f3070704a3Glenn Kasten} 110782aaf94a5b18939e4d790bbc752031f3070704a3Glenn Kasten 11089f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten// --------------------------------------------------------------------------- 11099f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 1110a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten} // namespace android 1111