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