AudioTrackShared.cpp revision cb2129b3b568a4e31bcbda3545a468024bc972fe
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)) {
3109f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        // it seems that a FUTEX_WAKE_PRIVATE will not wake a FUTEX_WAIT, even within same process
311ee499291404a192b059f2e04c5afc65aa6cdd74cElliott Hughes        (void) syscall(__NR_futex, &cblk->mFutex, mClientInServer ? FUTEX_WAKE_PRIVATE : FUTEX_WAKE,
312ee499291404a192b059f2e04c5afc65aa6cdd74cElliott Hughes                1);
3139f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
3149f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten}
315a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten
3169f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kastenvoid ClientProxy::interrupt()
3179f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten{
3189f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    audio_track_cblk_t* cblk = mCblk;
31996f60d8f04432a1ed503b3e24d5736d28c63c9a2Glenn Kasten    if (!(android_atomic_or(CBLK_INTERRUPT, &cblk->mFlags) & CBLK_INTERRUPT)) {
320ee499291404a192b059f2e04c5afc65aa6cdd74cElliott Hughes        (void) syscall(__NR_futex, &cblk->mFutex, mClientInServer ? FUTEX_WAKE_PRIVATE : FUTEX_WAKE,
321ee499291404a192b059f2e04c5afc65aa6cdd74cElliott Hughes                1);
322a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten    }
3239f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten}
324a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten
3259f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kastensize_t ClientProxy::getMisalignment()
3269f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten{
3279f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    audio_track_cblk_t* cblk = mCblk;
3289f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    return (mFrameCountP2 - (mIsOut ? cblk->u.mStreaming.mRear : cblk->u.mStreaming.mFront)) &
3299f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            (mFrameCountP2 - 1);
3309f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten}
331a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten
332cc21e4f1e41dfa17e7e2bef995fcd22c45f6bcd0Eric Laurentsize_t ClientProxy::getFramesFilled() {
333cc21e4f1e41dfa17e7e2bef995fcd22c45f6bcd0Eric Laurent    audio_track_cblk_t* cblk = mCblk;
334cc21e4f1e41dfa17e7e2bef995fcd22c45f6bcd0Eric Laurent    int32_t front;
335cc21e4f1e41dfa17e7e2bef995fcd22c45f6bcd0Eric Laurent    int32_t rear;
336cc21e4f1e41dfa17e7e2bef995fcd22c45f6bcd0Eric Laurent
337cc21e4f1e41dfa17e7e2bef995fcd22c45f6bcd0Eric Laurent    if (mIsOut) {
338cc21e4f1e41dfa17e7e2bef995fcd22c45f6bcd0Eric Laurent        front = android_atomic_acquire_load(&cblk->u.mStreaming.mFront);
339cc21e4f1e41dfa17e7e2bef995fcd22c45f6bcd0Eric Laurent        rear = cblk->u.mStreaming.mRear;
340cc21e4f1e41dfa17e7e2bef995fcd22c45f6bcd0Eric Laurent    } else {
341cc21e4f1e41dfa17e7e2bef995fcd22c45f6bcd0Eric Laurent        rear = android_atomic_acquire_load(&cblk->u.mStreaming.mRear);
342cc21e4f1e41dfa17e7e2bef995fcd22c45f6bcd0Eric Laurent        front = cblk->u.mStreaming.mFront;
343cc21e4f1e41dfa17e7e2bef995fcd22c45f6bcd0Eric Laurent    }
344cc21e4f1e41dfa17e7e2bef995fcd22c45f6bcd0Eric Laurent    ssize_t filled = rear - front;
345cc21e4f1e41dfa17e7e2bef995fcd22c45f6bcd0Eric Laurent    // pipe should not be overfull
346cc21e4f1e41dfa17e7e2bef995fcd22c45f6bcd0Eric Laurent    if (!(0 <= filled && (size_t) filled <= mFrameCount)) {
34734fb29696b0f3abf61b10f8d053b1f33d501de0aMark Salyzyn        ALOGE("Shared memory control block is corrupt (filled=%zd); shutting down", filled);
348cc21e4f1e41dfa17e7e2bef995fcd22c45f6bcd0Eric Laurent        return 0;
349cc21e4f1e41dfa17e7e2bef995fcd22c45f6bcd0Eric Laurent    }
350cc21e4f1e41dfa17e7e2bef995fcd22c45f6bcd0Eric Laurent    return (size_t)filled;
351cc21e4f1e41dfa17e7e2bef995fcd22c45f6bcd0Eric Laurent}
352cc21e4f1e41dfa17e7e2bef995fcd22c45f6bcd0Eric Laurent
3539f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten// ---------------------------------------------------------------------------
3549f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
3559f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kastenvoid AudioTrackClientProxy::flush()
3569f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten{
35720f51b1ea04c410a25f214e37bcdb586e2a028ccGlenn Kasten    // This works for mFrameCountP2 <= 2^30
35820f51b1ea04c410a25f214e37bcdb586e2a028ccGlenn Kasten    size_t increment = mFrameCountP2 << 1;
35920f51b1ea04c410a25f214e37bcdb586e2a028ccGlenn Kasten    size_t mask = increment - 1;
36020f51b1ea04c410a25f214e37bcdb586e2a028ccGlenn Kasten    audio_track_cblk_t* cblk = mCblk;
36120f51b1ea04c410a25f214e37bcdb586e2a028ccGlenn Kasten    int32_t newFlush = (cblk->u.mStreaming.mRear & mask) |
36220f51b1ea04c410a25f214e37bcdb586e2a028ccGlenn Kasten                        ((cblk->u.mStreaming.mFlush & ~mask) + increment);
36320f51b1ea04c410a25f214e37bcdb586e2a028ccGlenn Kasten    android_atomic_release_store(newFlush, &cblk->u.mStreaming.mFlush);
3649f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten}
3659f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
366bfb1b832079bbb9426f72f3863199a54aefd02daEric Laurentbool AudioTrackClientProxy::clearStreamEndDone() {
36796f60d8f04432a1ed503b3e24d5736d28c63c9a2Glenn Kasten    return (android_atomic_and(~CBLK_STREAM_END_DONE, &mCblk->mFlags) & CBLK_STREAM_END_DONE) != 0;
368bfb1b832079bbb9426f72f3863199a54aefd02daEric Laurent}
369bfb1b832079bbb9426f72f3863199a54aefd02daEric Laurent
370bfb1b832079bbb9426f72f3863199a54aefd02daEric Laurentbool AudioTrackClientProxy::getStreamEndDone() const {
37196f60d8f04432a1ed503b3e24d5736d28c63c9a2Glenn Kasten    return (mCblk->mFlags & CBLK_STREAM_END_DONE) != 0;
372bfb1b832079bbb9426f72f3863199a54aefd02daEric Laurent}
373bfb1b832079bbb9426f72f3863199a54aefd02daEric Laurent
374b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgeraldstatus_t AudioTrackClientProxy::waitStreamEndDone(const struct timespec *requested)
375b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald{
376b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald    struct timespec total;          // total elapsed time spent waiting
377b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald    total.tv_sec = 0;
378b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald    total.tv_nsec = 0;
379b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald    audio_track_cblk_t* cblk = mCblk;
380b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald    status_t status;
381b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald    enum {
382b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald        TIMEOUT_ZERO,       // requested == NULL || *requested == 0
383b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald        TIMEOUT_INFINITE,   // *requested == infinity
384b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald        TIMEOUT_FINITE,     // 0 < *requested < infinity
385b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald        TIMEOUT_CONTINUE,   // additional chances after TIMEOUT_FINITE
386b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald    } timeout;
387b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald    if (requested == NULL) {
388b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald        timeout = TIMEOUT_ZERO;
389b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald    } else if (requested->tv_sec == 0 && requested->tv_nsec == 0) {
390b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald        timeout = TIMEOUT_ZERO;
391b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald    } else if (requested->tv_sec == INT_MAX) {
392b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald        timeout = TIMEOUT_INFINITE;
393b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald    } else {
394b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald        timeout = TIMEOUT_FINITE;
395b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald    }
396b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald    for (;;) {
39796f60d8f04432a1ed503b3e24d5736d28c63c9a2Glenn Kasten        int32_t flags = android_atomic_and(~(CBLK_INTERRUPT|CBLK_STREAM_END_DONE), &cblk->mFlags);
398b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald        // check for track invalidation by server, or server death detection
399b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald        if (flags & CBLK_INVALID) {
400b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald            ALOGV("Track invalidated");
401b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald            status = DEAD_OBJECT;
402b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald            goto end;
403b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald        }
404b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald        if (flags & CBLK_STREAM_END_DONE) {
405b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald            ALOGV("stream end received");
406b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald            status = NO_ERROR;
407b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald            goto end;
408b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald        }
409b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald        // check for obtainBuffer interrupted by client
410b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald        // check for obtainBuffer interrupted by client
411b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald        if (flags & CBLK_INTERRUPT) {
412b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald            ALOGV("waitStreamEndDone() interrupted by client");
413b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald            status = -EINTR;
414b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald            goto end;
415b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald        }
416b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald        struct timespec remaining;
417b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald        const struct timespec *ts;
418b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald        switch (timeout) {
419b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald        case TIMEOUT_ZERO:
420b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald            status = WOULD_BLOCK;
421b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald            goto end;
422b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald        case TIMEOUT_INFINITE:
423b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald            ts = NULL;
424b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald            break;
425b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald        case TIMEOUT_FINITE:
426b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald            timeout = TIMEOUT_CONTINUE;
427b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald            if (MAX_SEC == 0) {
428b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald                ts = requested;
429b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald                break;
430b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald            }
431b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald            // fall through
432b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald        case TIMEOUT_CONTINUE:
433b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald            // FIXME we do not retry if requested < 10ms? needs documentation on this state machine
434b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald            if (requested->tv_sec < total.tv_sec ||
435b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald                    (requested->tv_sec == total.tv_sec && requested->tv_nsec <= total.tv_nsec)) {
436b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald                status = TIMED_OUT;
437b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald                goto end;
438b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald            }
439b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald            remaining.tv_sec = requested->tv_sec - total.tv_sec;
440b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald            if ((remaining.tv_nsec = requested->tv_nsec - total.tv_nsec) < 0) {
441b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald                remaining.tv_nsec += 1000000000;
442b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald                remaining.tv_sec++;
443b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald            }
444b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald            if (0 < MAX_SEC && MAX_SEC < remaining.tv_sec) {
445b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald                remaining.tv_sec = MAX_SEC;
446b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald                remaining.tv_nsec = 0;
447b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald            }
448b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald            ts = &remaining;
449b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald            break;
450b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald        default:
451adad3d7d935da176ff24941b4ae9edf7340e9b96Glenn Kasten            LOG_ALWAYS_FATAL("waitStreamEndDone() timeout=%d", timeout);
452b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald            ts = NULL;
453b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald            break;
454b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald        }
455b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald        int32_t old = android_atomic_and(~CBLK_FUTEX_WAKE, &cblk->mFutex);
456b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald        if (!(old & CBLK_FUTEX_WAKE)) {
457ee499291404a192b059f2e04c5afc65aa6cdd74cElliott Hughes            errno = 0;
458ee499291404a192b059f2e04c5afc65aa6cdd74cElliott Hughes            (void) syscall(__NR_futex, &cblk->mFutex,
459b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald                    mClientInServer ? FUTEX_WAIT_PRIVATE : FUTEX_WAIT, old & ~CBLK_FUTEX_WAKE, ts);
460ee499291404a192b059f2e04c5afc65aa6cdd74cElliott Hughes            switch (errno) {
461ee499291404a192b059f2e04c5afc65aa6cdd74cElliott Hughes            case 0:            // normal wakeup by server, or by binderDied()
462ee499291404a192b059f2e04c5afc65aa6cdd74cElliott Hughes            case EWOULDBLOCK:  // benign race condition with server
463ee499291404a192b059f2e04c5afc65aa6cdd74cElliott Hughes            case EINTR:        // wait was interrupted by signal or other spurious wakeup
464ee499291404a192b059f2e04c5afc65aa6cdd74cElliott Hughes            case ETIMEDOUT:    // time-out expired
465b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald                break;
466b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald            default:
467ee499291404a192b059f2e04c5afc65aa6cdd74cElliott Hughes                status = errno;
468ee499291404a192b059f2e04c5afc65aa6cdd74cElliott Hughes                ALOGE("%s unexpected error %s", __func__, strerror(status));
469b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald                goto end;
470b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald            }
471b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald        }
472b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald    }
473b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald
474b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgeraldend:
475b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald    if (requested == NULL) {
476b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald        requested = &kNonBlocking;
477b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald    }
478b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald    return status;
479b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald}
480b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald
4819f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten// ---------------------------------------------------------------------------
4829f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
4839f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn KastenStaticAudioTrackClientProxy::StaticAudioTrackClientProxy(audio_track_cblk_t* cblk, void *buffers,
4849f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        size_t frameCount, size_t frameSize)
4859f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    : AudioTrackClientProxy(cblk, buffers, frameCount, frameSize),
4869f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten      mMutator(&cblk->u.mStatic.mSingleStateQueue), mBufferPosition(0)
4879f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten{
4889f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten}
4899f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
4909f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kastenvoid StaticAudioTrackClientProxy::flush()
4919f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten{
492adad3d7d935da176ff24941b4ae9edf7340e9b96Glenn Kasten    LOG_ALWAYS_FATAL("static flush");
4939f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten}
4949f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
4959f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kastenvoid StaticAudioTrackClientProxy::setLoop(size_t loopStart, size_t loopEnd, int loopCount)
4969f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten{
497fdac7c00f9201bb3a9862069145f01d37e39755bGlenn Kasten    // This can only happen on a 64-bit client
498fdac7c00f9201bb3a9862069145f01d37e39755bGlenn Kasten    if (loopStart > UINT32_MAX || loopEnd > UINT32_MAX) {
499fdac7c00f9201bb3a9862069145f01d37e39755bGlenn Kasten        // FIXME Should return an error status
500fdac7c00f9201bb3a9862069145f01d37e39755bGlenn Kasten        return;
501fdac7c00f9201bb3a9862069145f01d37e39755bGlenn Kasten    }
5029f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    StaticAudioTrackState newState;
503fdac7c00f9201bb3a9862069145f01d37e39755bGlenn Kasten    newState.mLoopStart = (uint32_t) loopStart;
504fdac7c00f9201bb3a9862069145f01d37e39755bGlenn Kasten    newState.mLoopEnd = (uint32_t) loopEnd;
5059f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    newState.mLoopCount = loopCount;
5069f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    mBufferPosition = loopStart;
5079f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    (void) mMutator.push(newState);
5089f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten}
5099f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
5109f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kastensize_t StaticAudioTrackClientProxy::getBufferPosition()
5119f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten{
5129f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    size_t bufferPosition;
5139f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (mMutator.ack()) {
514fdac7c00f9201bb3a9862069145f01d37e39755bGlenn Kasten        bufferPosition = (size_t) mCblk->u.mStatic.mBufferPosition;
5159f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        if (bufferPosition > mFrameCount) {
5169f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            bufferPosition = mFrameCount;
517a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten        }
5189f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    } else {
5199f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        bufferPosition = mBufferPosition;
520a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten    }
5219f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    return bufferPosition;
5229f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten}
5239f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
5249f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten// ---------------------------------------------------------------------------
525a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten
5269f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn KastenServerProxy::ServerProxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount,
5279f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        size_t frameSize, bool isOut, bool clientInServer)
5287db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kasten    : Proxy(cblk, buffers, frameCount, frameSize, isOut, clientInServer),
529ce8828a016b082f730152af2204b8ea3610dc1ecGlenn Kasten      mAvailToClient(0), mFlush(0)
5309f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten{
5319f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten}
5329f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
5332e422c472c91aa7912befd0fc038d1e11f354bc1Glenn Kastenstatus_t ServerProxy::obtainBuffer(Buffer* buffer, bool ackFlush)
5349f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten{
5357db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kasten    LOG_ALWAYS_FATAL_IF(buffer == NULL || buffer->mFrameCount == 0);
5369f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (mIsShutdown) {
5377db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kasten        goto no_init;
5389f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
5397db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kasten    {
5409f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    audio_track_cblk_t* cblk = mCblk;
5419f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    // compute number of frames available to write (AudioTrack) or read (AudioRecord),
5429f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    // or use previous cached value from framesReady(), with added barrier if it omits.
5439f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    int32_t front;
5449f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    int32_t rear;
5459f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    // See notes on barriers at ClientProxy::obtainBuffer()
5469f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (mIsOut) {
5479f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        int32_t flush = cblk->u.mStreaming.mFlush;
5489f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        rear = android_atomic_acquire_load(&cblk->u.mStreaming.mRear);
549b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald        front = cblk->u.mStreaming.mFront;
5509f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        if (flush != mFlush) {
551050501d11d944dcb256d37d3b86bd658d94f6a7fGlenn Kasten            // effectively obtain then release whatever is in the buffer
55220f51b1ea04c410a25f214e37bcdb586e2a028ccGlenn Kasten            size_t mask = (mFrameCountP2 << 1) - 1;
55320f51b1ea04c410a25f214e37bcdb586e2a028ccGlenn Kasten            int32_t newFront = (front & ~mask) | (flush & mask);
55420f51b1ea04c410a25f214e37bcdb586e2a028ccGlenn Kasten            ssize_t filled = rear - newFront;
55520f51b1ea04c410a25f214e37bcdb586e2a028ccGlenn Kasten            // Rather than shutting down on a corrupt flush, just treat it as a full flush
55620f51b1ea04c410a25f214e37bcdb586e2a028ccGlenn Kasten            if (!(0 <= filled && (size_t) filled <= mFrameCount)) {
55720f51b1ea04c410a25f214e37bcdb586e2a028ccGlenn Kasten                ALOGE("mFlush %#x -> %#x, front %#x, rear %#x, mask %#x, newFront %#x, filled %d=%#x",
55820f51b1ea04c410a25f214e37bcdb586e2a028ccGlenn Kasten                        mFlush, flush, front, rear, mask, newFront, filled, filled);
55920f51b1ea04c410a25f214e37bcdb586e2a028ccGlenn Kasten                newFront = rear;
56020f51b1ea04c410a25f214e37bcdb586e2a028ccGlenn Kasten            }
56120f51b1ea04c410a25f214e37bcdb586e2a028ccGlenn Kasten            mFlush = flush;
56220f51b1ea04c410a25f214e37bcdb586e2a028ccGlenn Kasten            android_atomic_release_store(newFront, &cblk->u.mStreaming.mFront);
56320f51b1ea04c410a25f214e37bcdb586e2a028ccGlenn Kasten            // There is no danger from a false positive, so err on the side of caution
56420f51b1ea04c410a25f214e37bcdb586e2a028ccGlenn Kasten            if (true /*front != newFront*/) {
565b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald                int32_t old = android_atomic_or(CBLK_FUTEX_WAKE, &cblk->mFutex);
566b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald                if (!(old & CBLK_FUTEX_WAKE)) {
567ee499291404a192b059f2e04c5afc65aa6cdd74cElliott Hughes                    (void) syscall(__NR_futex, &cblk->mFutex,
568ee499291404a192b059f2e04c5afc65aa6cdd74cElliott Hughes                            mClientInServer ? FUTEX_WAKE_PRIVATE : FUTEX_WAKE, 1);
569b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald                }
570b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald            }
57120f51b1ea04c410a25f214e37bcdb586e2a028ccGlenn Kasten            front = newFront;
572a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten        }
5739f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    } else {
5749f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        front = android_atomic_acquire_load(&cblk->u.mStreaming.mFront);
5759f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        rear = cblk->u.mStreaming.mRear;
5769f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
5779f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    ssize_t filled = rear - front;
5789f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    // pipe should not already be overfull
5799f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (!(0 <= filled && (size_t) filled <= mFrameCount)) {
58034fb29696b0f3abf61b10f8d053b1f33d501de0aMark Salyzyn        ALOGE("Shared memory control block is corrupt (filled=%zd); shutting down", filled);
5819f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        mIsShutdown = true;
5829f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
5839f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (mIsShutdown) {
5847db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kasten        goto no_init;
585a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten    }
5869f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    // don't allow filling pipe beyond the nominal size
5879f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    size_t availToServer;
5889f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (mIsOut) {
5899f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        availToServer = filled;
5909f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        mAvailToClient = mFrameCount - filled;
5919f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    } else {
5929f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        availToServer = mFrameCount - filled;
5939f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        mAvailToClient = filled;
5949f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
5959f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    // 'availToServer' may be non-contiguous, so return only the first contiguous chunk
5969f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    size_t part1;
5979f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (mIsOut) {
5989f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        front &= mFrameCountP2 - 1;
5999f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        part1 = mFrameCountP2 - front;
6009f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    } else {
6019f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        rear &= mFrameCountP2 - 1;
6029f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        part1 = mFrameCountP2 - rear;
6039f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
6049f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (part1 > availToServer) {
6059f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        part1 = availToServer;
6069f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
6079f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    size_t ask = buffer->mFrameCount;
6089f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (part1 > ask) {
6099f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        part1 = ask;
6109f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
6119f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    // is assignment redundant in some cases?
6129f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    buffer->mFrameCount = part1;
6139f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    buffer->mRaw = part1 > 0 ?
6149f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            &((char *) mBuffers)[(mIsOut ? front : rear) * mFrameSize] : NULL;
6159f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    buffer->mNonContig = availToServer - part1;
6162e422c472c91aa7912befd0fc038d1e11f354bc1Glenn Kasten    // After flush(), allow releaseBuffer() on a previously obtained buffer;
6172e422c472c91aa7912befd0fc038d1e11f354bc1Glenn Kasten    // see "Acknowledge any pending flush()" in audioflinger/Tracks.cpp.
6182e422c472c91aa7912befd0fc038d1e11f354bc1Glenn Kasten    if (!ackFlush) {
6192e422c472c91aa7912befd0fc038d1e11f354bc1Glenn Kasten        mUnreleased = part1;
6202e422c472c91aa7912befd0fc038d1e11f354bc1Glenn Kasten    }
6219f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    return part1 > 0 ? NO_ERROR : WOULD_BLOCK;
6227db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kasten    }
6237db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kastenno_init:
6247db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kasten    buffer->mFrameCount = 0;
6257db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kasten    buffer->mRaw = NULL;
6267db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kasten    buffer->mNonContig = 0;
6277db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kasten    mUnreleased = 0;
6287db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kasten    return NO_INIT;
6299f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten}
630a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten
6319f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kastenvoid ServerProxy::releaseBuffer(Buffer* buffer)
6329f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten{
6337db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kasten    LOG_ALWAYS_FATAL_IF(buffer == NULL);
6349f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    size_t stepCount = buffer->mFrameCount;
6357db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kasten    if (stepCount == 0 || mIsShutdown) {
6367db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kasten        // prevent accidental re-use of buffer
6377db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kasten        buffer->mFrameCount = 0;
6389f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        buffer->mRaw = NULL;
6399f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        buffer->mNonContig = 0;
6409f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        return;
6419f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
6427db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kasten    LOG_ALWAYS_FATAL_IF(!(stepCount <= mUnreleased && mUnreleased <= mFrameCount));
6439f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    mUnreleased -= stepCount;
6449f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    audio_track_cblk_t* cblk = mCblk;
6459f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (mIsOut) {
6469f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        int32_t front = cblk->u.mStreaming.mFront;
6479f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        android_atomic_release_store(stepCount + front, &cblk->u.mStreaming.mFront);
6489f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    } else {
6499f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        int32_t rear = cblk->u.mStreaming.mRear;
6509f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        android_atomic_release_store(stepCount + rear, &cblk->u.mStreaming.mRear);
651a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten    }
652a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten
653844f88ccfcca95687e774bccb5e9065da61d33f8Glenn Kasten    cblk->mServer += stepCount;
654a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten
6559f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    size_t half = mFrameCount / 2;
6569f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (half == 0) {
6579f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        half = 1;
6589f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
659fdac7c00f9201bb3a9862069145f01d37e39755bGlenn Kasten    size_t minimum = (size_t) cblk->mMinimum;
6609f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (minimum == 0) {
6619f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        minimum = mIsOut ? half : 1;
6629f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    } else if (minimum > half) {
6639f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        minimum = half;
6649f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
66593bb77da5481ab75c2cd6e3aa681839273c6e43dGlenn Kasten    // FIXME AudioRecord wakeup needs to be optimized; it currently wakes up client every time
666ce8828a016b082f730152af2204b8ea3610dc1ecGlenn Kasten    if (!mIsOut || (mAvailToClient + stepCount >= minimum)) {
66734fb29696b0f3abf61b10f8d053b1f33d501de0aMark Salyzyn        ALOGV("mAvailToClient=%zu stepCount=%zu minimum=%zu", mAvailToClient, stepCount, minimum);
6680d09a9bec07b3bec78bd473ff0bfcf0a261f3f25Glenn Kasten        int32_t old = android_atomic_or(CBLK_FUTEX_WAKE, &cblk->mFutex);
6690d09a9bec07b3bec78bd473ff0bfcf0a261f3f25Glenn Kasten        if (!(old & CBLK_FUTEX_WAKE)) {
670ee499291404a192b059f2e04c5afc65aa6cdd74cElliott Hughes            (void) syscall(__NR_futex, &cblk->mFutex,
671ee499291404a192b059f2e04c5afc65aa6cdd74cElliott Hughes                    mClientInServer ? FUTEX_WAKE_PRIVATE : FUTEX_WAKE, 1);
6729f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        }
673a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten    }
6749f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
6759f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    buffer->mFrameCount = 0;
6769f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    buffer->mRaw = NULL;
6779f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    buffer->mNonContig = 0;
678a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten}
679a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten
6809f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten// ---------------------------------------------------------------------------
6819f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
6829f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kastensize_t AudioTrackServerProxy::framesReady()
683a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten{
6849f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    LOG_ALWAYS_FATAL_IF(!mIsOut);
6859f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
6869f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (mIsShutdown) {
6879f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        return 0;
6889f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
6899f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    audio_track_cblk_t* cblk = mCblk;
690b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald
691b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald    int32_t flush = cblk->u.mStreaming.mFlush;
692b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald    if (flush != mFlush) {
69320f51b1ea04c410a25f214e37bcdb586e2a028ccGlenn Kasten        // FIXME should return an accurate value, but over-estimate is better than under-estimate
694b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald        return mFrameCount;
695b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald    }
6969f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    // the acquire might not be necessary since not doing a subsequent read
6979f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    int32_t rear = android_atomic_acquire_load(&cblk->u.mStreaming.mRear);
6989f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    ssize_t filled = rear - cblk->u.mStreaming.mFront;
6999f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    // pipe should not already be overfull
7009f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (!(0 <= filled && (size_t) filled <= mFrameCount)) {
70134fb29696b0f3abf61b10f8d053b1f33d501de0aMark Salyzyn        ALOGE("Shared memory control block is corrupt (filled=%zd); shutting down", filled);
7029f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        mIsShutdown = true;
7039f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        return 0;
7049f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
7059f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    //  cache this value for later use by obtainBuffer(), with added barrier
7069f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    //  and racy if called by normal mixer thread
7079f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    // ignores flush(), so framesReady() may report a larger mFrameCount than obtainBuffer()
7089f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    return filled;
709a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten}
710a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten
711bfb1b832079bbb9426f72f3863199a54aefd02daEric Laurentbool  AudioTrackServerProxy::setStreamEndDone() {
712844f88ccfcca95687e774bccb5e9065da61d33f8Glenn Kasten    audio_track_cblk_t* cblk = mCblk;
713bfb1b832079bbb9426f72f3863199a54aefd02daEric Laurent    bool old =
714844f88ccfcca95687e774bccb5e9065da61d33f8Glenn Kasten            (android_atomic_or(CBLK_STREAM_END_DONE, &cblk->mFlags) & CBLK_STREAM_END_DONE) != 0;
715bfb1b832079bbb9426f72f3863199a54aefd02daEric Laurent    if (!old) {
716e348c5b72ad889389c7c1c900c121f0fbee221b5Elliott Hughes        (void) syscall(__NR_futex, &cblk->mFutex, mClientInServer ? FUTEX_WAKE_PRIVATE : FUTEX_WAKE,
717ee499291404a192b059f2e04c5afc65aa6cdd74cElliott Hughes                1);
718bfb1b832079bbb9426f72f3863199a54aefd02daEric Laurent    }
719bfb1b832079bbb9426f72f3863199a54aefd02daEric Laurent    return old;
720bfb1b832079bbb9426f72f3863199a54aefd02daEric Laurent}
721bfb1b832079bbb9426f72f3863199a54aefd02daEric Laurent
72282aaf94a5b18939e4d790bbc752031f3070704a3Glenn Kastenvoid AudioTrackServerProxy::tallyUnderrunFrames(uint32_t frameCount)
72382aaf94a5b18939e4d790bbc752031f3070704a3Glenn Kasten{
724844f88ccfcca95687e774bccb5e9065da61d33f8Glenn Kasten    audio_track_cblk_t* cblk = mCblk;
725844f88ccfcca95687e774bccb5e9065da61d33f8Glenn Kasten    cblk->u.mStreaming.mUnderrunFrames += frameCount;
72682aaf94a5b18939e4d790bbc752031f3070704a3Glenn Kasten
72782aaf94a5b18939e4d790bbc752031f3070704a3Glenn Kasten    // FIXME also wake futex so that underrun is noticed more quickly
728844f88ccfcca95687e774bccb5e9065da61d33f8Glenn Kasten    (void) android_atomic_or(CBLK_UNDERRUN, &cblk->mFlags);
72982aaf94a5b18939e4d790bbc752031f3070704a3Glenn Kasten}
73082aaf94a5b18939e4d790bbc752031f3070704a3Glenn Kasten
7319f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten// ---------------------------------------------------------------------------
7329f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
7339f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn KastenStaticAudioTrackServerProxy::StaticAudioTrackServerProxy(audio_track_cblk_t* cblk, void *buffers,
7349f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        size_t frameCount, size_t frameSize)
7359f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    : AudioTrackServerProxy(cblk, buffers, frameCount, frameSize),
7369f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten      mObserver(&cblk->u.mStatic.mSingleStateQueue), mPosition(0),
737cb2129b3b568a4e31bcbda3545a468024bc972feAndy Hung      mFramesReadySafe(frameCount), mFramesReady(frameCount),
738cb2129b3b568a4e31bcbda3545a468024bc972feAndy Hung      mFramesReadyIsCalledByMultipleThreads(false)
739a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten{
7409f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    mState.mLoopStart = 0;
7419f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    mState.mLoopEnd = 0;
7429f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    mState.mLoopCount = 0;
743a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten}
744a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten
7459f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kastenvoid StaticAudioTrackServerProxy::framesReadyIsCalledByMultipleThreads()
746a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten{
7479f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    mFramesReadyIsCalledByMultipleThreads = true;
7489f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten}
749a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten
7509f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kastensize_t StaticAudioTrackServerProxy::framesReady()
7519f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten{
752cb2129b3b568a4e31bcbda3545a468024bc972feAndy Hung    // Can't call pollPosition() from multiple threads.
7539f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (!mFramesReadyIsCalledByMultipleThreads) {
754cb2129b3b568a4e31bcbda3545a468024bc972feAndy Hung        (void) pollPosition();
755a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten    }
756cb2129b3b568a4e31bcbda3545a468024bc972feAndy Hung    return mFramesReadySafe;
757a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten}
758a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten
7599f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kastenssize_t StaticAudioTrackServerProxy::pollPosition()
760a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten{
7619f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    size_t position = mPosition;
7629f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    StaticAudioTrackState state;
7639f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (mObserver.poll(state)) {
7649f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        bool valid = false;
7659f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        size_t loopStart = state.mLoopStart;
7669f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        size_t loopEnd = state.mLoopEnd;
7679f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        if (state.mLoopCount == 0) {
7689f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            if (loopStart > mFrameCount) {
7699f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten                loopStart = mFrameCount;
770a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten            }
7719f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            // ignore loopEnd
7729f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            mPosition = position = loopStart;
773cb2129b3b568a4e31bcbda3545a468024bc972feAndy Hung            mFramesReady = mFrameCount - mPosition;
7749f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            mState.mLoopCount = 0;
7759f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            valid = true;
776cb2129b3b568a4e31bcbda3545a468024bc972feAndy Hung        } else if (state.mLoopCount >= -1) {
7779f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            if (loopStart < loopEnd && loopEnd <= mFrameCount &&
7789f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten                    loopEnd - loopStart >= MIN_LOOP) {
7799f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten                if (!(loopStart <= position && position < loopEnd)) {
7809f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten                    mPosition = position = loopStart;
7819f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten                }
782cb2129b3b568a4e31bcbda3545a468024bc972feAndy Hung                if (state.mLoopCount == -1) {
783cb2129b3b568a4e31bcbda3545a468024bc972feAndy Hung                    mFramesReady = INT64_MAX;
784cb2129b3b568a4e31bcbda3545a468024bc972feAndy Hung                } else {
785cb2129b3b568a4e31bcbda3545a468024bc972feAndy Hung                    // mFramesReady is 64 bits to handle the effective number of frames
786cb2129b3b568a4e31bcbda3545a468024bc972feAndy Hung                    // that the static audio track contains, including loops.
787cb2129b3b568a4e31bcbda3545a468024bc972feAndy Hung                    // TODO: Later consider fixing overflow, but does not seem needed now
788cb2129b3b568a4e31bcbda3545a468024bc972feAndy Hung                    // as will not overflow if loopStart and loopEnd are Java "ints".
789cb2129b3b568a4e31bcbda3545a468024bc972feAndy Hung                    mFramesReady = int64_t(state.mLoopCount) * (loopEnd - loopStart)
790cb2129b3b568a4e31bcbda3545a468024bc972feAndy Hung                            + mFrameCount - mPosition;
791cb2129b3b568a4e31bcbda3545a468024bc972feAndy Hung                }
7929f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten                mState = state;
7939f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten                valid = true;
794a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten            }
795a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten        }
796cb2129b3b568a4e31bcbda3545a468024bc972feAndy Hung        if (!valid || mPosition > mFrameCount) {
7979f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            ALOGE("%s client pushed an invalid state, shutting down", __func__);
7989f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            mIsShutdown = true;
7999f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            return (ssize_t) NO_INIT;
8009f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        }
801cb2129b3b568a4e31bcbda3545a468024bc972feAndy Hung        mFramesReadySafe = clampToSize(mFramesReady);
802fdac7c00f9201bb3a9862069145f01d37e39755bGlenn Kasten        // This may overflow, but client is not supposed to rely on it
803fdac7c00f9201bb3a9862069145f01d37e39755bGlenn Kasten        mCblk->u.mStatic.mBufferPosition = (uint32_t) position;
804a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten    }
8059f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    return (ssize_t) position;
806a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten}
807a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten
8087c7be1e05634d96d08210efb4bdeb012ffba440dGlenn Kastenstatus_t StaticAudioTrackServerProxy::obtainBuffer(Buffer* buffer, bool ackFlush __unused)
809a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten{
8109f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (mIsShutdown) {
8119f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        buffer->mFrameCount = 0;
8129f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        buffer->mRaw = NULL;
8139f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        buffer->mNonContig = 0;
8149f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        mUnreleased = 0;
8159f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        return NO_INIT;
8169f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
8179f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    ssize_t positionOrStatus = pollPosition();
8189f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (positionOrStatus < 0) {
8199f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        buffer->mFrameCount = 0;
8209f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        buffer->mRaw = NULL;
8219f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        buffer->mNonContig = 0;
8229f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        mUnreleased = 0;
8239f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        return (status_t) positionOrStatus;
8249f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
8259f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    size_t position = (size_t) positionOrStatus;
826cb2129b3b568a4e31bcbda3545a468024bc972feAndy Hung    size_t end = mState.mLoopCount != 0 ? mState.mLoopEnd : mFrameCount;
8279f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    size_t avail;
828cb2129b3b568a4e31bcbda3545a468024bc972feAndy Hung    if (position < end) {
829cb2129b3b568a4e31bcbda3545a468024bc972feAndy Hung        avail = end - position;
8309f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        size_t wanted = buffer->mFrameCount;
8319f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        if (avail < wanted) {
8329f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            buffer->mFrameCount = avail;
8339f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        } else {
8349f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            avail = wanted;
8359f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        }
8369f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        buffer->mRaw = &((char *) mBuffers)[position * mFrameSize];
8379f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    } else {
8389f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        avail = 0;
8399f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        buffer->mFrameCount = 0;
8409f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        buffer->mRaw = NULL;
8419f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
842cb2129b3b568a4e31bcbda3545a468024bc972feAndy Hung    // As mFramesReady is the total remaining frames in the static audio track,
843cb2129b3b568a4e31bcbda3545a468024bc972feAndy Hung    // it is always larger or equal to avail.
844cb2129b3b568a4e31bcbda3545a468024bc972feAndy Hung    LOG_ALWAYS_FATAL_IF(mFramesReady < avail);
845cb2129b3b568a4e31bcbda3545a468024bc972feAndy Hung    buffer->mNonContig = mFramesReady == INT64_MAX ? SIZE_MAX : clampToSize(mFramesReady - avail);
8469f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    mUnreleased = avail;
8479f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    return NO_ERROR;
8489f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten}
849a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten
8509f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kastenvoid StaticAudioTrackServerProxy::releaseBuffer(Buffer* buffer)
8519f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten{
8529f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    size_t stepCount = buffer->mFrameCount;
853cb2129b3b568a4e31bcbda3545a468024bc972feAndy Hung    LOG_ALWAYS_FATAL_IF(!(stepCount <= mFramesReady));
8547db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kasten    LOG_ALWAYS_FATAL_IF(!(stepCount <= mUnreleased));
8559f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (stepCount == 0) {
8567db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kasten        // prevent accidental re-use of buffer
8579f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        buffer->mRaw = NULL;
8589f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        buffer->mNonContig = 0;
8599f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        return;
860a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten    }
8619f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    mUnreleased -= stepCount;
8629f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    audio_track_cblk_t* cblk = mCblk;
8639f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    size_t position = mPosition;
8649f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    size_t newPosition = position + stepCount;
8659f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    int32_t setFlags = 0;
8669f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (!(position <= newPosition && newPosition <= mFrameCount)) {
86734fb29696b0f3abf61b10f8d053b1f33d501de0aMark Salyzyn        ALOGW("%s newPosition %zu outside [%zu, %zu]", __func__, newPosition, position, mFrameCount);
8689f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        newPosition = mFrameCount;
8699f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    } else if (mState.mLoopCount != 0 && newPosition == mState.mLoopEnd) {
870cb2129b3b568a4e31bcbda3545a468024bc972feAndy Hung        newPosition = mState.mLoopStart;
8719f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        if (mState.mLoopCount == -1 || --mState.mLoopCount != 0) {
8729f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            setFlags = CBLK_LOOP_CYCLE;
8739f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        } else {
8749f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            setFlags = CBLK_LOOP_FINAL;
8759f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        }
876a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten    }
8779f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (newPosition == mFrameCount) {
8789f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        setFlags |= CBLK_BUFFER_END;
8799f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
8809f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    mPosition = newPosition;
881cb2129b3b568a4e31bcbda3545a468024bc972feAndy Hung    if (mFramesReady != INT64_MAX) {
882cb2129b3b568a4e31bcbda3545a468024bc972feAndy Hung        mFramesReady -= stepCount;
883cb2129b3b568a4e31bcbda3545a468024bc972feAndy Hung    }
884cb2129b3b568a4e31bcbda3545a468024bc972feAndy Hung    mFramesReadySafe = clampToSize(mFramesReady);
8859f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
886f20e1d8df84c5fbeeace0052d100982ae39bb7a4Glenn Kasten    cblk->mServer += stepCount;
887fdac7c00f9201bb3a9862069145f01d37e39755bGlenn Kasten    // This may overflow, but client is not supposed to rely on it
888fdac7c00f9201bb3a9862069145f01d37e39755bGlenn Kasten    cblk->u.mStatic.mBufferPosition = (uint32_t) newPosition;
8899f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (setFlags != 0) {
89096f60d8f04432a1ed503b3e24d5736d28c63c9a2Glenn Kasten        (void) android_atomic_or(setFlags, &cblk->mFlags);
8919f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        // this would be a good place to wake a futex
8929f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
8939f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
8949f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    buffer->mFrameCount = 0;
8959f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    buffer->mRaw = NULL;
8969f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    buffer->mNonContig = 0;
897a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten}
898a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten
8997c7be1e05634d96d08210efb4bdeb012ffba440dGlenn Kastenvoid StaticAudioTrackServerProxy::tallyUnderrunFrames(uint32_t frameCount __unused)
90082aaf94a5b18939e4d790bbc752031f3070704a3Glenn Kasten{
90182aaf94a5b18939e4d790bbc752031f3070704a3Glenn Kasten    // Unlike AudioTrackServerProxy::tallyUnderrunFrames() used for streaming tracks,
90282aaf94a5b18939e4d790bbc752031f3070704a3Glenn Kasten    // we don't have a location to count underrun frames.  The underrun frame counter
90382aaf94a5b18939e4d790bbc752031f3070704a3Glenn Kasten    // only exists in AudioTrackSharedStreaming.  Fortunately, underruns are not
90482aaf94a5b18939e4d790bbc752031f3070704a3Glenn Kasten    // possible for static buffer tracks other than at end of buffer, so this is not a loss.
90582aaf94a5b18939e4d790bbc752031f3070704a3Glenn Kasten
90682aaf94a5b18939e4d790bbc752031f3070704a3Glenn Kasten    // FIXME also wake futex so that underrun is noticed more quickly
90782aaf94a5b18939e4d790bbc752031f3070704a3Glenn Kasten    (void) android_atomic_or(CBLK_UNDERRUN, &mCblk->mFlags);
90882aaf94a5b18939e4d790bbc752031f3070704a3Glenn Kasten}
90982aaf94a5b18939e4d790bbc752031f3070704a3Glenn Kasten
9109f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten// ---------------------------------------------------------------------------
9119f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
912a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten}   // namespace android
913