AudioTrackShared.cpp revision bfb1b832079bbb9426f72f3863199a54aefd02da
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> 229f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kastenextern "C" { 239f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten#include "../private/bionic_futex.h" 249f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten} 25a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten 26a8190fc518b6769257896605f3aee091aeb60b50Glenn Kastennamespace android { 27a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten 28a8190fc518b6769257896605f3aee091aeb60b50Glenn Kastenaudio_track_cblk_t::audio_track_cblk_t() 299f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten : server(0), frameCount_(0), mFutex(0), mMinimum(0), 309f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mVolumeLR(0x10001000), mSampleRate(0), mSendLevel(0), mName(0), flags(0) 31a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten{ 329f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten memset(&u, 0, sizeof(u)); 33a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten} 34a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten 359f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten// --------------------------------------------------------------------------- 369f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 379f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn KastenProxy::Proxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount, size_t frameSize, 389f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten bool isOut, bool clientInServer) 399f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten : mCblk(cblk), mBuffers(buffers), mFrameCount(frameCount), mFrameSize(frameSize), 409f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mFrameCountP2(roundup(frameCount)), mIsOut(isOut), mClientInServer(clientInServer), 417db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kasten mIsShutdown(false), mUnreleased(0) 42a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten{ 439f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten} 44a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten 459f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten// --------------------------------------------------------------------------- 469f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 479f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn KastenClientProxy::ClientProxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount, 489f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten size_t frameSize, bool isOut, bool clientInServer) 499f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten : Proxy(cblk, buffers, frameCount, frameSize, isOut, clientInServer), mEpoch(0) 509f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten{ 519f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten} 529f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 539f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kastenconst struct timespec ClientProxy::kForever = {INT_MAX /*tv_sec*/, 0 /*tv_nsec*/}; 549f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kastenconst struct timespec ClientProxy::kNonBlocking = {0 /*tv_sec*/, 0 /*tv_nsec*/}; 559f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 569f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten#define MEASURE_NS 10000000 // attempt to provide accurate timeouts if requested >= MEASURE_NS 579f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 589f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten// To facilitate quicker recovery from server failure, this value limits the timeout per each futex 599f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten// wait. However it does not protect infinite timeouts. If defined to be zero, there is no limit. 609f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten// FIXME May not be compatible with audio tunneling requirements where timeout should be in the 619f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten// order of minutes. 629f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten#define MAX_SEC 5 639f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 649f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kastenstatus_t ClientProxy::obtainBuffer(Buffer* buffer, const struct timespec *requested, 659f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten struct timespec *elapsed) 669f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten{ 677db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kasten LOG_ALWAYS_FATAL_IF(buffer == NULL || buffer->mFrameCount == 0); 689f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten struct timespec total; // total elapsed time spent waiting 699f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten total.tv_sec = 0; 709f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten total.tv_nsec = 0; 719f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten bool measure = elapsed != NULL; // whether to measure total elapsed time spent waiting 72a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten 739f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten status_t status; 749f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten enum { 759f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten TIMEOUT_ZERO, // requested == NULL || *requested == 0 769f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten TIMEOUT_INFINITE, // *requested == infinity 779f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten TIMEOUT_FINITE, // 0 < *requested < infinity 789f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten TIMEOUT_CONTINUE, // additional chances after TIMEOUT_FINITE 799f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } timeout; 809f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (requested == NULL) { 819f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten timeout = TIMEOUT_ZERO; 829f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } else if (requested->tv_sec == 0 && requested->tv_nsec == 0) { 839f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten timeout = TIMEOUT_ZERO; 849f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } else if (requested->tv_sec == INT_MAX) { 859f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten timeout = TIMEOUT_INFINITE; 869f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } else { 879f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten timeout = TIMEOUT_FINITE; 889f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (requested->tv_sec > 0 || requested->tv_nsec >= MEASURE_NS) { 899f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten measure = true; 909f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 919f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 929f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten struct timespec before; 939f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten bool beforeIsValid = false; 949f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten audio_track_cblk_t* cblk = mCblk; 959f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten bool ignoreInitialPendingInterrupt = true; 969f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // check for shared memory corruption 979f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (mIsShutdown) { 989f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten status = NO_INIT; 999f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten goto end; 1009f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 1019f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten for (;;) { 1029f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten int32_t flags = android_atomic_and(~CBLK_INTERRUPT, &cblk->flags); 1039f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // check for track invalidation by server, or server death detection 1049f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (flags & CBLK_INVALID) { 1059f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten ALOGV("Track invalidated"); 1069f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten status = DEAD_OBJECT; 1079f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten goto end; 1089f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 1099f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // check for obtainBuffer interrupted by client 1109f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (!ignoreInitialPendingInterrupt && (flags & CBLK_INTERRUPT)) { 1119f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten ALOGV("obtainBuffer() interrupted by client"); 1129f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten status = -EINTR; 1139f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten goto end; 1149f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 1159f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten ignoreInitialPendingInterrupt = false; 1169f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // compute number of frames available to write (AudioTrack) or read (AudioRecord) 1179f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten int32_t front; 1189f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten int32_t rear; 1199f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (mIsOut) { 1209f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // The barrier following the read of mFront is probably redundant. 1219f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // We're about to perform a conditional branch based on 'filled', 1229f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // which will force the processor to observe the read of mFront 1239f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // prior to allowing data writes starting at mRaw. 1249f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // However, the processor may support speculative execution, 1259f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // and be unable to undo speculative writes into shared memory. 1269f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // The barrier will prevent such speculative execution. 1279f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten front = android_atomic_acquire_load(&cblk->u.mStreaming.mFront); 1289f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten rear = cblk->u.mStreaming.mRear; 1299f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } else { 1309f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // On the other hand, this barrier is required. 1319f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten rear = android_atomic_acquire_load(&cblk->u.mStreaming.mRear); 1329f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten front = cblk->u.mStreaming.mFront; 1339f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 1349f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten ssize_t filled = rear - front; 1359f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // pipe should not be overfull 1369f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (!(0 <= filled && (size_t) filled <= mFrameCount)) { 1379f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten ALOGE("Shared memory control block is corrupt (filled=%d); shutting down", filled); 1389f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mIsShutdown = true; 1399f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten status = NO_INIT; 1409f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten goto end; 1419f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 1429f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // don't allow filling pipe beyond the nominal size 1439f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten size_t avail = mIsOut ? mFrameCount - filled : filled; 1449f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (avail > 0) { 1459f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // 'avail' may be non-contiguous, so return only the first contiguous chunk 1469f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten size_t part1; 1479f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (mIsOut) { 1489f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten rear &= mFrameCountP2 - 1; 1499f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten part1 = mFrameCountP2 - rear; 1509f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } else { 1519f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten front &= mFrameCountP2 - 1; 1529f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten part1 = mFrameCountP2 - front; 1539f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 1549f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (part1 > avail) { 1559f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten part1 = avail; 1569f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 1579f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (part1 > buffer->mFrameCount) { 1589f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten part1 = buffer->mFrameCount; 1599f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 1609f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten buffer->mFrameCount = part1; 1619f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten buffer->mRaw = part1 > 0 ? 1629f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten &((char *) mBuffers)[(mIsOut ? rear : front) * mFrameSize] : NULL; 1639f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten buffer->mNonContig = avail - part1; 1647db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kasten mUnreleased = part1; 1659f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten status = NO_ERROR; 1669f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten break; 1679f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 1689f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten struct timespec remaining; 1699f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten const struct timespec *ts; 1709f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten switch (timeout) { 1719f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten case TIMEOUT_ZERO: 1729f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten status = WOULD_BLOCK; 1739f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten goto end; 1749f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten case TIMEOUT_INFINITE: 1759f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten ts = NULL; 1769f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten break; 1779f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten case TIMEOUT_FINITE: 1789f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten timeout = TIMEOUT_CONTINUE; 1799f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (MAX_SEC == 0) { 1809f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten ts = requested; 1819f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten break; 1829f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 1839f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // fall through 1849f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten case TIMEOUT_CONTINUE: 1859f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // FIXME we do not retry if requested < 10ms? needs documentation on this state machine 1869f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (!measure || requested->tv_sec < total.tv_sec || 1879f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten (requested->tv_sec == total.tv_sec && requested->tv_nsec <= total.tv_nsec)) { 1889f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten status = TIMED_OUT; 1899f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten goto end; 1909f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 1919f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten remaining.tv_sec = requested->tv_sec - total.tv_sec; 1929f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if ((remaining.tv_nsec = requested->tv_nsec - total.tv_nsec) < 0) { 1939f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten remaining.tv_nsec += 1000000000; 1949f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten remaining.tv_sec++; 1959f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 1969f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (0 < MAX_SEC && MAX_SEC < remaining.tv_sec) { 1979f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten remaining.tv_sec = MAX_SEC; 1989f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten remaining.tv_nsec = 0; 1999f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 2009f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten ts = &remaining; 2019f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten break; 2029f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten default: 2039f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten LOG_FATAL("%s timeout=%d", timeout); 2049f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten ts = NULL; 2059f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten break; 2069f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 2070d09a9bec07b3bec78bd473ff0bfcf0a261f3f25Glenn Kasten int32_t old = android_atomic_and(~CBLK_FUTEX_WAKE, &cblk->mFutex); 2080d09a9bec07b3bec78bd473ff0bfcf0a261f3f25Glenn Kasten if (!(old & CBLK_FUTEX_WAKE)) { 2099f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten int rc; 2109f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (measure && !beforeIsValid) { 2119f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten clock_gettime(CLOCK_MONOTONIC, &before); 2129f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten beforeIsValid = true; 2139f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 2149f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten int ret = __futex_syscall4(&cblk->mFutex, 2150d09a9bec07b3bec78bd473ff0bfcf0a261f3f25Glenn Kasten mClientInServer ? FUTEX_WAIT_PRIVATE : FUTEX_WAIT, old & ~CBLK_FUTEX_WAKE, ts); 2169f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // update total elapsed time spent waiting 2179f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (measure) { 2189f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten struct timespec after; 2199f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten clock_gettime(CLOCK_MONOTONIC, &after); 2209f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten total.tv_sec += after.tv_sec - before.tv_sec; 2219f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten long deltaNs = after.tv_nsec - before.tv_nsec; 2229f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (deltaNs < 0) { 2239f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten deltaNs += 1000000000; 2249f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten total.tv_sec--; 2259f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 2269f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if ((total.tv_nsec += deltaNs) >= 1000000000) { 2279f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten total.tv_nsec -= 1000000000; 2289f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten total.tv_sec++; 2299f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 2309f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten before = after; 2319f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten beforeIsValid = true; 2329f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 2339f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten switch (ret) { 2349f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten case 0: // normal wakeup by server, or by binderDied() 2359f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten case -EWOULDBLOCK: // benign race condition with server 2369f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten case -EINTR: // wait was interrupted by signal or other spurious wakeup 2379f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten case -ETIMEDOUT: // time-out expired 2387db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kasten // FIXME these error/non-0 status are being dropped 2399f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten break; 2409f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten default: 2419f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten ALOGE("%s unexpected error %d", __func__, ret); 2429f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten status = -ret; 2439f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten goto end; 2449f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 245a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten } 246a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten } 247a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten 2489f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kastenend: 2499f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (status != NO_ERROR) { 2509f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten buffer->mFrameCount = 0; 2519f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten buffer->mRaw = NULL; 2529f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten buffer->mNonContig = 0; 2537db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kasten mUnreleased = 0; 2549f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 2559f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (elapsed != NULL) { 2569f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten *elapsed = total; 257a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten } 2589f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (requested == NULL) { 2599f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten requested = &kNonBlocking; 2609f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 2619f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (measure) { 2629f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten ALOGV("requested %d.%03d elapsed %d.%03d", requested->tv_sec, requested->tv_nsec / 1000000, 2639f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten total.tv_sec, total.tv_nsec / 1000000); 2649f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 2659f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten return status; 2669f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten} 267a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten 2689f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kastenvoid ClientProxy::releaseBuffer(Buffer* buffer) 2699f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten{ 2707db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kasten LOG_ALWAYS_FATAL_IF(buffer == NULL); 2719f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten size_t stepCount = buffer->mFrameCount; 2727db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kasten if (stepCount == 0 || mIsShutdown) { 2737db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kasten // prevent accidental re-use of buffer 2747db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kasten buffer->mFrameCount = 0; 2757db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kasten buffer->mRaw = NULL; 2767db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kasten buffer->mNonContig = 0; 2779f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten return; 2789f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 2797db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kasten LOG_ALWAYS_FATAL_IF(!(stepCount <= mUnreleased && mUnreleased <= mFrameCount)); 2807db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kasten mUnreleased -= stepCount; 2819f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten audio_track_cblk_t* cblk = mCblk; 2829f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // Both of these barriers are required 2839f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (mIsOut) { 2849f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten int32_t rear = cblk->u.mStreaming.mRear; 2859f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten android_atomic_release_store(stepCount + rear, &cblk->u.mStreaming.mRear); 2869f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } else { 2879f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten int32_t front = cblk->u.mStreaming.mFront; 2889f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten android_atomic_release_store(stepCount + front, &cblk->u.mStreaming.mFront); 2899f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 290a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten} 291a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten 2929f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kastenvoid ClientProxy::binderDied() 293a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten{ 2949f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten audio_track_cblk_t* cblk = mCblk; 2959f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (!(android_atomic_or(CBLK_INVALID, &cblk->flags) & CBLK_INVALID)) { 2969f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // it seems that a FUTEX_WAKE_PRIVATE will not wake a FUTEX_WAIT, even within same process 2979f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten (void) __futex_syscall3(&cblk->mFutex, mClientInServer ? FUTEX_WAKE_PRIVATE : FUTEX_WAKE, 2989f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 1); 2999f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 3009f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten} 301a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten 3029f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kastenvoid ClientProxy::interrupt() 3039f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten{ 3049f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten audio_track_cblk_t* cblk = mCblk; 3059f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (!(android_atomic_or(CBLK_INTERRUPT, &cblk->flags) & CBLK_INTERRUPT)) { 3069f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten (void) __futex_syscall3(&cblk->mFutex, mClientInServer ? FUTEX_WAKE_PRIVATE : FUTEX_WAKE, 3079f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 1); 308a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten } 3099f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten} 310a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten 3119f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kastensize_t ClientProxy::getMisalignment() 3129f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten{ 3139f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten audio_track_cblk_t* cblk = mCblk; 3149f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten return (mFrameCountP2 - (mIsOut ? cblk->u.mStreaming.mRear : cblk->u.mStreaming.mFront)) & 3159f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten (mFrameCountP2 - 1); 3169f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten} 317a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten 3189f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten// --------------------------------------------------------------------------- 3199f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 3209f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kastenvoid AudioTrackClientProxy::flush() 3219f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten{ 3229f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mCblk->u.mStreaming.mFlush++; 3239f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten} 3249f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 325bfb1b832079bbb9426f72f3863199a54aefd02daEric Laurentbool AudioTrackClientProxy::clearStreamEndDone() { 326bfb1b832079bbb9426f72f3863199a54aefd02daEric Laurent return android_atomic_and(~CBLK_STREAM_END_DONE, &mCblk->flags) & CBLK_STREAM_END_DONE; 327bfb1b832079bbb9426f72f3863199a54aefd02daEric Laurent} 328bfb1b832079bbb9426f72f3863199a54aefd02daEric Laurent 329bfb1b832079bbb9426f72f3863199a54aefd02daEric Laurentbool AudioTrackClientProxy::getStreamEndDone() const { 330bfb1b832079bbb9426f72f3863199a54aefd02daEric Laurent return (mCblk->flags & CBLK_STREAM_END_DONE) != 0; 331bfb1b832079bbb9426f72f3863199a54aefd02daEric Laurent} 332bfb1b832079bbb9426f72f3863199a54aefd02daEric Laurent 3339f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten// --------------------------------------------------------------------------- 3349f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 3359f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn KastenStaticAudioTrackClientProxy::StaticAudioTrackClientProxy(audio_track_cblk_t* cblk, void *buffers, 3369f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten size_t frameCount, size_t frameSize) 3379f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten : AudioTrackClientProxy(cblk, buffers, frameCount, frameSize), 3389f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mMutator(&cblk->u.mStatic.mSingleStateQueue), mBufferPosition(0) 3399f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten{ 3409f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten} 3419f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 3429f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kastenvoid StaticAudioTrackClientProxy::flush() 3439f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten{ 3449f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten LOG_FATAL("static flush"); 3459f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten} 3469f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 3479f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kastenvoid StaticAudioTrackClientProxy::setLoop(size_t loopStart, size_t loopEnd, int loopCount) 3489f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten{ 3499f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten StaticAudioTrackState newState; 3509f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten newState.mLoopStart = loopStart; 3519f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten newState.mLoopEnd = loopEnd; 3529f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten newState.mLoopCount = loopCount; 3539f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mBufferPosition = loopStart; 3549f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten (void) mMutator.push(newState); 3559f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten} 3569f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 3579f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kastensize_t StaticAudioTrackClientProxy::getBufferPosition() 3589f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten{ 3599f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten size_t bufferPosition; 3609f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (mMutator.ack()) { 3619f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten bufferPosition = mCblk->u.mStatic.mBufferPosition; 3629f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (bufferPosition > mFrameCount) { 3639f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten bufferPosition = mFrameCount; 364a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten } 3659f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } else { 3669f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten bufferPosition = mBufferPosition; 367a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten } 3689f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten return bufferPosition; 3699f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten} 3709f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 3719f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten// --------------------------------------------------------------------------- 372a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten 3739f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn KastenServerProxy::ServerProxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount, 3749f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten size_t frameSize, bool isOut, bool clientInServer) 3757db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kasten : Proxy(cblk, buffers, frameCount, frameSize, isOut, clientInServer), 3769f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mAvailToClient(0), mFlush(0), mDeferWake(false) 3779f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten{ 3789f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten} 3799f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 3809f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kastenstatus_t ServerProxy::obtainBuffer(Buffer* buffer) 3819f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten{ 3827db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kasten LOG_ALWAYS_FATAL_IF(buffer == NULL || buffer->mFrameCount == 0); 3839f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (mIsShutdown) { 3847db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kasten goto no_init; 3859f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 3867db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kasten { 3879f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten audio_track_cblk_t* cblk = mCblk; 3889f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // compute number of frames available to write (AudioTrack) or read (AudioRecord), 3899f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // or use previous cached value from framesReady(), with added barrier if it omits. 3909f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten int32_t front; 3919f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten int32_t rear; 3929f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // See notes on barriers at ClientProxy::obtainBuffer() 3939f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (mIsOut) { 3949f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten int32_t flush = cblk->u.mStreaming.mFlush; 3959f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten rear = android_atomic_acquire_load(&cblk->u.mStreaming.mRear); 3969f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (flush != mFlush) { 3979f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten front = rear; 3989f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mFlush = flush; 399050501d11d944dcb256d37d3b86bd658d94f6a7fGlenn Kasten // effectively obtain then release whatever is in the buffer 400050501d11d944dcb256d37d3b86bd658d94f6a7fGlenn Kasten android_atomic_release_store(rear, &cblk->u.mStreaming.mFront); 4019f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } else { 4029f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten front = cblk->u.mStreaming.mFront; 403a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten } 4049f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } else { 4059f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten front = android_atomic_acquire_load(&cblk->u.mStreaming.mFront); 4069f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten rear = cblk->u.mStreaming.mRear; 4079f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 4089f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten ssize_t filled = rear - front; 4099f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // pipe should not already be overfull 4109f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (!(0 <= filled && (size_t) filled <= mFrameCount)) { 4119f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten ALOGE("Shared memory control block is corrupt (filled=%d); shutting down", filled); 4129f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mIsShutdown = true; 4139f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 4149f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (mIsShutdown) { 4157db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kasten goto no_init; 416a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten } 4179f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // don't allow filling pipe beyond the nominal size 4189f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten size_t availToServer; 4199f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (mIsOut) { 4209f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten availToServer = filled; 4219f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mAvailToClient = mFrameCount - filled; 4229f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } else { 4239f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten availToServer = mFrameCount - filled; 4249f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mAvailToClient = filled; 4259f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 4269f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // 'availToServer' may be non-contiguous, so return only the first contiguous chunk 4279f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten size_t part1; 4289f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (mIsOut) { 4299f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten front &= mFrameCountP2 - 1; 4309f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten part1 = mFrameCountP2 - front; 4319f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } else { 4329f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten rear &= mFrameCountP2 - 1; 4339f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten part1 = mFrameCountP2 - rear; 4349f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 4359f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (part1 > availToServer) { 4369f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten part1 = availToServer; 4379f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 4389f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten size_t ask = buffer->mFrameCount; 4399f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (part1 > ask) { 4409f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten part1 = ask; 4419f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 4429f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // is assignment redundant in some cases? 4439f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten buffer->mFrameCount = part1; 4449f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten buffer->mRaw = part1 > 0 ? 4459f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten &((char *) mBuffers)[(mIsOut ? front : rear) * mFrameSize] : NULL; 4469f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten buffer->mNonContig = availToServer - part1; 4479f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mUnreleased = part1; 4489f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // optimization to avoid waking up the client too early 4499f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // FIXME need to test for recording 4509f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mDeferWake = part1 < ask && availToServer >= ask; 4519f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten return part1 > 0 ? NO_ERROR : WOULD_BLOCK; 4527db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kasten } 4537db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kastenno_init: 4547db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kasten buffer->mFrameCount = 0; 4557db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kasten buffer->mRaw = NULL; 4567db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kasten buffer->mNonContig = 0; 4577db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kasten mUnreleased = 0; 4587db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kasten return NO_INIT; 4599f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten} 460a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten 4619f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kastenvoid ServerProxy::releaseBuffer(Buffer* buffer) 4629f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten{ 4637db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kasten LOG_ALWAYS_FATAL_IF(buffer == NULL); 4649f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten size_t stepCount = buffer->mFrameCount; 4657db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kasten if (stepCount == 0 || mIsShutdown) { 4667db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kasten // prevent accidental re-use of buffer 4677db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kasten buffer->mFrameCount = 0; 4689f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten buffer->mRaw = NULL; 4699f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten buffer->mNonContig = 0; 4709f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten return; 4719f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 4727db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kasten LOG_ALWAYS_FATAL_IF(!(stepCount <= mUnreleased && mUnreleased <= mFrameCount)); 4739f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mUnreleased -= stepCount; 4749f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten audio_track_cblk_t* cblk = mCblk; 4759f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (mIsOut) { 4769f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten int32_t front = cblk->u.mStreaming.mFront; 4779f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten android_atomic_release_store(stepCount + front, &cblk->u.mStreaming.mFront); 4789f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } else { 4799f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten int32_t rear = cblk->u.mStreaming.mRear; 4809f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten android_atomic_release_store(stepCount + rear, &cblk->u.mStreaming.mRear); 481a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten } 482a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten 4839f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mCblk->server += stepCount; 484a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten 4859f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten size_t half = mFrameCount / 2; 4869f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (half == 0) { 4879f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten half = 1; 4889f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 4899f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten size_t minimum = cblk->mMinimum; 4909f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (minimum == 0) { 4919f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten minimum = mIsOut ? half : 1; 4929f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } else if (minimum > half) { 4939f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten minimum = half; 4949f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 49593bb77da5481ab75c2cd6e3aa681839273c6e43dGlenn Kasten // FIXME AudioRecord wakeup needs to be optimized; it currently wakes up client every time 49693bb77da5481ab75c2cd6e3aa681839273c6e43dGlenn Kasten if (!mIsOut || (!mDeferWake && mAvailToClient + stepCount >= minimum)) { 4979f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten ALOGV("mAvailToClient=%u stepCount=%u minimum=%u", mAvailToClient, stepCount, minimum); 4980d09a9bec07b3bec78bd473ff0bfcf0a261f3f25Glenn Kasten int32_t old = android_atomic_or(CBLK_FUTEX_WAKE, &cblk->mFutex); 4990d09a9bec07b3bec78bd473ff0bfcf0a261f3f25Glenn Kasten if (!(old & CBLK_FUTEX_WAKE)) { 5009f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten (void) __futex_syscall3(&cblk->mFutex, 5019f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mClientInServer ? FUTEX_WAKE_PRIVATE : FUTEX_WAKE, 1); 5029f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 503a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten } 5049f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 5059f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten buffer->mFrameCount = 0; 5069f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten buffer->mRaw = NULL; 5079f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten buffer->mNonContig = 0; 508a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten} 509a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten 5109f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten// --------------------------------------------------------------------------- 5119f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 5129f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kastensize_t AudioTrackServerProxy::framesReady() 513a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten{ 5149f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten LOG_ALWAYS_FATAL_IF(!mIsOut); 5159f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 5169f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (mIsShutdown) { 5179f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten return 0; 5189f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 5199f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten audio_track_cblk_t* cblk = mCblk; 5209f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // the acquire might not be necessary since not doing a subsequent read 5219f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten int32_t rear = android_atomic_acquire_load(&cblk->u.mStreaming.mRear); 5229f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten ssize_t filled = rear - cblk->u.mStreaming.mFront; 5239f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // pipe should not already be overfull 5249f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (!(0 <= filled && (size_t) filled <= mFrameCount)) { 5259f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten ALOGE("Shared memory control block is corrupt (filled=%d); shutting down", filled); 5269f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mIsShutdown = true; 5279f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten return 0; 5289f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 5299f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // cache this value for later use by obtainBuffer(), with added barrier 5309f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // and racy if called by normal mixer thread 5319f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // ignores flush(), so framesReady() may report a larger mFrameCount than obtainBuffer() 5329f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten return filled; 533a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten} 534a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten 535bfb1b832079bbb9426f72f3863199a54aefd02daEric Laurentbool AudioTrackServerProxy::setStreamEndDone() { 536bfb1b832079bbb9426f72f3863199a54aefd02daEric Laurent bool old = 537bfb1b832079bbb9426f72f3863199a54aefd02daEric Laurent (android_atomic_or(CBLK_STREAM_END_DONE, &mCblk->flags) & CBLK_STREAM_END_DONE) != 0; 538bfb1b832079bbb9426f72f3863199a54aefd02daEric Laurent if (!old) { 539bfb1b832079bbb9426f72f3863199a54aefd02daEric Laurent (void) __futex_syscall3(&mCblk->mFutex, mClientInServer ? FUTEX_WAKE_PRIVATE : FUTEX_WAKE, 540bfb1b832079bbb9426f72f3863199a54aefd02daEric Laurent 1); 541bfb1b832079bbb9426f72f3863199a54aefd02daEric Laurent } 542bfb1b832079bbb9426f72f3863199a54aefd02daEric Laurent return old; 543bfb1b832079bbb9426f72f3863199a54aefd02daEric Laurent} 544bfb1b832079bbb9426f72f3863199a54aefd02daEric Laurent 5459f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten// --------------------------------------------------------------------------- 5469f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 5479f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn KastenStaticAudioTrackServerProxy::StaticAudioTrackServerProxy(audio_track_cblk_t* cblk, void *buffers, 5489f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten size_t frameCount, size_t frameSize) 5499f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten : AudioTrackServerProxy(cblk, buffers, frameCount, frameSize), 5509f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mObserver(&cblk->u.mStatic.mSingleStateQueue), mPosition(0), 5519f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mEnd(frameCount), mFramesReadyIsCalledByMultipleThreads(false) 552a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten{ 5539f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mState.mLoopStart = 0; 5549f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mState.mLoopEnd = 0; 5559f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mState.mLoopCount = 0; 556a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten} 557a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten 5589f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kastenvoid StaticAudioTrackServerProxy::framesReadyIsCalledByMultipleThreads() 559a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten{ 5609f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mFramesReadyIsCalledByMultipleThreads = true; 5619f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten} 562a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten 5639f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kastensize_t StaticAudioTrackServerProxy::framesReady() 5649f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten{ 5659f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // FIXME 5669f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // This is racy if called by normal mixer thread, 5679f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // as we're reading 2 independent variables without a lock. 5689f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // Can't call mObserver.poll(), as we might be called from wrong thread. 5699f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // If looping is enabled, should return a higher number (since includes non-contiguous). 5709f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten size_t position = mPosition; 5719f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (!mFramesReadyIsCalledByMultipleThreads) { 5729f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten ssize_t positionOrStatus = pollPosition(); 5739f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (positionOrStatus >= 0) { 5749f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten position = (size_t) positionOrStatus; 5759f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 576a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten } 5779f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten size_t end = mEnd; 5789f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten return position < end ? end - position : 0; 579a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten} 580a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten 5819f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kastenssize_t StaticAudioTrackServerProxy::pollPosition() 582a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten{ 5839f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten size_t position = mPosition; 5849f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten StaticAudioTrackState state; 5859f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (mObserver.poll(state)) { 5869f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten bool valid = false; 5879f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten size_t loopStart = state.mLoopStart; 5889f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten size_t loopEnd = state.mLoopEnd; 5899f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (state.mLoopCount == 0) { 5909f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (loopStart > mFrameCount) { 5919f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten loopStart = mFrameCount; 592a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten } 5939f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // ignore loopEnd 5949f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mPosition = position = loopStart; 5959f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mEnd = mFrameCount; 5969f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mState.mLoopCount = 0; 5979f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten valid = true; 5989f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } else { 5999f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (loopStart < loopEnd && loopEnd <= mFrameCount && 6009f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten loopEnd - loopStart >= MIN_LOOP) { 6019f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (!(loopStart <= position && position < loopEnd)) { 6029f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mPosition = position = loopStart; 6039f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 6049f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mEnd = loopEnd; 6059f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mState = state; 6069f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten valid = true; 607a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten } 608a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten } 6099f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (!valid) { 6109f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten ALOGE("%s client pushed an invalid state, shutting down", __func__); 6119f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mIsShutdown = true; 6129f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten return (ssize_t) NO_INIT; 6139f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 6149f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mCblk->u.mStatic.mBufferPosition = position; 615a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten } 6169f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten return (ssize_t) position; 617a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten} 618a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten 6199f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kastenstatus_t StaticAudioTrackServerProxy::obtainBuffer(Buffer* buffer) 620a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten{ 6219f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (mIsShutdown) { 6229f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten buffer->mFrameCount = 0; 6239f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten buffer->mRaw = NULL; 6249f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten buffer->mNonContig = 0; 6259f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mUnreleased = 0; 6269f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten return NO_INIT; 6279f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 6289f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten ssize_t positionOrStatus = pollPosition(); 6299f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (positionOrStatus < 0) { 6309f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten buffer->mFrameCount = 0; 6319f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten buffer->mRaw = NULL; 6329f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten buffer->mNonContig = 0; 6339f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mUnreleased = 0; 6349f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten return (status_t) positionOrStatus; 6359f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 6369f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten size_t position = (size_t) positionOrStatus; 6379f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten size_t avail; 6389f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (position < mEnd) { 6399f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten avail = mEnd - position; 6409f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten size_t wanted = buffer->mFrameCount; 6419f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (avail < wanted) { 6429f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten buffer->mFrameCount = avail; 6439f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } else { 6449f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten avail = wanted; 6459f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 6469f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten buffer->mRaw = &((char *) mBuffers)[position * mFrameSize]; 6479f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } else { 6489f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten avail = 0; 6499f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten buffer->mFrameCount = 0; 6509f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten buffer->mRaw = NULL; 6519f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 6529f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten buffer->mNonContig = 0; // FIXME should be > 0 for looping 6539f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mUnreleased = avail; 6549f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten return NO_ERROR; 6559f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten} 656a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten 6579f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kastenvoid StaticAudioTrackServerProxy::releaseBuffer(Buffer* buffer) 6589f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten{ 6599f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten size_t stepCount = buffer->mFrameCount; 6607db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kasten LOG_ALWAYS_FATAL_IF(!(stepCount <= mUnreleased)); 6619f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (stepCount == 0) { 6627db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kasten // prevent accidental re-use of buffer 6639f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten buffer->mRaw = NULL; 6649f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten buffer->mNonContig = 0; 6659f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten return; 666a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten } 6679f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mUnreleased -= stepCount; 6689f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten audio_track_cblk_t* cblk = mCblk; 6699f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten size_t position = mPosition; 6709f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten size_t newPosition = position + stepCount; 6719f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten int32_t setFlags = 0; 6729f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (!(position <= newPosition && newPosition <= mFrameCount)) { 6739f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten ALOGW("%s newPosition %u outside [%u, %u]", __func__, newPosition, position, mFrameCount); 6749f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten newPosition = mFrameCount; 6759f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } else if (mState.mLoopCount != 0 && newPosition == mState.mLoopEnd) { 6769f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (mState.mLoopCount == -1 || --mState.mLoopCount != 0) { 6779f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten newPosition = mState.mLoopStart; 6789f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten setFlags = CBLK_LOOP_CYCLE; 6799f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } else { 6809f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mEnd = mFrameCount; // this is what allows playback to continue after the loop 6819f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten setFlags = CBLK_LOOP_FINAL; 6829f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 683a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten } 6849f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (newPosition == mFrameCount) { 6859f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten setFlags |= CBLK_BUFFER_END; 6869f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 6879f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten mPosition = newPosition; 6889f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 6899f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten cblk->server += stepCount; 6909f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten cblk->u.mStatic.mBufferPosition = newPosition; 6919f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten if (setFlags != 0) { 6929f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten (void) android_atomic_or(setFlags, &cblk->flags); 6939f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten // this would be a good place to wake a futex 6949f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten } 6959f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 6969f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten buffer->mFrameCount = 0; 6979f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten buffer->mRaw = NULL; 6989f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten buffer->mNonContig = 0; 699a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten} 700a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten 7019f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten// --------------------------------------------------------------------------- 7029f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten 703a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten} // namespace android 704