AudioTrackShared.cpp revision 65dda4f09425ad027e27a51a3108472448d3ab8b
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) { 31cb2129b3b568a4e31bcbda3545a468024bc972feAndy Hung return x > SIZE_MAX ? SIZE_MAX : x < 0 ? 0 : (size_t) x; 32cb2129b3b568a4e31bcbda3545a468024bc972feAndy Hung} 33cb2129b3b568a4e31bcbda3545a468024bc972feAndy Hung 34a8190fc518b6769257896605f3aee091aeb60b50Glenn Kastenaudio_track_cblk_t::audio_track_cblk_t() 3574935e44734c1ec235c2b6677db3e0dbefa5ddb8Glenn Kasten : mServer(0), mFutex(0), mMinimum(0), 36c56f3426099a3cf2d07ccff8886050c7fbce140fGlenn Kasten mVolumeLR(GAIN_MINIFLOAT_PACKED_UNITY), mSampleRate(0), mSendLevel(0), mFlags(0) 37a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten{ 389f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten memset(&u, 0, sizeof(u)); 39a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten} 40a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten 419f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten// --------------------------------------------------------------------------- 429f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 439f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn KastenProxy::Proxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount, size_t frameSize, 449f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten bool isOut, bool clientInServer) 459f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten : mCblk(cblk), mBuffers(buffers), mFrameCount(frameCount), mFrameSize(frameSize), 469f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mFrameCountP2(roundup(frameCount)), mIsOut(isOut), mClientInServer(clientInServer), 477db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kasten mIsShutdown(false), mUnreleased(0) 48a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten{ 499f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten} 50a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten 519f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten// --------------------------------------------------------------------------- 529f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 539f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn KastenClientProxy::ClientProxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount, 549f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten size_t frameSize, bool isOut, bool clientInServer) 559f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten : Proxy(cblk, buffers, frameCount, frameSize, isOut, clientInServer), mEpoch(0) 569f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten{ 579f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten} 589f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 599f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kastenconst struct timespec ClientProxy::kForever = {INT_MAX /*tv_sec*/, 0 /*tv_nsec*/}; 609f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kastenconst struct timespec ClientProxy::kNonBlocking = {0 /*tv_sec*/, 0 /*tv_nsec*/}; 619f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 629f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten#define MEASURE_NS 10000000 // attempt to provide accurate timeouts if requested >= MEASURE_NS 639f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 649f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten// To facilitate quicker recovery from server failure, this value limits the timeout per each futex 659f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten// wait. However it does not protect infinite timeouts. If defined to be zero, there is no limit. 669f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten// FIXME May not be compatible with audio tunneling requirements where timeout should be in the 679f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten// order of minutes. 689f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten#define MAX_SEC 5 699f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 709f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kastenstatus_t ClientProxy::obtainBuffer(Buffer* buffer, const struct timespec *requested, 719f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten struct timespec *elapsed) 729f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten{ 737db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kasten LOG_ALWAYS_FATAL_IF(buffer == NULL || buffer->mFrameCount == 0); 749f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten struct timespec total; // total elapsed time spent waiting 759f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten total.tv_sec = 0; 769f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten total.tv_nsec = 0; 779f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten bool measure = elapsed != NULL; // whether to measure total elapsed time spent waiting 78a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten 799f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten status_t status; 809f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten enum { 819f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten TIMEOUT_ZERO, // requested == NULL || *requested == 0 829f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten TIMEOUT_INFINITE, // *requested == infinity 839f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten TIMEOUT_FINITE, // 0 < *requested < infinity 849f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten TIMEOUT_CONTINUE, // additional chances after TIMEOUT_FINITE 859f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } timeout; 869f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (requested == NULL) { 879f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten timeout = TIMEOUT_ZERO; 889f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } else if (requested->tv_sec == 0 && requested->tv_nsec == 0) { 899f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten timeout = TIMEOUT_ZERO; 909f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } else if (requested->tv_sec == INT_MAX) { 919f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten timeout = TIMEOUT_INFINITE; 929f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } else { 939f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten timeout = TIMEOUT_FINITE; 949f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (requested->tv_sec > 0 || requested->tv_nsec >= MEASURE_NS) { 959f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten measure = true; 969f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 979f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 989f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten struct timespec before; 999f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten bool beforeIsValid = false; 1009f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten audio_track_cblk_t* cblk = mCblk; 1019f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten bool ignoreInitialPendingInterrupt = true; 1029f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // check for shared memory corruption 1039f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (mIsShutdown) { 1049f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten status = NO_INIT; 1059f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten goto end; 1069f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 1079f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten for (;;) { 10896f60d8f04432a1ed503b3e24d5736d28c63c9a2Glenn Kasten int32_t flags = android_atomic_and(~CBLK_INTERRUPT, &cblk->mFlags); 1099f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // check for track invalidation by server, or server death detection 1109f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (flags & CBLK_INVALID) { 1119f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten ALOGV("Track invalidated"); 1129f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten status = DEAD_OBJECT; 1139f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten goto end; 1149f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 1159f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // check for obtainBuffer interrupted by client 1169f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (!ignoreInitialPendingInterrupt && (flags & CBLK_INTERRUPT)) { 1179f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten ALOGV("obtainBuffer() interrupted by client"); 1189f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten status = -EINTR; 1199f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten goto end; 1209f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 1219f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten ignoreInitialPendingInterrupt = false; 1229f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // compute number of frames available to write (AudioTrack) or read (AudioRecord) 1239f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten int32_t front; 1249f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten int32_t rear; 1259f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (mIsOut) { 1269f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // The barrier following the read of mFront is probably redundant. 1279f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // We're about to perform a conditional branch based on 'filled', 1289f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // which will force the processor to observe the read of mFront 1299f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // prior to allowing data writes starting at mRaw. 1309f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // However, the processor may support speculative execution, 1319f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // and be unable to undo speculative writes into shared memory. 1329f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // The barrier will prevent such speculative execution. 1339f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten front = android_atomic_acquire_load(&cblk->u.mStreaming.mFront); 1349f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten rear = cblk->u.mStreaming.mRear; 1359f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } else { 1369f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // On the other hand, this barrier is required. 1379f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten rear = android_atomic_acquire_load(&cblk->u.mStreaming.mRear); 1389f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten front = cblk->u.mStreaming.mFront; 1399f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 1409f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten ssize_t filled = rear - front; 1419f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // pipe should not be overfull 1429f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (!(0 <= filled && (size_t) filled <= mFrameCount)) { 1436dbb5e3336cfff1ad51d429fcb847307c06efd61Glenn Kasten if (mIsOut) { 14434fb29696b0f3abf61b10f8d053b1f33d501de0aMark Salyzyn ALOGE("Shared memory control block is corrupt (filled=%zd, mFrameCount=%zu); " 1456dbb5e3336cfff1ad51d429fcb847307c06efd61Glenn Kasten "shutting down", filled, mFrameCount); 1466dbb5e3336cfff1ad51d429fcb847307c06efd61Glenn Kasten mIsShutdown = true; 1476dbb5e3336cfff1ad51d429fcb847307c06efd61Glenn Kasten status = NO_INIT; 1486dbb5e3336cfff1ad51d429fcb847307c06efd61Glenn Kasten goto end; 1496dbb5e3336cfff1ad51d429fcb847307c06efd61Glenn Kasten } 1506dbb5e3336cfff1ad51d429fcb847307c06efd61Glenn Kasten // for input, sync up on overrun 1516dbb5e3336cfff1ad51d429fcb847307c06efd61Glenn Kasten filled = 0; 1526dbb5e3336cfff1ad51d429fcb847307c06efd61Glenn Kasten cblk->u.mStreaming.mFront = rear; 1536dbb5e3336cfff1ad51d429fcb847307c06efd61Glenn Kasten (void) android_atomic_or(CBLK_OVERRUN, &cblk->mFlags); 1549f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 1559f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // don't allow filling pipe beyond the nominal size 1569f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten size_t avail = mIsOut ? mFrameCount - filled : filled; 1579f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (avail > 0) { 1589f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // 'avail' may be non-contiguous, so return only the first contiguous chunk 1599f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten size_t part1; 1609f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (mIsOut) { 1619f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten rear &= mFrameCountP2 - 1; 1629f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten part1 = mFrameCountP2 - rear; 1639f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } else { 1649f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten front &= mFrameCountP2 - 1; 1659f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten part1 = mFrameCountP2 - front; 1669f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 1679f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (part1 > avail) { 1689f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten part1 = avail; 1699f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 1709f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (part1 > buffer->mFrameCount) { 1719f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten part1 = buffer->mFrameCount; 1729f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 1739f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten buffer->mFrameCount = part1; 1749f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten buffer->mRaw = part1 > 0 ? 1759f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten &((char *) mBuffers)[(mIsOut ? rear : front) * mFrameSize] : NULL; 1769f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten buffer->mNonContig = avail - part1; 1777db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kasten mUnreleased = part1; 1789f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten status = NO_ERROR; 1799f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten break; 1809f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 1819f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten struct timespec remaining; 1829f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten const struct timespec *ts; 1839f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten switch (timeout) { 1849f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten case TIMEOUT_ZERO: 1859f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten status = WOULD_BLOCK; 1869f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten goto end; 1879f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten case TIMEOUT_INFINITE: 1889f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten ts = NULL; 1899f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten break; 1909f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten case TIMEOUT_FINITE: 1919f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten timeout = TIMEOUT_CONTINUE; 1929f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (MAX_SEC == 0) { 1939f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten ts = requested; 1949f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten break; 1959f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 1969f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // fall through 1979f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten case TIMEOUT_CONTINUE: 1989f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // FIXME we do not retry if requested < 10ms? needs documentation on this state machine 1999f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (!measure || requested->tv_sec < total.tv_sec || 2009f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten (requested->tv_sec == total.tv_sec && requested->tv_nsec <= total.tv_nsec)) { 2019f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten status = TIMED_OUT; 2029f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten goto end; 2039f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 2049f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten remaining.tv_sec = requested->tv_sec - total.tv_sec; 2059f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if ((remaining.tv_nsec = requested->tv_nsec - total.tv_nsec) < 0) { 2069f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten remaining.tv_nsec += 1000000000; 2079f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten remaining.tv_sec++; 2089f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 2099f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (0 < MAX_SEC && MAX_SEC < remaining.tv_sec) { 2109f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten remaining.tv_sec = MAX_SEC; 2119f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten remaining.tv_nsec = 0; 2129f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 2139f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten ts = &remaining; 2149f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten break; 2159f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten default: 216adad3d7d935da176ff24941b4ae9edf7340e9b96Glenn Kasten LOG_ALWAYS_FATAL("obtainBuffer() timeout=%d", timeout); 2179f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten ts = NULL; 2189f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten break; 2199f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 2200d09a9bec07b3bec78bd473ff0bfcf0a261f3f25Glenn Kasten int32_t old = android_atomic_and(~CBLK_FUTEX_WAKE, &cblk->mFutex); 2210d09a9bec07b3bec78bd473ff0bfcf0a261f3f25Glenn Kasten if (!(old & CBLK_FUTEX_WAKE)) { 2229f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (measure && !beforeIsValid) { 2239f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten clock_gettime(CLOCK_MONOTONIC, &before); 2249f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten beforeIsValid = true; 2259f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 226ee499291404a192b059f2e04c5afc65aa6cdd74cElliott Hughes errno = 0; 227ee499291404a192b059f2e04c5afc65aa6cdd74cElliott Hughes (void) syscall(__NR_futex, &cblk->mFutex, 2280d09a9bec07b3bec78bd473ff0bfcf0a261f3f25Glenn Kasten mClientInServer ? FUTEX_WAIT_PRIVATE : FUTEX_WAIT, old & ~CBLK_FUTEX_WAKE, ts); 2299f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // update total elapsed time spent waiting 2309f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (measure) { 2319f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten struct timespec after; 2329f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten clock_gettime(CLOCK_MONOTONIC, &after); 2339f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten total.tv_sec += after.tv_sec - before.tv_sec; 2349f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten long deltaNs = after.tv_nsec - before.tv_nsec; 2359f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (deltaNs < 0) { 2369f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten deltaNs += 1000000000; 2379f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten total.tv_sec--; 2389f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 2399f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if ((total.tv_nsec += deltaNs) >= 1000000000) { 2409f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten total.tv_nsec -= 1000000000; 2419f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten total.tv_sec++; 2429f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 2439f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten before = after; 2449f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten beforeIsValid = true; 2459f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 246ee499291404a192b059f2e04c5afc65aa6cdd74cElliott Hughes switch (errno) { 247ee499291404a192b059f2e04c5afc65aa6cdd74cElliott Hughes case 0: // normal wakeup by server, or by binderDied() 248ee499291404a192b059f2e04c5afc65aa6cdd74cElliott Hughes case EWOULDBLOCK: // benign race condition with server 249ee499291404a192b059f2e04c5afc65aa6cdd74cElliott Hughes case EINTR: // wait was interrupted by signal or other spurious wakeup 250ee499291404a192b059f2e04c5afc65aa6cdd74cElliott Hughes case ETIMEDOUT: // time-out expired 2517db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kasten // FIXME these error/non-0 status are being dropped 2529f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten break; 2539f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten default: 254ee499291404a192b059f2e04c5afc65aa6cdd74cElliott Hughes status = errno; 255ee499291404a192b059f2e04c5afc65aa6cdd74cElliott Hughes ALOGE("%s unexpected error %s", __func__, strerror(status)); 2569f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten goto end; 2579f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 258a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten } 259a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten } 260a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten 2619f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kastenend: 2629f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (status != NO_ERROR) { 2639f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten buffer->mFrameCount = 0; 2649f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten buffer->mRaw = NULL; 2659f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten buffer->mNonContig = 0; 2667db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kasten mUnreleased = 0; 2679f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 2689f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (elapsed != NULL) { 2699f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten *elapsed = total; 270a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten } 2719f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (requested == NULL) { 2729f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten requested = &kNonBlocking; 2739f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 2749f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (measure) { 275b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald ALOGV("requested %ld.%03ld elapsed %ld.%03ld", 276b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald requested->tv_sec, requested->tv_nsec / 1000000, 277b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald total.tv_sec, total.tv_nsec / 1000000); 2789f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 2799f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten return status; 2809f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten} 281a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten 2829f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kastenvoid ClientProxy::releaseBuffer(Buffer* buffer) 2839f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten{ 2847db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kasten LOG_ALWAYS_FATAL_IF(buffer == NULL); 2859f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten size_t stepCount = buffer->mFrameCount; 2867db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kasten if (stepCount == 0 || mIsShutdown) { 2877db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kasten // prevent accidental re-use of buffer 2887db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kasten buffer->mFrameCount = 0; 2897db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kasten buffer->mRaw = NULL; 2907db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kasten buffer->mNonContig = 0; 2919f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten return; 2929f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 2937db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kasten LOG_ALWAYS_FATAL_IF(!(stepCount <= mUnreleased && mUnreleased <= mFrameCount)); 2947db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kasten mUnreleased -= stepCount; 2959f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten audio_track_cblk_t* cblk = mCblk; 2969f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // Both of these barriers are required 2979f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (mIsOut) { 2989f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten int32_t rear = cblk->u.mStreaming.mRear; 2999f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten android_atomic_release_store(stepCount + rear, &cblk->u.mStreaming.mRear); 3009f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } else { 3019f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten int32_t front = cblk->u.mStreaming.mFront; 3029f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten android_atomic_release_store(stepCount + front, &cblk->u.mStreaming.mFront); 3039f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 304a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten} 305a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten 3069f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kastenvoid ClientProxy::binderDied() 307a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten{ 3089f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten audio_track_cblk_t* cblk = mCblk; 30996f60d8f04432a1ed503b3e24d5736d28c63c9a2Glenn Kasten if (!(android_atomic_or(CBLK_INVALID, &cblk->mFlags) & CBLK_INVALID)) { 31082a69ea8b090d57bff5e02774688b546a711bbb8zunkyu.lee android_atomic_or(CBLK_FUTEX_WAKE, &cblk->mFutex); 3119f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // it seems that a FUTEX_WAKE_PRIVATE will not wake a FUTEX_WAIT, even within same process 312ee499291404a192b059f2e04c5afc65aa6cdd74cElliott Hughes (void) syscall(__NR_futex, &cblk->mFutex, mClientInServer ? FUTEX_WAKE_PRIVATE : FUTEX_WAKE, 313ee499291404a192b059f2e04c5afc65aa6cdd74cElliott Hughes 1); 3149f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 3159f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten} 316a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten 3179f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kastenvoid ClientProxy::interrupt() 3189f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten{ 3199f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten audio_track_cblk_t* cblk = mCblk; 32096f60d8f04432a1ed503b3e24d5736d28c63c9a2Glenn Kasten if (!(android_atomic_or(CBLK_INTERRUPT, &cblk->mFlags) & CBLK_INTERRUPT)) { 32182a69ea8b090d57bff5e02774688b546a711bbb8zunkyu.lee android_atomic_or(CBLK_FUTEX_WAKE, &cblk->mFutex); 322ee499291404a192b059f2e04c5afc65aa6cdd74cElliott Hughes (void) syscall(__NR_futex, &cblk->mFutex, mClientInServer ? FUTEX_WAKE_PRIVATE : FUTEX_WAKE, 323ee499291404a192b059f2e04c5afc65aa6cdd74cElliott Hughes 1); 324a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten } 3259f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten} 326a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten 32765dda4f09425ad027e27a51a3108472448d3ab8bChad Brubaker__attribute__((no_sanitize("integer"))) 3289f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kastensize_t ClientProxy::getMisalignment() 3299f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten{ 3309f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten audio_track_cblk_t* cblk = mCblk; 3319f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten return (mFrameCountP2 - (mIsOut ? cblk->u.mStreaming.mRear : cblk->u.mStreaming.mFront)) & 3329f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten (mFrameCountP2 - 1); 3339f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten} 334a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten 335cc21e4f1e41dfa17e7e2bef995fcd22c45f6bcd0Eric Laurentsize_t ClientProxy::getFramesFilled() { 336cc21e4f1e41dfa17e7e2bef995fcd22c45f6bcd0Eric Laurent audio_track_cblk_t* cblk = mCblk; 337cc21e4f1e41dfa17e7e2bef995fcd22c45f6bcd0Eric Laurent int32_t front; 338cc21e4f1e41dfa17e7e2bef995fcd22c45f6bcd0Eric Laurent int32_t rear; 339cc21e4f1e41dfa17e7e2bef995fcd22c45f6bcd0Eric Laurent 340cc21e4f1e41dfa17e7e2bef995fcd22c45f6bcd0Eric Laurent if (mIsOut) { 341cc21e4f1e41dfa17e7e2bef995fcd22c45f6bcd0Eric Laurent front = android_atomic_acquire_load(&cblk->u.mStreaming.mFront); 342cc21e4f1e41dfa17e7e2bef995fcd22c45f6bcd0Eric Laurent rear = cblk->u.mStreaming.mRear; 343cc21e4f1e41dfa17e7e2bef995fcd22c45f6bcd0Eric Laurent } else { 344cc21e4f1e41dfa17e7e2bef995fcd22c45f6bcd0Eric Laurent rear = android_atomic_acquire_load(&cblk->u.mStreaming.mRear); 345cc21e4f1e41dfa17e7e2bef995fcd22c45f6bcd0Eric Laurent front = cblk->u.mStreaming.mFront; 346cc21e4f1e41dfa17e7e2bef995fcd22c45f6bcd0Eric Laurent } 347cc21e4f1e41dfa17e7e2bef995fcd22c45f6bcd0Eric Laurent ssize_t filled = rear - front; 348cc21e4f1e41dfa17e7e2bef995fcd22c45f6bcd0Eric Laurent // pipe should not be overfull 349cc21e4f1e41dfa17e7e2bef995fcd22c45f6bcd0Eric Laurent if (!(0 <= filled && (size_t) filled <= mFrameCount)) { 35034fb29696b0f3abf61b10f8d053b1f33d501de0aMark Salyzyn ALOGE("Shared memory control block is corrupt (filled=%zd); shutting down", filled); 351cc21e4f1e41dfa17e7e2bef995fcd22c45f6bcd0Eric Laurent return 0; 352cc21e4f1e41dfa17e7e2bef995fcd22c45f6bcd0Eric Laurent } 353cc21e4f1e41dfa17e7e2bef995fcd22c45f6bcd0Eric Laurent return (size_t)filled; 354cc21e4f1e41dfa17e7e2bef995fcd22c45f6bcd0Eric Laurent} 355cc21e4f1e41dfa17e7e2bef995fcd22c45f6bcd0Eric Laurent 3569f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten// --------------------------------------------------------------------------- 3579f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 3589f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kastenvoid AudioTrackClientProxy::flush() 3599f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten{ 36020f51b1ea04c410a25f214e37bcdb586e2a028ccGlenn Kasten // This works for mFrameCountP2 <= 2^30 36120f51b1ea04c410a25f214e37bcdb586e2a028ccGlenn Kasten size_t increment = mFrameCountP2 << 1; 36220f51b1ea04c410a25f214e37bcdb586e2a028ccGlenn Kasten size_t mask = increment - 1; 36320f51b1ea04c410a25f214e37bcdb586e2a028ccGlenn Kasten audio_track_cblk_t* cblk = mCblk; 36420f51b1ea04c410a25f214e37bcdb586e2a028ccGlenn Kasten int32_t newFlush = (cblk->u.mStreaming.mRear & mask) | 36520f51b1ea04c410a25f214e37bcdb586e2a028ccGlenn Kasten ((cblk->u.mStreaming.mFlush & ~mask) + increment); 36620f51b1ea04c410a25f214e37bcdb586e2a028ccGlenn Kasten android_atomic_release_store(newFlush, &cblk->u.mStreaming.mFlush); 3679f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten} 3689f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 369bfb1b832079bbb9426f72f3863199a54aefd02daEric Laurentbool AudioTrackClientProxy::clearStreamEndDone() { 37096f60d8f04432a1ed503b3e24d5736d28c63c9a2Glenn Kasten return (android_atomic_and(~CBLK_STREAM_END_DONE, &mCblk->mFlags) & CBLK_STREAM_END_DONE) != 0; 371bfb1b832079bbb9426f72f3863199a54aefd02daEric Laurent} 372bfb1b832079bbb9426f72f3863199a54aefd02daEric Laurent 373bfb1b832079bbb9426f72f3863199a54aefd02daEric Laurentbool AudioTrackClientProxy::getStreamEndDone() const { 37496f60d8f04432a1ed503b3e24d5736d28c63c9a2Glenn Kasten return (mCblk->mFlags & CBLK_STREAM_END_DONE) != 0; 375bfb1b832079bbb9426f72f3863199a54aefd02daEric Laurent} 376bfb1b832079bbb9426f72f3863199a54aefd02daEric Laurent 377b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgeraldstatus_t AudioTrackClientProxy::waitStreamEndDone(const struct timespec *requested) 378b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald{ 379b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald struct timespec total; // total elapsed time spent waiting 380b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald total.tv_sec = 0; 381b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald total.tv_nsec = 0; 382b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald audio_track_cblk_t* cblk = mCblk; 383b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald status_t status; 384b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald enum { 385b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald TIMEOUT_ZERO, // requested == NULL || *requested == 0 386b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald TIMEOUT_INFINITE, // *requested == infinity 387b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald TIMEOUT_FINITE, // 0 < *requested < infinity 388b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald TIMEOUT_CONTINUE, // additional chances after TIMEOUT_FINITE 389b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald } timeout; 390b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald if (requested == NULL) { 391b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald timeout = TIMEOUT_ZERO; 392b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald } else if (requested->tv_sec == 0 && requested->tv_nsec == 0) { 393b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald timeout = TIMEOUT_ZERO; 394b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald } else if (requested->tv_sec == INT_MAX) { 395b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald timeout = TIMEOUT_INFINITE; 396b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald } else { 397b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald timeout = TIMEOUT_FINITE; 398b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald } 399b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald for (;;) { 40096f60d8f04432a1ed503b3e24d5736d28c63c9a2Glenn Kasten int32_t flags = android_atomic_and(~(CBLK_INTERRUPT|CBLK_STREAM_END_DONE), &cblk->mFlags); 401b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald // check for track invalidation by server, or server death detection 402b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald if (flags & CBLK_INVALID) { 403b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald ALOGV("Track invalidated"); 404b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald status = DEAD_OBJECT; 405b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald goto end; 406b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald } 407b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald if (flags & CBLK_STREAM_END_DONE) { 408b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald ALOGV("stream end received"); 409b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald status = NO_ERROR; 410b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald goto end; 411b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald } 412b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald // check for obtainBuffer interrupted by client 413b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald // check for obtainBuffer interrupted by client 414b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald if (flags & CBLK_INTERRUPT) { 415b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald ALOGV("waitStreamEndDone() interrupted by client"); 416b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald status = -EINTR; 417b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald goto end; 418b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald } 419b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald struct timespec remaining; 420b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald const struct timespec *ts; 421b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald switch (timeout) { 422b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald case TIMEOUT_ZERO: 423b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald status = WOULD_BLOCK; 424b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald goto end; 425b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald case TIMEOUT_INFINITE: 426b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald ts = NULL; 427b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald break; 428b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald case TIMEOUT_FINITE: 429b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald timeout = TIMEOUT_CONTINUE; 430b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald if (MAX_SEC == 0) { 431b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald ts = requested; 432b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald break; 433b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald } 434b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald // fall through 435b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald case TIMEOUT_CONTINUE: 436b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald // FIXME we do not retry if requested < 10ms? needs documentation on this state machine 437b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald if (requested->tv_sec < total.tv_sec || 438b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald (requested->tv_sec == total.tv_sec && requested->tv_nsec <= total.tv_nsec)) { 439b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald status = TIMED_OUT; 440b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald goto end; 441b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald } 442b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald remaining.tv_sec = requested->tv_sec - total.tv_sec; 443b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald if ((remaining.tv_nsec = requested->tv_nsec - total.tv_nsec) < 0) { 444b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald remaining.tv_nsec += 1000000000; 445b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald remaining.tv_sec++; 446b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald } 447b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald if (0 < MAX_SEC && MAX_SEC < remaining.tv_sec) { 448b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald remaining.tv_sec = MAX_SEC; 449b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald remaining.tv_nsec = 0; 450b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald } 451b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald ts = &remaining; 452b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald break; 453b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald default: 454adad3d7d935da176ff24941b4ae9edf7340e9b96Glenn Kasten LOG_ALWAYS_FATAL("waitStreamEndDone() timeout=%d", timeout); 455b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald ts = NULL; 456b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald break; 457b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald } 458b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald int32_t old = android_atomic_and(~CBLK_FUTEX_WAKE, &cblk->mFutex); 459b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald if (!(old & CBLK_FUTEX_WAKE)) { 460ee499291404a192b059f2e04c5afc65aa6cdd74cElliott Hughes errno = 0; 461ee499291404a192b059f2e04c5afc65aa6cdd74cElliott Hughes (void) syscall(__NR_futex, &cblk->mFutex, 462b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald mClientInServer ? FUTEX_WAIT_PRIVATE : FUTEX_WAIT, old & ~CBLK_FUTEX_WAKE, ts); 463ee499291404a192b059f2e04c5afc65aa6cdd74cElliott Hughes switch (errno) { 464ee499291404a192b059f2e04c5afc65aa6cdd74cElliott Hughes case 0: // normal wakeup by server, or by binderDied() 465ee499291404a192b059f2e04c5afc65aa6cdd74cElliott Hughes case EWOULDBLOCK: // benign race condition with server 466ee499291404a192b059f2e04c5afc65aa6cdd74cElliott Hughes case EINTR: // wait was interrupted by signal or other spurious wakeup 467ee499291404a192b059f2e04c5afc65aa6cdd74cElliott Hughes case ETIMEDOUT: // time-out expired 468b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald break; 469b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald default: 470ee499291404a192b059f2e04c5afc65aa6cdd74cElliott Hughes status = errno; 471ee499291404a192b059f2e04c5afc65aa6cdd74cElliott Hughes ALOGE("%s unexpected error %s", __func__, strerror(status)); 472b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald goto end; 473b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald } 474b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald } 475b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald } 476b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald 477b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgeraldend: 478b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald if (requested == NULL) { 479b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald requested = &kNonBlocking; 480b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald } 481b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald return status; 482b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald} 483b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald 4849f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten// --------------------------------------------------------------------------- 4859f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 4869f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn KastenStaticAudioTrackClientProxy::StaticAudioTrackClientProxy(audio_track_cblk_t* cblk, void *buffers, 4879f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten size_t frameCount, size_t frameSize) 4889f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten : AudioTrackClientProxy(cblk, buffers, frameCount, frameSize), 4899f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mMutator(&cblk->u.mStatic.mSingleStateQueue), mBufferPosition(0) 4909f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten{ 4919f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten} 4929f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 4939f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kastenvoid StaticAudioTrackClientProxy::flush() 4949f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten{ 495adad3d7d935da176ff24941b4ae9edf7340e9b96Glenn Kasten LOG_ALWAYS_FATAL("static flush"); 4969f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten} 4979f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 4989f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kastenvoid StaticAudioTrackClientProxy::setLoop(size_t loopStart, size_t loopEnd, int loopCount) 4999f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten{ 500fdac7c00f9201bb3a9862069145f01d37e39755bGlenn Kasten // This can only happen on a 64-bit client 501fdac7c00f9201bb3a9862069145f01d37e39755bGlenn Kasten if (loopStart > UINT32_MAX || loopEnd > UINT32_MAX) { 502fdac7c00f9201bb3a9862069145f01d37e39755bGlenn Kasten // FIXME Should return an error status 503fdac7c00f9201bb3a9862069145f01d37e39755bGlenn Kasten return; 504fdac7c00f9201bb3a9862069145f01d37e39755bGlenn Kasten } 5059f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten StaticAudioTrackState newState; 506fdac7c00f9201bb3a9862069145f01d37e39755bGlenn Kasten newState.mLoopStart = (uint32_t) loopStart; 507fdac7c00f9201bb3a9862069145f01d37e39755bGlenn Kasten newState.mLoopEnd = (uint32_t) loopEnd; 5089f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten newState.mLoopCount = loopCount; 509680b795435a5a501a56610258dce5eda40a1725dAndy Hung size_t bufferPosition; 510680b795435a5a501a56610258dce5eda40a1725dAndy Hung if (loopCount == 0 || (bufferPosition = getBufferPosition()) >= loopEnd) { 511680b795435a5a501a56610258dce5eda40a1725dAndy Hung bufferPosition = loopStart; 512680b795435a5a501a56610258dce5eda40a1725dAndy Hung } 513680b795435a5a501a56610258dce5eda40a1725dAndy Hung mBufferPosition = bufferPosition; // snapshot buffer position until loop is acknowledged. 5149f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten (void) mMutator.push(newState); 5159f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten} 5169f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 5179f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kastensize_t StaticAudioTrackClientProxy::getBufferPosition() 5189f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten{ 5199f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten size_t bufferPosition; 5209f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (mMutator.ack()) { 521fdac7c00f9201bb3a9862069145f01d37e39755bGlenn Kasten bufferPosition = (size_t) mCblk->u.mStatic.mBufferPosition; 5229f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (bufferPosition > mFrameCount) { 5239f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten bufferPosition = mFrameCount; 524a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten } 5259f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } else { 5269f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten bufferPosition = mBufferPosition; 527a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten } 5289f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten return bufferPosition; 5299f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten} 5309f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 5319f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten// --------------------------------------------------------------------------- 532a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten 5339f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn KastenServerProxy::ServerProxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount, 5349f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten size_t frameSize, bool isOut, bool clientInServer) 5357db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kasten : Proxy(cblk, buffers, frameCount, frameSize, isOut, clientInServer), 536ce8828a016b082f730152af2204b8ea3610dc1ecGlenn Kasten mAvailToClient(0), mFlush(0) 5379f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten{ 5389f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten} 5399f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 5402e422c472c91aa7912befd0fc038d1e11f354bc1Glenn Kastenstatus_t ServerProxy::obtainBuffer(Buffer* buffer, bool ackFlush) 5419f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten{ 5427db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kasten LOG_ALWAYS_FATAL_IF(buffer == NULL || buffer->mFrameCount == 0); 5439f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (mIsShutdown) { 5447db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kasten goto no_init; 5459f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 5467db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kasten { 5479f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten audio_track_cblk_t* cblk = mCblk; 5489f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // compute number of frames available to write (AudioTrack) or read (AudioRecord), 5499f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // or use previous cached value from framesReady(), with added barrier if it omits. 5509f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten int32_t front; 5519f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten int32_t rear; 5529f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // See notes on barriers at ClientProxy::obtainBuffer() 5539f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (mIsOut) { 5549f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten int32_t flush = cblk->u.mStreaming.mFlush; 5559f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten rear = android_atomic_acquire_load(&cblk->u.mStreaming.mRear); 556b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald front = cblk->u.mStreaming.mFront; 5579f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (flush != mFlush) { 558050501d11d944dcb256d37d3b86bd658d94f6a7fGlenn Kasten // effectively obtain then release whatever is in the buffer 55920f51b1ea04c410a25f214e37bcdb586e2a028ccGlenn Kasten size_t mask = (mFrameCountP2 << 1) - 1; 56020f51b1ea04c410a25f214e37bcdb586e2a028ccGlenn Kasten int32_t newFront = (front & ~mask) | (flush & mask); 56120f51b1ea04c410a25f214e37bcdb586e2a028ccGlenn Kasten ssize_t filled = rear - newFront; 56220f51b1ea04c410a25f214e37bcdb586e2a028ccGlenn Kasten // Rather than shutting down on a corrupt flush, just treat it as a full flush 56320f51b1ea04c410a25f214e37bcdb586e2a028ccGlenn Kasten if (!(0 <= filled && (size_t) filled <= mFrameCount)) { 56420f51b1ea04c410a25f214e37bcdb586e2a028ccGlenn Kasten ALOGE("mFlush %#x -> %#x, front %#x, rear %#x, mask %#x, newFront %#x, filled %d=%#x", 56520f51b1ea04c410a25f214e37bcdb586e2a028ccGlenn Kasten mFlush, flush, front, rear, mask, newFront, filled, filled); 56620f51b1ea04c410a25f214e37bcdb586e2a028ccGlenn Kasten newFront = rear; 56720f51b1ea04c410a25f214e37bcdb586e2a028ccGlenn Kasten } 56820f51b1ea04c410a25f214e37bcdb586e2a028ccGlenn Kasten mFlush = flush; 56920f51b1ea04c410a25f214e37bcdb586e2a028ccGlenn Kasten android_atomic_release_store(newFront, &cblk->u.mStreaming.mFront); 57020f51b1ea04c410a25f214e37bcdb586e2a028ccGlenn Kasten // There is no danger from a false positive, so err on the side of caution 57120f51b1ea04c410a25f214e37bcdb586e2a028ccGlenn Kasten if (true /*front != newFront*/) { 572b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald int32_t old = android_atomic_or(CBLK_FUTEX_WAKE, &cblk->mFutex); 573b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald if (!(old & CBLK_FUTEX_WAKE)) { 574ee499291404a192b059f2e04c5afc65aa6cdd74cElliott Hughes (void) syscall(__NR_futex, &cblk->mFutex, 575ee499291404a192b059f2e04c5afc65aa6cdd74cElliott Hughes mClientInServer ? FUTEX_WAKE_PRIVATE : FUTEX_WAKE, 1); 576b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald } 577b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald } 57820f51b1ea04c410a25f214e37bcdb586e2a028ccGlenn Kasten front = newFront; 579a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten } 5809f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } else { 5819f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten front = android_atomic_acquire_load(&cblk->u.mStreaming.mFront); 5829f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten rear = cblk->u.mStreaming.mRear; 5839f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 5849f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten ssize_t filled = rear - front; 5859f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // pipe should not already be overfull 5869f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (!(0 <= filled && (size_t) filled <= mFrameCount)) { 58734fb29696b0f3abf61b10f8d053b1f33d501de0aMark Salyzyn ALOGE("Shared memory control block is corrupt (filled=%zd); shutting down", filled); 5889f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mIsShutdown = true; 5899f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 5909f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (mIsShutdown) { 5917db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kasten goto no_init; 592a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten } 5939f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // don't allow filling pipe beyond the nominal size 5949f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten size_t availToServer; 5959f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (mIsOut) { 5969f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten availToServer = filled; 5979f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mAvailToClient = mFrameCount - filled; 5989f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } else { 5999f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten availToServer = mFrameCount - filled; 6009f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mAvailToClient = filled; 6019f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 6029f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // 'availToServer' may be non-contiguous, so return only the first contiguous chunk 6039f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten size_t part1; 6049f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (mIsOut) { 6059f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten front &= mFrameCountP2 - 1; 6069f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten part1 = mFrameCountP2 - front; 6079f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } else { 6089f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten rear &= mFrameCountP2 - 1; 6099f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten part1 = mFrameCountP2 - rear; 6109f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 6119f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (part1 > availToServer) { 6129f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten part1 = availToServer; 6139f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 6149f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten size_t ask = buffer->mFrameCount; 6159f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (part1 > ask) { 6169f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten part1 = ask; 6179f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 6189f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // is assignment redundant in some cases? 6199f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten buffer->mFrameCount = part1; 6209f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten buffer->mRaw = part1 > 0 ? 6219f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten &((char *) mBuffers)[(mIsOut ? front : rear) * mFrameSize] : NULL; 6229f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten buffer->mNonContig = availToServer - part1; 6232e422c472c91aa7912befd0fc038d1e11f354bc1Glenn Kasten // After flush(), allow releaseBuffer() on a previously obtained buffer; 6242e422c472c91aa7912befd0fc038d1e11f354bc1Glenn Kasten // see "Acknowledge any pending flush()" in audioflinger/Tracks.cpp. 6252e422c472c91aa7912befd0fc038d1e11f354bc1Glenn Kasten if (!ackFlush) { 6262e422c472c91aa7912befd0fc038d1e11f354bc1Glenn Kasten mUnreleased = part1; 6272e422c472c91aa7912befd0fc038d1e11f354bc1Glenn Kasten } 6289f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten return part1 > 0 ? NO_ERROR : WOULD_BLOCK; 6297db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kasten } 6307db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kastenno_init: 6317db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kasten buffer->mFrameCount = 0; 6327db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kasten buffer->mRaw = NULL; 6337db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kasten buffer->mNonContig = 0; 6347db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kasten mUnreleased = 0; 6357db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kasten return NO_INIT; 6369f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten} 637a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten 6389f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kastenvoid ServerProxy::releaseBuffer(Buffer* buffer) 6399f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten{ 6407db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kasten LOG_ALWAYS_FATAL_IF(buffer == NULL); 6419f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten size_t stepCount = buffer->mFrameCount; 6427db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kasten if (stepCount == 0 || mIsShutdown) { 6437db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kasten // prevent accidental re-use of buffer 6447db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kasten buffer->mFrameCount = 0; 6459f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten buffer->mRaw = NULL; 6469f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten buffer->mNonContig = 0; 6479f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten return; 6489f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 6497db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kasten LOG_ALWAYS_FATAL_IF(!(stepCount <= mUnreleased && mUnreleased <= mFrameCount)); 6509f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mUnreleased -= stepCount; 6519f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten audio_track_cblk_t* cblk = mCblk; 6529f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (mIsOut) { 6539f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten int32_t front = cblk->u.mStreaming.mFront; 6549f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten android_atomic_release_store(stepCount + front, &cblk->u.mStreaming.mFront); 6559f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } else { 6569f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten int32_t rear = cblk->u.mStreaming.mRear; 6579f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten android_atomic_release_store(stepCount + rear, &cblk->u.mStreaming.mRear); 658a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten } 659a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten 660844f88ccfcca95687e774bccb5e9065da61d33f8Glenn Kasten cblk->mServer += stepCount; 661a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten 6629f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten size_t half = mFrameCount / 2; 6639f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (half == 0) { 6649f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten half = 1; 6659f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 666fdac7c00f9201bb3a9862069145f01d37e39755bGlenn Kasten size_t minimum = (size_t) cblk->mMinimum; 6679f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (minimum == 0) { 6689f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten minimum = mIsOut ? half : 1; 6699f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } else if (minimum > half) { 6709f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten minimum = half; 6719f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 67293bb77da5481ab75c2cd6e3aa681839273c6e43dGlenn Kasten // FIXME AudioRecord wakeup needs to be optimized; it currently wakes up client every time 673ce8828a016b082f730152af2204b8ea3610dc1ecGlenn Kasten if (!mIsOut || (mAvailToClient + stepCount >= minimum)) { 67434fb29696b0f3abf61b10f8d053b1f33d501de0aMark Salyzyn ALOGV("mAvailToClient=%zu stepCount=%zu minimum=%zu", mAvailToClient, stepCount, minimum); 6750d09a9bec07b3bec78bd473ff0bfcf0a261f3f25Glenn Kasten int32_t old = android_atomic_or(CBLK_FUTEX_WAKE, &cblk->mFutex); 6760d09a9bec07b3bec78bd473ff0bfcf0a261f3f25Glenn Kasten if (!(old & CBLK_FUTEX_WAKE)) { 677ee499291404a192b059f2e04c5afc65aa6cdd74cElliott Hughes (void) syscall(__NR_futex, &cblk->mFutex, 678ee499291404a192b059f2e04c5afc65aa6cdd74cElliott Hughes mClientInServer ? FUTEX_WAKE_PRIVATE : FUTEX_WAKE, 1); 6799f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 680a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten } 6819f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 6829f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten buffer->mFrameCount = 0; 6839f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten buffer->mRaw = NULL; 6849f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten buffer->mNonContig = 0; 685a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten} 686a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten 6879f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten// --------------------------------------------------------------------------- 6889f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 6899f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kastensize_t AudioTrackServerProxy::framesReady() 690a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten{ 6919f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten LOG_ALWAYS_FATAL_IF(!mIsOut); 6929f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 6939f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (mIsShutdown) { 6949f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten return 0; 6959f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 6969f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten audio_track_cblk_t* cblk = mCblk; 697b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald 698b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald int32_t flush = cblk->u.mStreaming.mFlush; 699b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald if (flush != mFlush) { 70020f51b1ea04c410a25f214e37bcdb586e2a028ccGlenn Kasten // FIXME should return an accurate value, but over-estimate is better than under-estimate 701b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald return mFrameCount; 702b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald } 7039f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // the acquire might not be necessary since not doing a subsequent read 7049f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten int32_t rear = android_atomic_acquire_load(&cblk->u.mStreaming.mRear); 7059f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten ssize_t filled = rear - cblk->u.mStreaming.mFront; 7069f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // pipe should not already be overfull 7079f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (!(0 <= filled && (size_t) filled <= mFrameCount)) { 70834fb29696b0f3abf61b10f8d053b1f33d501de0aMark Salyzyn ALOGE("Shared memory control block is corrupt (filled=%zd); shutting down", filled); 7099f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mIsShutdown = true; 7109f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten return 0; 7119f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 7129f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // cache this value for later use by obtainBuffer(), with added barrier 7139f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // and racy if called by normal mixer thread 7149f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // ignores flush(), so framesReady() may report a larger mFrameCount than obtainBuffer() 7159f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten return filled; 716a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten} 717a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten 718bfb1b832079bbb9426f72f3863199a54aefd02daEric Laurentbool AudioTrackServerProxy::setStreamEndDone() { 719844f88ccfcca95687e774bccb5e9065da61d33f8Glenn Kasten audio_track_cblk_t* cblk = mCblk; 720bfb1b832079bbb9426f72f3863199a54aefd02daEric Laurent bool old = 721844f88ccfcca95687e774bccb5e9065da61d33f8Glenn Kasten (android_atomic_or(CBLK_STREAM_END_DONE, &cblk->mFlags) & CBLK_STREAM_END_DONE) != 0; 722bfb1b832079bbb9426f72f3863199a54aefd02daEric Laurent if (!old) { 723e348c5b72ad889389c7c1c900c121f0fbee221b5Elliott Hughes (void) syscall(__NR_futex, &cblk->mFutex, mClientInServer ? FUTEX_WAKE_PRIVATE : FUTEX_WAKE, 724ee499291404a192b059f2e04c5afc65aa6cdd74cElliott Hughes 1); 725bfb1b832079bbb9426f72f3863199a54aefd02daEric Laurent } 726bfb1b832079bbb9426f72f3863199a54aefd02daEric Laurent return old; 727bfb1b832079bbb9426f72f3863199a54aefd02daEric Laurent} 728bfb1b832079bbb9426f72f3863199a54aefd02daEric Laurent 72982aaf94a5b18939e4d790bbc752031f3070704a3Glenn Kastenvoid AudioTrackServerProxy::tallyUnderrunFrames(uint32_t frameCount) 73082aaf94a5b18939e4d790bbc752031f3070704a3Glenn Kasten{ 731844f88ccfcca95687e774bccb5e9065da61d33f8Glenn Kasten audio_track_cblk_t* cblk = mCblk; 732844f88ccfcca95687e774bccb5e9065da61d33f8Glenn Kasten cblk->u.mStreaming.mUnderrunFrames += frameCount; 73382aaf94a5b18939e4d790bbc752031f3070704a3Glenn Kasten 73482aaf94a5b18939e4d790bbc752031f3070704a3Glenn Kasten // FIXME also wake futex so that underrun is noticed more quickly 735844f88ccfcca95687e774bccb5e9065da61d33f8Glenn Kasten (void) android_atomic_or(CBLK_UNDERRUN, &cblk->mFlags); 73682aaf94a5b18939e4d790bbc752031f3070704a3Glenn Kasten} 73782aaf94a5b18939e4d790bbc752031f3070704a3Glenn Kasten 7389f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten// --------------------------------------------------------------------------- 7399f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 7409f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn KastenStaticAudioTrackServerProxy::StaticAudioTrackServerProxy(audio_track_cblk_t* cblk, void *buffers, 7419f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten size_t frameCount, size_t frameSize) 7429f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten : AudioTrackServerProxy(cblk, buffers, frameCount, frameSize), 7439f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mObserver(&cblk->u.mStatic.mSingleStateQueue), mPosition(0), 744cb2129b3b568a4e31bcbda3545a468024bc972feAndy Hung mFramesReadySafe(frameCount), mFramesReady(frameCount), 745cb2129b3b568a4e31bcbda3545a468024bc972feAndy Hung mFramesReadyIsCalledByMultipleThreads(false) 746a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten{ 7479f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mState.mLoopStart = 0; 7489f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mState.mLoopEnd = 0; 7499f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mState.mLoopCount = 0; 750a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten} 751a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten 7529f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kastenvoid StaticAudioTrackServerProxy::framesReadyIsCalledByMultipleThreads() 753a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten{ 7549f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mFramesReadyIsCalledByMultipleThreads = true; 7559f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten} 756a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten 7579f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kastensize_t StaticAudioTrackServerProxy::framesReady() 7589f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten{ 759cb2129b3b568a4e31bcbda3545a468024bc972feAndy Hung // Can't call pollPosition() from multiple threads. 7609f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (!mFramesReadyIsCalledByMultipleThreads) { 761cb2129b3b568a4e31bcbda3545a468024bc972feAndy Hung (void) pollPosition(); 762a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten } 763cb2129b3b568a4e31bcbda3545a468024bc972feAndy Hung return mFramesReadySafe; 764a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten} 765a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten 7669f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kastenssize_t StaticAudioTrackServerProxy::pollPosition() 767a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten{ 7689f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten size_t position = mPosition; 7699f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten StaticAudioTrackState state; 7709f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (mObserver.poll(state)) { 7719f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten bool valid = false; 7729f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten size_t loopStart = state.mLoopStart; 7739f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten size_t loopEnd = state.mLoopEnd; 7749f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (state.mLoopCount == 0) { 7759f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (loopStart > mFrameCount) { 7769f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten loopStart = mFrameCount; 777a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten } 7789f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // ignore loopEnd 7799f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mPosition = position = loopStart; 780cb2129b3b568a4e31bcbda3545a468024bc972feAndy Hung mFramesReady = mFrameCount - mPosition; 7819f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mState.mLoopCount = 0; 7829f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten valid = true; 783cb2129b3b568a4e31bcbda3545a468024bc972feAndy Hung } else if (state.mLoopCount >= -1) { 7849f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (loopStart < loopEnd && loopEnd <= mFrameCount && 7859f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten loopEnd - loopStart >= MIN_LOOP) { 786680b795435a5a501a56610258dce5eda40a1725dAndy Hung // If the current position is greater than the end of the loop 787680b795435a5a501a56610258dce5eda40a1725dAndy Hung // we "wrap" to the loop start. This might cause an audible pop. 788680b795435a5a501a56610258dce5eda40a1725dAndy Hung if (position >= loopEnd) { 7899f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mPosition = position = loopStart; 7909f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 791cb2129b3b568a4e31bcbda3545a468024bc972feAndy Hung if (state.mLoopCount == -1) { 792cb2129b3b568a4e31bcbda3545a468024bc972feAndy Hung mFramesReady = INT64_MAX; 793cb2129b3b568a4e31bcbda3545a468024bc972feAndy Hung } else { 794cb2129b3b568a4e31bcbda3545a468024bc972feAndy Hung // mFramesReady is 64 bits to handle the effective number of frames 795cb2129b3b568a4e31bcbda3545a468024bc972feAndy Hung // that the static audio track contains, including loops. 796cb2129b3b568a4e31bcbda3545a468024bc972feAndy Hung // TODO: Later consider fixing overflow, but does not seem needed now 797cb2129b3b568a4e31bcbda3545a468024bc972feAndy Hung // as will not overflow if loopStart and loopEnd are Java "ints". 798cb2129b3b568a4e31bcbda3545a468024bc972feAndy Hung mFramesReady = int64_t(state.mLoopCount) * (loopEnd - loopStart) 799cb2129b3b568a4e31bcbda3545a468024bc972feAndy Hung + mFrameCount - mPosition; 800cb2129b3b568a4e31bcbda3545a468024bc972feAndy Hung } 8019f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mState = state; 8029f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten valid = true; 803a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten } 804a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten } 805cb2129b3b568a4e31bcbda3545a468024bc972feAndy Hung if (!valid || mPosition > mFrameCount) { 8069f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten ALOGE("%s client pushed an invalid state, shutting down", __func__); 8079f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mIsShutdown = true; 8089f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten return (ssize_t) NO_INIT; 8099f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 810cb2129b3b568a4e31bcbda3545a468024bc972feAndy Hung mFramesReadySafe = clampToSize(mFramesReady); 811fdac7c00f9201bb3a9862069145f01d37e39755bGlenn Kasten // This may overflow, but client is not supposed to rely on it 812fdac7c00f9201bb3a9862069145f01d37e39755bGlenn Kasten mCblk->u.mStatic.mBufferPosition = (uint32_t) position; 813a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten } 8149f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten return (ssize_t) position; 815a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten} 816a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten 8177c7be1e05634d96d08210efb4bdeb012ffba440dGlenn Kastenstatus_t StaticAudioTrackServerProxy::obtainBuffer(Buffer* buffer, bool ackFlush __unused) 818a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten{ 8199f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (mIsShutdown) { 8209f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten buffer->mFrameCount = 0; 8219f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten buffer->mRaw = NULL; 8229f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten buffer->mNonContig = 0; 8239f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mUnreleased = 0; 8249f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten return NO_INIT; 8259f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 8269f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten ssize_t positionOrStatus = pollPosition(); 8279f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (positionOrStatus < 0) { 8289f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten buffer->mFrameCount = 0; 8299f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten buffer->mRaw = NULL; 8309f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten buffer->mNonContig = 0; 8319f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mUnreleased = 0; 8329f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten return (status_t) positionOrStatus; 8339f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 8349f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten size_t position = (size_t) positionOrStatus; 835cb2129b3b568a4e31bcbda3545a468024bc972feAndy Hung size_t end = mState.mLoopCount != 0 ? mState.mLoopEnd : mFrameCount; 8369f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten size_t avail; 837cb2129b3b568a4e31bcbda3545a468024bc972feAndy Hung if (position < end) { 838cb2129b3b568a4e31bcbda3545a468024bc972feAndy Hung avail = end - position; 8399f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten size_t wanted = buffer->mFrameCount; 8409f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (avail < wanted) { 8419f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten buffer->mFrameCount = avail; 8429f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } else { 8439f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten avail = wanted; 8449f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 8459f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten buffer->mRaw = &((char *) mBuffers)[position * mFrameSize]; 8469f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } else { 8479f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten avail = 0; 8489f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten buffer->mFrameCount = 0; 8499f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten buffer->mRaw = NULL; 8509f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 851cb2129b3b568a4e31bcbda3545a468024bc972feAndy Hung // As mFramesReady is the total remaining frames in the static audio track, 852cb2129b3b568a4e31bcbda3545a468024bc972feAndy Hung // it is always larger or equal to avail. 853cb2129b3b568a4e31bcbda3545a468024bc972feAndy Hung LOG_ALWAYS_FATAL_IF(mFramesReady < avail); 854cb2129b3b568a4e31bcbda3545a468024bc972feAndy Hung buffer->mNonContig = mFramesReady == INT64_MAX ? SIZE_MAX : clampToSize(mFramesReady - avail); 8559f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mUnreleased = avail; 8569f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten return NO_ERROR; 8579f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten} 858a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten 8599f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kastenvoid StaticAudioTrackServerProxy::releaseBuffer(Buffer* buffer) 8609f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten{ 8619f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten size_t stepCount = buffer->mFrameCount; 862cb2129b3b568a4e31bcbda3545a468024bc972feAndy Hung LOG_ALWAYS_FATAL_IF(!(stepCount <= mFramesReady)); 8637db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kasten LOG_ALWAYS_FATAL_IF(!(stepCount <= mUnreleased)); 8649f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (stepCount == 0) { 8657db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kasten // prevent accidental re-use of buffer 8669f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten buffer->mRaw = NULL; 8679f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten buffer->mNonContig = 0; 8689f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten return; 869a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten } 8709f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mUnreleased -= stepCount; 8719f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten audio_track_cblk_t* cblk = mCblk; 8729f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten size_t position = mPosition; 8739f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten size_t newPosition = position + stepCount; 8749f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten int32_t setFlags = 0; 8759f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (!(position <= newPosition && newPosition <= mFrameCount)) { 87634fb29696b0f3abf61b10f8d053b1f33d501de0aMark Salyzyn ALOGW("%s newPosition %zu outside [%zu, %zu]", __func__, newPosition, position, mFrameCount); 8779f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten newPosition = mFrameCount; 8789f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } else if (mState.mLoopCount != 0 && newPosition == mState.mLoopEnd) { 879cb2129b3b568a4e31bcbda3545a468024bc972feAndy Hung newPosition = mState.mLoopStart; 8809f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (mState.mLoopCount == -1 || --mState.mLoopCount != 0) { 8819f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten setFlags = CBLK_LOOP_CYCLE; 8829f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } else { 8839f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten setFlags = CBLK_LOOP_FINAL; 8849f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 885a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten } 8869f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (newPosition == mFrameCount) { 8879f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten setFlags |= CBLK_BUFFER_END; 8889f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 8899f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mPosition = newPosition; 890cb2129b3b568a4e31bcbda3545a468024bc972feAndy Hung if (mFramesReady != INT64_MAX) { 891cb2129b3b568a4e31bcbda3545a468024bc972feAndy Hung mFramesReady -= stepCount; 892cb2129b3b568a4e31bcbda3545a468024bc972feAndy Hung } 893cb2129b3b568a4e31bcbda3545a468024bc972feAndy Hung mFramesReadySafe = clampToSize(mFramesReady); 8949f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 895f20e1d8df84c5fbeeace0052d100982ae39bb7a4Glenn Kasten cblk->mServer += stepCount; 896fdac7c00f9201bb3a9862069145f01d37e39755bGlenn Kasten // This may overflow, but client is not supposed to rely on it 897fdac7c00f9201bb3a9862069145f01d37e39755bGlenn Kasten cblk->u.mStatic.mBufferPosition = (uint32_t) newPosition; 8989f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (setFlags != 0) { 89996f60d8f04432a1ed503b3e24d5736d28c63c9a2Glenn Kasten (void) android_atomic_or(setFlags, &cblk->mFlags); 9009f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // this would be a good place to wake a futex 9019f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 9029f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 9039f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten buffer->mFrameCount = 0; 9049f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten buffer->mRaw = NULL; 9059f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten buffer->mNonContig = 0; 906a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten} 907a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten 9087c7be1e05634d96d08210efb4bdeb012ffba440dGlenn Kastenvoid StaticAudioTrackServerProxy::tallyUnderrunFrames(uint32_t frameCount __unused) 90982aaf94a5b18939e4d790bbc752031f3070704a3Glenn Kasten{ 91082aaf94a5b18939e4d790bbc752031f3070704a3Glenn Kasten // Unlike AudioTrackServerProxy::tallyUnderrunFrames() used for streaming tracks, 91182aaf94a5b18939e4d790bbc752031f3070704a3Glenn Kasten // we don't have a location to count underrun frames. The underrun frame counter 91282aaf94a5b18939e4d790bbc752031f3070704a3Glenn Kasten // only exists in AudioTrackSharedStreaming. Fortunately, underruns are not 91382aaf94a5b18939e4d790bbc752031f3070704a3Glenn Kasten // possible for static buffer tracks other than at end of buffer, so this is not a loss. 91482aaf94a5b18939e4d790bbc752031f3070704a3Glenn Kasten 91582aaf94a5b18939e4d790bbc752031f3070704a3Glenn Kasten // FIXME also wake futex so that underrun is noticed more quickly 91682aaf94a5b18939e4d790bbc752031f3070704a3Glenn Kasten (void) android_atomic_or(CBLK_UNDERRUN, &mCblk->mFlags); 91782aaf94a5b18939e4d790bbc752031f3070704a3Glenn Kasten} 91882aaf94a5b18939e4d790bbc752031f3070704a3Glenn Kasten 9199f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten// --------------------------------------------------------------------------- 9209f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 921a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten} // namespace android 922