AudioTrackShared.cpp revision 96f60d8f04432a1ed503b3e24d5736d28c63c9a2
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()
29f20e1d8df84c5fbeeace0052d100982ae39bb7a4Glenn Kasten    : mServer(0), frameCount_(0), mFutex(0), mMinimum(0),
3096f60d8f04432a1ed503b3e24d5736d28c63c9a2Glenn Kasten    mVolumeLR(0x10001000), mSampleRate(0), mSendLevel(0), mName(0), mFlags(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 (;;) {
10296f60d8f04432a1ed503b3e24d5736d28c63c9a2Glenn Kasten        int32_t flags = android_atomic_and(~CBLK_INTERRUPT, &cblk->mFlags);
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:
203b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald            LOG_FATAL("obtainBuffer() 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) {
262b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald        ALOGV("requested %ld.%03ld elapsed %ld.%03ld",
263b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald              requested->tv_sec, requested->tv_nsec / 1000000,
264b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald              total.tv_sec, total.tv_nsec / 1000000);
2659f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
2669f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    return status;
2679f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten}
268a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten
2699f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kastenvoid ClientProxy::releaseBuffer(Buffer* buffer)
2709f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten{
2717db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kasten    LOG_ALWAYS_FATAL_IF(buffer == NULL);
2729f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    size_t stepCount = buffer->mFrameCount;
2737db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kasten    if (stepCount == 0 || mIsShutdown) {
2747db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kasten        // prevent accidental re-use of buffer
2757db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kasten        buffer->mFrameCount = 0;
2767db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kasten        buffer->mRaw = NULL;
2777db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kasten        buffer->mNonContig = 0;
2789f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        return;
2799f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
2807db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kasten    LOG_ALWAYS_FATAL_IF(!(stepCount <= mUnreleased && mUnreleased <= mFrameCount));
2817db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kasten    mUnreleased -= stepCount;
2829f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    audio_track_cblk_t* cblk = mCblk;
2839f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    // Both of these barriers are required
2849f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (mIsOut) {
2859f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        int32_t rear = cblk->u.mStreaming.mRear;
2869f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        android_atomic_release_store(stepCount + rear, &cblk->u.mStreaming.mRear);
2879f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    } else {
2889f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        int32_t front = cblk->u.mStreaming.mFront;
2899f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        android_atomic_release_store(stepCount + front, &cblk->u.mStreaming.mFront);
2909f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
291a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten}
292a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten
2939f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kastenvoid ClientProxy::binderDied()
294a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten{
2959f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    audio_track_cblk_t* cblk = mCblk;
29696f60d8f04432a1ed503b3e24d5736d28c63c9a2Glenn Kasten    if (!(android_atomic_or(CBLK_INVALID, &cblk->mFlags) & CBLK_INVALID)) {
2979f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        // it seems that a FUTEX_WAKE_PRIVATE will not wake a FUTEX_WAIT, even within same process
2989f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        (void) __futex_syscall3(&cblk->mFutex, mClientInServer ? FUTEX_WAKE_PRIVATE : FUTEX_WAKE,
2999f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten                1);
3009f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
3019f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten}
302a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten
3039f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kastenvoid ClientProxy::interrupt()
3049f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten{
3059f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    audio_track_cblk_t* cblk = mCblk;
30696f60d8f04432a1ed503b3e24d5736d28c63c9a2Glenn Kasten    if (!(android_atomic_or(CBLK_INTERRUPT, &cblk->mFlags) & CBLK_INTERRUPT)) {
3079f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        (void) __futex_syscall3(&cblk->mFutex, mClientInServer ? FUTEX_WAKE_PRIVATE : FUTEX_WAKE,
3089f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten                1);
309a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten    }
3109f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten}
311a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten
3129f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kastensize_t ClientProxy::getMisalignment()
3139f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten{
3149f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    audio_track_cblk_t* cblk = mCblk;
3159f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    return (mFrameCountP2 - (mIsOut ? cblk->u.mStreaming.mRear : cblk->u.mStreaming.mFront)) &
3169f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            (mFrameCountP2 - 1);
3179f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten}
318a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten
3199f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten// ---------------------------------------------------------------------------
3209f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
3219f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kastenvoid AudioTrackClientProxy::flush()
3229f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten{
3239f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    mCblk->u.mStreaming.mFlush++;
3249f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten}
3259f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
326bfb1b832079bbb9426f72f3863199a54aefd02daEric Laurentbool AudioTrackClientProxy::clearStreamEndDone() {
32796f60d8f04432a1ed503b3e24d5736d28c63c9a2Glenn Kasten    return (android_atomic_and(~CBLK_STREAM_END_DONE, &mCblk->mFlags) & CBLK_STREAM_END_DONE) != 0;
328bfb1b832079bbb9426f72f3863199a54aefd02daEric Laurent}
329bfb1b832079bbb9426f72f3863199a54aefd02daEric Laurent
330bfb1b832079bbb9426f72f3863199a54aefd02daEric Laurentbool AudioTrackClientProxy::getStreamEndDone() const {
33196f60d8f04432a1ed503b3e24d5736d28c63c9a2Glenn Kasten    return (mCblk->mFlags & CBLK_STREAM_END_DONE) != 0;
332bfb1b832079bbb9426f72f3863199a54aefd02daEric Laurent}
333bfb1b832079bbb9426f72f3863199a54aefd02daEric Laurent
334b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgeraldstatus_t AudioTrackClientProxy::waitStreamEndDone(const struct timespec *requested)
335b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald{
336b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald    struct timespec total;          // total elapsed time spent waiting
337b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald    total.tv_sec = 0;
338b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald    total.tv_nsec = 0;
339b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald    audio_track_cblk_t* cblk = mCblk;
340b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald    status_t status;
341b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald    enum {
342b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald        TIMEOUT_ZERO,       // requested == NULL || *requested == 0
343b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald        TIMEOUT_INFINITE,   // *requested == infinity
344b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald        TIMEOUT_FINITE,     // 0 < *requested < infinity
345b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald        TIMEOUT_CONTINUE,   // additional chances after TIMEOUT_FINITE
346b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald    } timeout;
347b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald    if (requested == NULL) {
348b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald        timeout = TIMEOUT_ZERO;
349b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald    } else if (requested->tv_sec == 0 && requested->tv_nsec == 0) {
350b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald        timeout = TIMEOUT_ZERO;
351b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald    } else if (requested->tv_sec == INT_MAX) {
352b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald        timeout = TIMEOUT_INFINITE;
353b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald    } else {
354b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald        timeout = TIMEOUT_FINITE;
355b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald    }
356b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald    for (;;) {
35796f60d8f04432a1ed503b3e24d5736d28c63c9a2Glenn Kasten        int32_t flags = android_atomic_and(~(CBLK_INTERRUPT|CBLK_STREAM_END_DONE), &cblk->mFlags);
358b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald        // check for track invalidation by server, or server death detection
359b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald        if (flags & CBLK_INVALID) {
360b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald            ALOGV("Track invalidated");
361b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald            status = DEAD_OBJECT;
362b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald            goto end;
363b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald        }
364b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald        if (flags & CBLK_STREAM_END_DONE) {
365b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald            ALOGV("stream end received");
366b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald            status = NO_ERROR;
367b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald            goto end;
368b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald        }
369b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald        // check for obtainBuffer interrupted by client
370b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald        // check for obtainBuffer interrupted by client
371b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald        if (flags & CBLK_INTERRUPT) {
372b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald            ALOGV("waitStreamEndDone() interrupted by client");
373b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald            status = -EINTR;
374b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald            goto end;
375b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald        }
376b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald        struct timespec remaining;
377b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald        const struct timespec *ts;
378b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald        switch (timeout) {
379b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald        case TIMEOUT_ZERO:
380b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald            status = WOULD_BLOCK;
381b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald            goto end;
382b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald        case TIMEOUT_INFINITE:
383b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald            ts = NULL;
384b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald            break;
385b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald        case TIMEOUT_FINITE:
386b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald            timeout = TIMEOUT_CONTINUE;
387b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald            if (MAX_SEC == 0) {
388b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald                ts = requested;
389b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald                break;
390b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald            }
391b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald            // fall through
392b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald        case TIMEOUT_CONTINUE:
393b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald            // FIXME we do not retry if requested < 10ms? needs documentation on this state machine
394b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald            if (requested->tv_sec < total.tv_sec ||
395b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald                    (requested->tv_sec == total.tv_sec && requested->tv_nsec <= total.tv_nsec)) {
396b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald                status = TIMED_OUT;
397b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald                goto end;
398b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald            }
399b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald            remaining.tv_sec = requested->tv_sec - total.tv_sec;
400b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald            if ((remaining.tv_nsec = requested->tv_nsec - total.tv_nsec) < 0) {
401b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald                remaining.tv_nsec += 1000000000;
402b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald                remaining.tv_sec++;
403b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald            }
404b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald            if (0 < MAX_SEC && MAX_SEC < remaining.tv_sec) {
405b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald                remaining.tv_sec = MAX_SEC;
406b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald                remaining.tv_nsec = 0;
407b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald            }
408b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald            ts = &remaining;
409b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald            break;
410b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald        default:
411b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald            LOG_FATAL("waitStreamEndDone() timeout=%d", timeout);
412b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald            ts = NULL;
413b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald            break;
414b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald        }
415b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald        int32_t old = android_atomic_and(~CBLK_FUTEX_WAKE, &cblk->mFutex);
416b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald        if (!(old & CBLK_FUTEX_WAKE)) {
417b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald            int rc;
418b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald            int ret = __futex_syscall4(&cblk->mFutex,
419b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald                    mClientInServer ? FUTEX_WAIT_PRIVATE : FUTEX_WAIT, old & ~CBLK_FUTEX_WAKE, ts);
420b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald            switch (ret) {
421b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald            case 0:             // normal wakeup by server, or by binderDied()
422b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald            case -EWOULDBLOCK:  // benign race condition with server
423b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald            case -EINTR:        // wait was interrupted by signal or other spurious wakeup
424b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald            case -ETIMEDOUT:    // time-out expired
425b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald                break;
426b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald            default:
427b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald                ALOGE("%s unexpected error %d", __func__, ret);
428b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald                status = -ret;
429b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald                goto end;
430b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald            }
431b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald        }
432b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald    }
433b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald
434b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgeraldend:
435b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald    if (requested == NULL) {
436b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald        requested = &kNonBlocking;
437b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald    }
438b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald    return status;
439b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald}
440b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald
4419f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten// ---------------------------------------------------------------------------
4429f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
4439f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn KastenStaticAudioTrackClientProxy::StaticAudioTrackClientProxy(audio_track_cblk_t* cblk, void *buffers,
4449f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        size_t frameCount, size_t frameSize)
4459f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    : AudioTrackClientProxy(cblk, buffers, frameCount, frameSize),
4469f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten      mMutator(&cblk->u.mStatic.mSingleStateQueue), mBufferPosition(0)
4479f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten{
4489f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten}
4499f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
4509f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kastenvoid StaticAudioTrackClientProxy::flush()
4519f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten{
4529f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    LOG_FATAL("static flush");
4539f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten}
4549f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
4559f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kastenvoid StaticAudioTrackClientProxy::setLoop(size_t loopStart, size_t loopEnd, int loopCount)
4569f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten{
4579f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    StaticAudioTrackState newState;
4589f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    newState.mLoopStart = loopStart;
4599f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    newState.mLoopEnd = loopEnd;
4609f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    newState.mLoopCount = loopCount;
4619f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    mBufferPosition = loopStart;
4629f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    (void) mMutator.push(newState);
4639f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten}
4649f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
4659f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kastensize_t StaticAudioTrackClientProxy::getBufferPosition()
4669f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten{
4679f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    size_t bufferPosition;
4689f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (mMutator.ack()) {
4699f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        bufferPosition = mCblk->u.mStatic.mBufferPosition;
4709f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        if (bufferPosition > mFrameCount) {
4719f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            bufferPosition = mFrameCount;
472a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten        }
4739f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    } else {
4749f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        bufferPosition = mBufferPosition;
475a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten    }
4769f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    return bufferPosition;
4779f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten}
4789f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
4799f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten// ---------------------------------------------------------------------------
480a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten
4819f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn KastenServerProxy::ServerProxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount,
4829f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        size_t frameSize, bool isOut, bool clientInServer)
4837db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kasten    : Proxy(cblk, buffers, frameCount, frameSize, isOut, clientInServer),
4849f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten      mAvailToClient(0), mFlush(0), mDeferWake(false)
4859f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten{
4869f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten}
4879f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
4889f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kastenstatus_t ServerProxy::obtainBuffer(Buffer* buffer)
4899f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten{
4907db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kasten    LOG_ALWAYS_FATAL_IF(buffer == NULL || buffer->mFrameCount == 0);
4919f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (mIsShutdown) {
4927db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kasten        goto no_init;
4939f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
4947db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kasten    {
4959f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    audio_track_cblk_t* cblk = mCblk;
4969f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    // compute number of frames available to write (AudioTrack) or read (AudioRecord),
4979f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    // or use previous cached value from framesReady(), with added barrier if it omits.
4989f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    int32_t front;
4999f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    int32_t rear;
5009f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    // See notes on barriers at ClientProxy::obtainBuffer()
5019f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (mIsOut) {
5029f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        int32_t flush = cblk->u.mStreaming.mFlush;
5039f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        rear = android_atomic_acquire_load(&cblk->u.mStreaming.mRear);
504b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald        front = cblk->u.mStreaming.mFront;
5059f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        if (flush != mFlush) {
5069f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            mFlush = flush;
507050501d11d944dcb256d37d3b86bd658d94f6a7fGlenn Kasten            // effectively obtain then release whatever is in the buffer
508050501d11d944dcb256d37d3b86bd658d94f6a7fGlenn Kasten            android_atomic_release_store(rear, &cblk->u.mStreaming.mFront);
509b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald            if (front != rear) {
510b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald                int32_t old = android_atomic_or(CBLK_FUTEX_WAKE, &cblk->mFutex);
511b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald                if (!(old & CBLK_FUTEX_WAKE)) {
512b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald                    (void) __futex_syscall3(&cblk->mFutex,
513b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald                            mClientInServer ? FUTEX_WAKE_PRIVATE : FUTEX_WAKE, 1);
514b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald                }
515b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald            }
516b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald            front = rear;
517a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten        }
5189f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    } else {
5199f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        front = android_atomic_acquire_load(&cblk->u.mStreaming.mFront);
5209f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        rear = cblk->u.mStreaming.mRear;
5219f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
5229f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    ssize_t filled = rear - front;
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    }
5289f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (mIsShutdown) {
5297db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kasten        goto no_init;
530a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten    }
5319f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    // don't allow filling pipe beyond the nominal size
5329f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    size_t availToServer;
5339f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (mIsOut) {
5349f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        availToServer = filled;
5359f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        mAvailToClient = mFrameCount - filled;
5369f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    } else {
5379f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        availToServer = mFrameCount - filled;
5389f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        mAvailToClient = filled;
5399f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
5409f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    // 'availToServer' may be non-contiguous, so return only the first contiguous chunk
5419f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    size_t part1;
5429f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (mIsOut) {
5439f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        front &= mFrameCountP2 - 1;
5449f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        part1 = mFrameCountP2 - front;
5459f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    } else {
5469f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        rear &= mFrameCountP2 - 1;
5479f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        part1 = mFrameCountP2 - rear;
5489f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
5499f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (part1 > availToServer) {
5509f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        part1 = availToServer;
5519f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
5529f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    size_t ask = buffer->mFrameCount;
5539f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (part1 > ask) {
5549f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        part1 = ask;
5559f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
5569f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    // is assignment redundant in some cases?
5579f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    buffer->mFrameCount = part1;
5589f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    buffer->mRaw = part1 > 0 ?
5599f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            &((char *) mBuffers)[(mIsOut ? front : rear) * mFrameSize] : NULL;
5609f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    buffer->mNonContig = availToServer - part1;
5619f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    mUnreleased = part1;
5629f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    // optimization to avoid waking up the client too early
5639f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    // FIXME need to test for recording
5649f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    mDeferWake = part1 < ask && availToServer >= ask;
5659f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    return part1 > 0 ? NO_ERROR : WOULD_BLOCK;
5667db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kasten    }
5677db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kastenno_init:
5687db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kasten    buffer->mFrameCount = 0;
5697db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kasten    buffer->mRaw = NULL;
5707db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kasten    buffer->mNonContig = 0;
5717db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kasten    mUnreleased = 0;
5727db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kasten    return NO_INIT;
5739f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten}
574a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten
5759f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kastenvoid ServerProxy::releaseBuffer(Buffer* buffer)
5769f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten{
5777db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kasten    LOG_ALWAYS_FATAL_IF(buffer == NULL);
5789f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    size_t stepCount = buffer->mFrameCount;
5797db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kasten    if (stepCount == 0 || mIsShutdown) {
5807db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kasten        // prevent accidental re-use of buffer
5817db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kasten        buffer->mFrameCount = 0;
5829f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        buffer->mRaw = NULL;
5839f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        buffer->mNonContig = 0;
5849f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        return;
5859f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
5867db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kasten    LOG_ALWAYS_FATAL_IF(!(stepCount <= mUnreleased && mUnreleased <= mFrameCount));
5879f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    mUnreleased -= stepCount;
5889f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    audio_track_cblk_t* cblk = mCblk;
5899f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (mIsOut) {
5909f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        int32_t front = cblk->u.mStreaming.mFront;
5919f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        android_atomic_release_store(stepCount + front, &cblk->u.mStreaming.mFront);
5929f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    } else {
5939f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        int32_t rear = cblk->u.mStreaming.mRear;
5949f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        android_atomic_release_store(stepCount + rear, &cblk->u.mStreaming.mRear);
595a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten    }
596a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten
597f20e1d8df84c5fbeeace0052d100982ae39bb7a4Glenn Kasten    mCblk->mServer += stepCount;
598a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten
5999f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    size_t half = mFrameCount / 2;
6009f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (half == 0) {
6019f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        half = 1;
6029f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
6039f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    size_t minimum = cblk->mMinimum;
6049f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (minimum == 0) {
6059f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        minimum = mIsOut ? half : 1;
6069f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    } else if (minimum > half) {
6079f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        minimum = half;
6089f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
60993bb77da5481ab75c2cd6e3aa681839273c6e43dGlenn Kasten    // FIXME AudioRecord wakeup needs to be optimized; it currently wakes up client every time
61093bb77da5481ab75c2cd6e3aa681839273c6e43dGlenn Kasten    if (!mIsOut || (!mDeferWake && mAvailToClient + stepCount >= minimum)) {
6119f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        ALOGV("mAvailToClient=%u stepCount=%u minimum=%u", mAvailToClient, stepCount, minimum);
6120d09a9bec07b3bec78bd473ff0bfcf0a261f3f25Glenn Kasten        int32_t old = android_atomic_or(CBLK_FUTEX_WAKE, &cblk->mFutex);
6130d09a9bec07b3bec78bd473ff0bfcf0a261f3f25Glenn Kasten        if (!(old & CBLK_FUTEX_WAKE)) {
6149f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            (void) __futex_syscall3(&cblk->mFutex,
6159f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten                    mClientInServer ? FUTEX_WAKE_PRIVATE : FUTEX_WAKE, 1);
6169f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        }
617a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten    }
6189f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
6199f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    buffer->mFrameCount = 0;
6209f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    buffer->mRaw = NULL;
6219f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    buffer->mNonContig = 0;
622a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten}
623a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten
6249f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten// ---------------------------------------------------------------------------
6259f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
6269f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kastensize_t AudioTrackServerProxy::framesReady()
627a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten{
6289f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    LOG_ALWAYS_FATAL_IF(!mIsOut);
6299f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
6309f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (mIsShutdown) {
6319f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        return 0;
6329f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
6339f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    audio_track_cblk_t* cblk = mCblk;
634b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald
635b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald    int32_t flush = cblk->u.mStreaming.mFlush;
636b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald    if (flush != mFlush) {
637b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald        return mFrameCount;
638b1a270d1e926fb9a01b4265a7675ed0c2c8f4868Richard Fitzgerald    }
6399f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    // the acquire might not be necessary since not doing a subsequent read
6409f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    int32_t rear = android_atomic_acquire_load(&cblk->u.mStreaming.mRear);
6419f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    ssize_t filled = rear - cblk->u.mStreaming.mFront;
6429f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    // pipe should not already be overfull
6439f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (!(0 <= filled && (size_t) filled <= mFrameCount)) {
6449f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        ALOGE("Shared memory control block is corrupt (filled=%d); shutting down", filled);
6459f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        mIsShutdown = true;
6469f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        return 0;
6479f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
6489f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    //  cache this value for later use by obtainBuffer(), with added barrier
6499f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    //  and racy if called by normal mixer thread
6509f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    // ignores flush(), so framesReady() may report a larger mFrameCount than obtainBuffer()
6519f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    return filled;
652a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten}
653a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten
654bfb1b832079bbb9426f72f3863199a54aefd02daEric Laurentbool  AudioTrackServerProxy::setStreamEndDone() {
655bfb1b832079bbb9426f72f3863199a54aefd02daEric Laurent    bool old =
65696f60d8f04432a1ed503b3e24d5736d28c63c9a2Glenn Kasten            (android_atomic_or(CBLK_STREAM_END_DONE, &mCblk->mFlags) & CBLK_STREAM_END_DONE) != 0;
657bfb1b832079bbb9426f72f3863199a54aefd02daEric Laurent    if (!old) {
658bfb1b832079bbb9426f72f3863199a54aefd02daEric Laurent        (void) __futex_syscall3(&mCblk->mFutex, mClientInServer ? FUTEX_WAKE_PRIVATE : FUTEX_WAKE,
659bfb1b832079bbb9426f72f3863199a54aefd02daEric Laurent                1);
660bfb1b832079bbb9426f72f3863199a54aefd02daEric Laurent    }
661bfb1b832079bbb9426f72f3863199a54aefd02daEric Laurent    return old;
662bfb1b832079bbb9426f72f3863199a54aefd02daEric Laurent}
663bfb1b832079bbb9426f72f3863199a54aefd02daEric Laurent
6649f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten// ---------------------------------------------------------------------------
6659f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
6669f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn KastenStaticAudioTrackServerProxy::StaticAudioTrackServerProxy(audio_track_cblk_t* cblk, void *buffers,
6679f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        size_t frameCount, size_t frameSize)
6689f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    : AudioTrackServerProxy(cblk, buffers, frameCount, frameSize),
6699f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten      mObserver(&cblk->u.mStatic.mSingleStateQueue), mPosition(0),
6709f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten      mEnd(frameCount), mFramesReadyIsCalledByMultipleThreads(false)
671a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten{
6729f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    mState.mLoopStart = 0;
6739f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    mState.mLoopEnd = 0;
6749f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    mState.mLoopCount = 0;
675a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten}
676a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten
6779f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kastenvoid StaticAudioTrackServerProxy::framesReadyIsCalledByMultipleThreads()
678a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten{
6799f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    mFramesReadyIsCalledByMultipleThreads = true;
6809f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten}
681a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten
6829f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kastensize_t StaticAudioTrackServerProxy::framesReady()
6839f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten{
6849f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    // FIXME
6859f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    // This is racy if called by normal mixer thread,
6869f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    // as we're reading 2 independent variables without a lock.
6879f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    // Can't call mObserver.poll(), as we might be called from wrong thread.
6889f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    // If looping is enabled, should return a higher number (since includes non-contiguous).
6899f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    size_t position = mPosition;
6909f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (!mFramesReadyIsCalledByMultipleThreads) {
6919f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        ssize_t positionOrStatus = pollPosition();
6929f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        if (positionOrStatus >= 0) {
6939f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            position = (size_t) positionOrStatus;
6949f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        }
695a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten    }
6969f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    size_t end = mEnd;
6979f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    return position < end ? end - position : 0;
698a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten}
699a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten
7009f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kastenssize_t StaticAudioTrackServerProxy::pollPosition()
701a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten{
7029f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    size_t position = mPosition;
7039f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    StaticAudioTrackState state;
7049f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (mObserver.poll(state)) {
7059f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        bool valid = false;
7069f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        size_t loopStart = state.mLoopStart;
7079f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        size_t loopEnd = state.mLoopEnd;
7089f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        if (state.mLoopCount == 0) {
7099f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            if (loopStart > mFrameCount) {
7109f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten                loopStart = mFrameCount;
711a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten            }
7129f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            // ignore loopEnd
7139f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            mPosition = position = loopStart;
7149f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            mEnd = mFrameCount;
7159f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            mState.mLoopCount = 0;
7169f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            valid = true;
7179f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        } else {
7189f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            if (loopStart < loopEnd && loopEnd <= mFrameCount &&
7199f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten                    loopEnd - loopStart >= MIN_LOOP) {
7209f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten                if (!(loopStart <= position && position < loopEnd)) {
7219f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten                    mPosition = position = loopStart;
7229f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten                }
7239f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten                mEnd = loopEnd;
7249f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten                mState = state;
7259f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten                valid = true;
726a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten            }
727a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten        }
7289f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        if (!valid) {
7299f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            ALOGE("%s client pushed an invalid state, shutting down", __func__);
7309f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            mIsShutdown = true;
7319f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            return (ssize_t) NO_INIT;
7329f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        }
7339f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        mCblk->u.mStatic.mBufferPosition = position;
734a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten    }
7359f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    return (ssize_t) position;
736a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten}
737a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten
7389f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kastenstatus_t StaticAudioTrackServerProxy::obtainBuffer(Buffer* buffer)
739a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten{
7409f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (mIsShutdown) {
7419f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        buffer->mFrameCount = 0;
7429f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        buffer->mRaw = NULL;
7439f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        buffer->mNonContig = 0;
7449f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        mUnreleased = 0;
7459f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        return NO_INIT;
7469f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
7479f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    ssize_t positionOrStatus = pollPosition();
7489f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (positionOrStatus < 0) {
7499f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        buffer->mFrameCount = 0;
7509f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        buffer->mRaw = NULL;
7519f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        buffer->mNonContig = 0;
7529f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        mUnreleased = 0;
7539f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        return (status_t) positionOrStatus;
7549f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
7559f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    size_t position = (size_t) positionOrStatus;
7569f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    size_t avail;
7579f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (position < mEnd) {
7589f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        avail = mEnd - position;
7599f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        size_t wanted = buffer->mFrameCount;
7609f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        if (avail < wanted) {
7619f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            buffer->mFrameCount = avail;
7629f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        } else {
7639f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            avail = wanted;
7649f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        }
7659f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        buffer->mRaw = &((char *) mBuffers)[position * mFrameSize];
7669f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    } else {
7679f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        avail = 0;
7689f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        buffer->mFrameCount = 0;
7699f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        buffer->mRaw = NULL;
7709f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
7719f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    buffer->mNonContig = 0;     // FIXME should be > 0 for looping
7729f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    mUnreleased = avail;
7739f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    return NO_ERROR;
7749f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten}
775a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten
7769f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kastenvoid StaticAudioTrackServerProxy::releaseBuffer(Buffer* buffer)
7779f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten{
7789f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    size_t stepCount = buffer->mFrameCount;
7797db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kasten    LOG_ALWAYS_FATAL_IF(!(stepCount <= mUnreleased));
7809f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (stepCount == 0) {
7817db7df0e8d9d7cee8ba374468cdbfa0108e3337cGlenn Kasten        // prevent accidental re-use of buffer
7829f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        buffer->mRaw = NULL;
7839f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        buffer->mNonContig = 0;
7849f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        return;
785a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten    }
7869f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    mUnreleased -= stepCount;
7879f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    audio_track_cblk_t* cblk = mCblk;
7889f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    size_t position = mPosition;
7899f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    size_t newPosition = position + stepCount;
7909f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    int32_t setFlags = 0;
7919f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (!(position <= newPosition && newPosition <= mFrameCount)) {
7929f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        ALOGW("%s newPosition %u outside [%u, %u]", __func__, newPosition, position, mFrameCount);
7939f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        newPosition = mFrameCount;
7949f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    } else if (mState.mLoopCount != 0 && newPosition == mState.mLoopEnd) {
7959f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        if (mState.mLoopCount == -1 || --mState.mLoopCount != 0) {
7969f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            newPosition = mState.mLoopStart;
7979f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            setFlags = CBLK_LOOP_CYCLE;
7989f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        } else {
7999f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            mEnd = mFrameCount;     // this is what allows playback to continue after the loop
8009f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten            setFlags = CBLK_LOOP_FINAL;
8019f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        }
802a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten    }
8039f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (newPosition == mFrameCount) {
8049f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        setFlags |= CBLK_BUFFER_END;
8059f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
8069f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    mPosition = newPosition;
8079f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
808f20e1d8df84c5fbeeace0052d100982ae39bb7a4Glenn Kasten    cblk->mServer += stepCount;
8099f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    cblk->u.mStatic.mBufferPosition = newPosition;
8109f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    if (setFlags != 0) {
81196f60d8f04432a1ed503b3e24d5736d28c63c9a2Glenn Kasten        (void) android_atomic_or(setFlags, &cblk->mFlags);
8129f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten        // this would be a good place to wake a futex
8139f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    }
8149f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
8159f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    buffer->mFrameCount = 0;
8169f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    buffer->mRaw = NULL;
8179f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten    buffer->mNonContig = 0;
818a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten}
819a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten
8209f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten// ---------------------------------------------------------------------------
8219f80dd223d83d9bb9077fb6baee056cee4eaf7e5Glenn Kasten
822a8190fc518b6769257896605f3aee091aeb60b50Glenn Kasten}   // namespace android
823