Home | History | Annotate | Download | only in audio_utils
      1 /*
      2  * Copyright (C) 2015 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #ifndef ANDROID_AUDIO_FIFO_H
     18 #define ANDROID_AUDIO_FIFO_H
     19 
     20 #include <atomic>
     21 #include <stdlib.h>
     22 #include <audio_utils/fifo_index.h>
     23 
     24 #ifndef __cplusplus
     25 #error C API is no longer supported
     26 #endif
     27 
     28 /** Indicates whether an index is also used for synchronization. */
     29 enum audio_utils_fifo_sync {
     30     /** Index is not also used for synchronization; timeouts are done via clock_nanosleep(). */
     31     AUDIO_UTILS_FIFO_SYNC_SLEEP,
     32     /** Index is also used for synchronization as futex, and is mapped by one process. */
     33     AUDIO_UTILS_FIFO_SYNC_PRIVATE,
     34     /** Index is also used for synchronization as futex, and is mapped by one or more processes. */
     35     AUDIO_UTILS_FIFO_SYNC_SHARED,
     36 };
     37 
     38 /**
     39  * Base class for single-writer, single-reader or multi-reader, optionally blocking FIFO.
     40  * The base class manipulates frame indices only, and has no knowledge of frame sizes or the buffer.
     41  * At most one reader, called the "throttling reader", can block the writer.
     42  * The "fill level", or unread frame count, is defined with respect to the throttling reader.
     43  */
     44 class audio_utils_fifo_base {
     45 
     46 public:
     47 
     48     /**
     49      * Return the capacity, or statically configured maximum frame count.
     50      *
     51      * \return The capacity in frames.
     52      */
     53     uint32_t capacity() const
     54             { return mFrameCount; }
     55 
     56 protected:
     57 
     58     /**
     59      * Construct FIFO base class
     60      *
     61      *  \param frameCount    Maximum usable frames to be stored in the FIFO > 0 && <= INT32_MAX,
     62      *                       aka "capacity".
     63      *                       If release()s always use the same count, and the count is a divisor of
     64      *                       (effective) \p frameCount, then the obtain()s won't ever be fragmented.
     65      *  \param writerRear    Writer's rear index.  Passed by reference because it must be non-NULL.
     66      *  \param throttleFront Pointer to the front index of at most one reader that throttles the
     67      *                       writer, or NULL for no throttling.
     68      */
     69     audio_utils_fifo_base(uint32_t frameCount, audio_utils_fifo_index& writerRear,
     70             audio_utils_fifo_index *throttleFront = NULL);
     71     /*virtual*/ ~audio_utils_fifo_base();
     72 
     73     /** Return a new index as the sum of a validated index and a specified increment.
     74      *
     75      * \param index     Caller should supply a validated mFront or mRear.
     76      * \param increment Value to be added to the index <= mFrameCount.
     77      *
     78      * \return The sum of index plus increment.
     79      */
     80     uint32_t sum(uint32_t index, uint32_t increment) const;
     81 
     82     /** Return the difference between two indices: rear - front.
     83      *
     84      * \param rear  Caller should supply an unvalidated mRear.
     85      * \param front Caller should supply an unvalidated mFront.
     86      * \param lost  If non-NULL, set to the approximate number of frames lost before
     87      *              re-synchronization when -EOVERFLOW occurs, or set to zero when no frames lost.
     88      * \param flush Whether to flush the entire buffer on -EOVERFLOW.
     89      *
     90      * \return The zero or positive difference <= mFrameCount, or a negative error code.
     91      * \retval -EIO        corrupted indices, no recovery is possible
     92      * \retval -EOVERFLOW  reader doesn't throttle writer, and frames were lost because reader
     93      *                     isn't keeping up with writer; see \p lost
     94      */
     95     int32_t diff(uint32_t rear, uint32_t front, size_t *lost = NULL, bool flush = false) const;
     96 
     97     /**
     98      * Mark the FIFO as shutdown (permanently unusable), usually due to an -EIO status from an API.
     99      * Thereafter, all APIs that return a status will return -EIO, and other APIs will be no-ops.
    100      */
    101     void shutdown() const;
    102 
    103     // These fields are const after initialization
    104 
    105     /** Maximum usable frames to be stored in the FIFO > 0 && <= INT32_MAX, aka "capacity". */
    106     const uint32_t mFrameCount;
    107     /** Equal to roundup(mFrameCount). */
    108     const uint32_t mFrameCountP2;
    109 
    110     /**
    111      * Equal to mFrameCountP2 - mFrameCount, the number of "wasted" frames after the end of mBuffer.
    112      * Only the indices are wasted, not any memory.
    113      */
    114     const uint32_t mFudgeFactor;
    115 
    116     /** Reference to writer's rear index. */
    117     audio_utils_fifo_index&         mWriterRear;
    118     /** Indicates how synchronization is done for mWriterRear. */
    119     const audio_utils_fifo_sync     mWriterRearSync;
    120 
    121     /**
    122      * Pointer to the front index of at most one reader that throttles the writer,
    123      * or NULL for no throttling.
    124      */
    125     audio_utils_fifo_index* const   mThrottleFront;
    126     /** Indicates how synchronization is done for mThrottleFront. */
    127     const audio_utils_fifo_sync     mThrottleFrontSync;
    128 
    129     /** Whether FIFO is marked as shutdown due to detection of an "impossible" error condition. */
    130     mutable bool                    mIsShutdown;
    131 };
    132 
    133 ////////////////////////////////////////////////////////////////////////////////
    134 
    135 /**
    136  * Same as audio_utils_fifo_base, but understands frame sizes and knows about the buffer but does
    137  * not own it.
    138  */
    139 class audio_utils_fifo : public audio_utils_fifo_base {
    140 
    141     friend class audio_utils_fifo_reader;
    142     friend class audio_utils_fifo_writer;
    143 
    144 public:
    145 
    146     /**
    147      * Construct a FIFO object: multi-process.
    148      *
    149      *  \param frameCount  Maximum usable frames to be stored in the FIFO > 0 && <= INT32_MAX,
    150      *                     aka "capacity".
    151      *                     If writes and reads always use the same count, and the count is a divisor
    152      *                     of \p frameCount, then the writes and reads won't do a partial transfer.
    153      *  \param frameSize   Size of each frame in bytes > 0,
    154      *                     \p frameSize * \p frameCount <= INT32_MAX.
    155      *  \param buffer      Pointer to a non-NULL caller-allocated buffer of \p frameCount frames.
    156      *  \param writerRear  Writer's rear index.  Passed by reference because it must be non-NULL.
    157      *  \param throttleFront Pointer to the front index of at most one reader that throttles the
    158      *                       writer, or NULL for no throttling.
    159      */
    160     audio_utils_fifo(uint32_t frameCount, uint32_t frameSize, void *buffer,
    161             audio_utils_fifo_index& writerRear, audio_utils_fifo_index *throttleFront = NULL);
    162 
    163     /**
    164      * Construct a FIFO object: single-process.
    165      *  \param frameCount  Maximum usable frames to be stored in the FIFO > 0 && <= INT32_MAX,
    166      *                     aka "capacity".
    167      *                     If writes and reads always use the same count, and the count is a divisor
    168      *                     of \p frameCount, then the writes and reads won't do a partial transfer.
    169      *  \param frameSize   Size of each frame in bytes > 0,
    170      *                     \p frameSize * \p frameCount <= INT32_MAX.
    171      *  \param buffer      Pointer to a non-NULL caller-allocated buffer of \p frameCount frames.
    172      *  \param throttlesWriter Whether there is one reader that throttles the writer.
    173      */
    174     audio_utils_fifo(uint32_t frameCount, uint32_t frameSize, void *buffer,
    175             bool throttlesWriter = true);
    176 
    177     /*virtual*/ ~audio_utils_fifo();
    178 
    179     /**
    180      * Return the frame size in bytes.
    181      *
    182      * \return frame size in bytes, always > 0.
    183      */
    184     uint32_t frameSize() const
    185             { return mFrameSize; }
    186 
    187     /**
    188      * Return a pointer to the caller-allocated buffer.
    189      *
    190      * \return non-NULL pointer to buffer.
    191      */
    192     void *buffer() const
    193             { return mBuffer; }
    194 
    195 private:
    196     // These fields are const after initialization
    197     const uint32_t mFrameSize;  // size of each frame in bytes
    198     void * const   mBuffer;     // non-NULL pointer to caller-allocated buffer
    199                                 // of size mFrameCount frames
    200 
    201     // only used for single-process constructor
    202     audio_utils_fifo_index      mSingleProcessSharedRear;
    203 
    204     // only used for single-process constructor when throttlesWriter == true
    205     audio_utils_fifo_index      mSingleProcessSharedFront;
    206 };
    207 
    208 /**
    209  * Describes one virtually contiguous fragment of a logically contiguous slice.
    210  * Compare to struct iovec for readv(2) and writev(2).
    211  */
    212 struct audio_utils_iovec {
    213     /** Offset of fragment in frames, relative to mBuffer, undefined if mLength == 0 */
    214     uint32_t    mOffset;
    215     /** Length of fragment in frames, 0 means fragment is empty */
    216     uint32_t    mLength;
    217 };
    218 
    219 ////////////////////////////////////////////////////////////////////////////////
    220 
    221 /**
    222  * Based on frameworks/av/include/media/AudioBufferProvider.h
    223  */
    224 class audio_utils_fifo_provider {
    225 public:
    226     audio_utils_fifo_provider(audio_utils_fifo& fifo);
    227     virtual ~audio_utils_fifo_provider();
    228 
    229     /**
    230      * Obtain access to a logically contiguous slice of a stream, represented by \p iovec.
    231      * For the reader(s), the slice is initialized and has read-only access.
    232      * For the writer, the slice is uninitialized and has read/write access.
    233      * It is permitted to call obtain() multiple times without an intervening release().
    234      * Each call resets the notion of most recently obtained slice.
    235      *
    236      * \param iovec Non-NULL pointer to a pair of fragment descriptors.
    237      *              On entry, the descriptors may be uninitialized.
    238      *              On exit, the descriptors are initialized and refer to each of the two fragments.
    239      *              iovec[0] describes the initial fragment of the slice, and
    240      *              iovec[1] describes the remaining non-virtually-contiguous fragment.
    241      *              Empty iovec[0] implies that iovec[1] is also empty.
    242      *              iovec[0].mOffset and iovec[1].mOffset are always < capacity.
    243      *              Typically iovec[1].mOffset is zero, but don't assume that.
    244      * \param count The maximum number of frames to obtain.
    245      *              See setHysteresis() for something which is close to, but not the same as,
    246      *              a minimum.
    247      * \param timeout Indicates the maximum time to block for at least one frame.
    248      *                NULL and {0, 0} both mean non-blocking.
    249      *                Time is expressed as relative CLOCK_MONOTONIC.
    250      *                As an optimization, if \p timeout->tv_sec is the maximum positive value for
    251      *                time_t (LONG_MAX), then the implementation treats it as infinite timeout.
    252      *                See fifo_index.h for explanation of why representation is struct timespec.
    253      *
    254      * \return Actual number of frames available, if greater than or equal to zero.
    255      *         Guaranteed to be <= \p count and == iovec[0].mLength + iovec[1].mLength.
    256      *
    257      *  \retval -EIO        corrupted indices, no recovery is possible
    258      *  \retval -EOVERFLOW  reader doesn't throttle writer, and frames were lost because reader
    259      *                      isn't keeping up with writer; see \p lost
    260      *  \retval -ETIMEDOUT  count is greater than zero, timeout is non-NULL and not {0, 0},
    261      *                      timeout expired, and no frames were available after the timeout.
    262      *  \retval -EINTR      count is greater than zero, timeout is non-NULL and not {0, 0}, timeout
    263      *                      was interrupted by a signal, and no frames were available after signal.
    264      *  \retval -EWOULDBLOCK count is greater than zero, timeout is non-NULL and not {0, 0},
    265      *                      futex wait failed due to benign race, and unable to converge after
    266      *                      retrying.  Should usually handle like -EINTR.
    267      *
    268      * Applications should treat all of these as equivalent to zero available frames,
    269      * except they convey extra information as to the cause.
    270      * After any error, both iovec[0] and iovec[1] will be empty.
    271      */
    272     virtual ssize_t obtain(audio_utils_iovec iovec[2], size_t count,
    273             const struct timespec *timeout = NULL) = 0;
    274 
    275     /**
    276      * Release access to a portion of the most recently obtained slice.
    277      * It is permitted to call release() multiple times without an intervening obtain().
    278      *
    279      * \param count Number of frames to release.  The cumulative number of frames released must not
    280      *              exceed the number of frames most recently obtained.
    281      *              If it ever happens, then the FIFO will be marked unusable with shutdown().
    282      */
    283     virtual void release(size_t count) = 0;
    284 
    285     /**
    286      * Determine the number of frames that could be obtained or read/written without blocking.
    287      * There's an inherent race condition: the value may soon be obsolete so shouldn't be trusted.
    288      * available() may be called after obtain(), but doesn't affect the number of releasable frames.
    289      *
    290      * \return Number of available frames, if greater than or equal to zero.
    291      *  \retval -EIO        corrupted indices, no recovery is possible
    292      *  \retval -EOVERFLOW  reader doesn't throttle writer, and frames were lost because reader
    293      *                      isn't keeping up with writer
    294      */
    295     virtual ssize_t available() = 0;
    296 
    297     /**
    298      * Return the capacity, or statically configured maximum frame count.
    299      *
    300      * \return The capacity in frames.
    301      */
    302     uint32_t capacity() const
    303             { return mFifo.capacity(); }
    304 
    305     /**
    306      * Return the total number of frames released since construction.
    307      * For a reader, this includes lost and flushed frames.
    308      *
    309      * \return Total frames released.
    310      */
    311     uint64_t totalReleased() const
    312             { return mTotalReleased; }
    313 
    314 protected:
    315     audio_utils_fifo&   mFifo;
    316 
    317     /** Number of frames obtained at most recent obtain(), less total number of frames released. */
    318     uint32_t    mObtained;
    319 
    320     /** Number of times to retry a futex wait that fails with EWOULDBLOCK. */
    321     static const int kRetries = 2;
    322 
    323     /**
    324      * Total number of frames released since construction.
    325      * For a reader, this includes lost and flushed frames.
    326      */
    327     uint64_t    mTotalReleased;
    328 };
    329 
    330 ////////////////////////////////////////////////////////////////////////////////
    331 
    332 /**
    333  * Used to write to a FIFO.  There should be exactly one writer per FIFO.
    334  * The writer is multi-thread safe with respect to reader(s),
    335  * but not with respect to multiple threads calling the writer API.
    336  */
    337 class audio_utils_fifo_writer : public audio_utils_fifo_provider {
    338 
    339 public:
    340     /**
    341      * Single-process and multi-process use same constructor here,
    342      * but different FIFO constructors.
    343      *
    344      * \param fifo Associated FIFO.  Passed by reference because it must be non-NULL.
    345      */
    346     explicit audio_utils_fifo_writer(audio_utils_fifo& fifo);
    347     virtual ~audio_utils_fifo_writer();
    348 
    349     /**
    350      * Write to FIFO.  Resets the number of releasable frames to zero.
    351      *
    352      * \param buffer  Pointer to source buffer containing \p count frames of data.
    353      *                Pointer must be non-NULL if \p count is greater than zero.
    354      * \param count   Desired number of frames to write.
    355      * \param timeout Indicates the maximum time to block for at least one frame.
    356      *                NULL and {0, 0} both mean non-blocking.
    357      *                Time is expressed as relative CLOCK_MONOTONIC.
    358      *                As an optimization, if \p timeout->tv_sec is the maximum positive value for
    359      *                time_t (LONG_MAX), then the implementation treats it as infinite timeout.
    360      *                See fifo_index.h for explanation of why representation is struct timespec.
    361      *
    362      * \return Actual number of frames written, if greater than or equal to zero.
    363      *         Guaranteed to be <= \p count.
    364      *         The actual transfer count may be zero if the FIFO is full,
    365      *         or partial if the FIFO was almost full.
    366      *  \retval -EIO       corrupted indices, no recovery is possible
    367      *  \retval -ETIMEDOUT count is greater than zero, timeout is non-NULL and not {0, 0},
    368      *                     timeout expired, and no frames were available after the timeout.
    369      *  \retval -EINTR     count is greater than zero, timeout is non-NULL and not {0, 0}, timeout
    370      *                     was interrupted by a signal, and no frames were available after signal.
    371      *  \retval -EWOULDBLOCK count is greater than zero, timeout is non-NULL and not {0, 0},
    372      *                      futex wait failed due to benign race, and unable to converge after
    373      *                      retrying.  Should usually handle like -EINTR.
    374      */
    375     ssize_t write(const void *buffer, size_t count, const struct timespec *timeout = NULL);
    376 
    377     // Implement audio_utils_fifo_provider
    378     virtual ssize_t obtain(audio_utils_iovec iovec[2], size_t count,
    379             const struct timespec *timeout = NULL);
    380     virtual void release(size_t count);
    381     virtual ssize_t available();
    382 
    383     /**
    384      * Set the current effective buffer size.
    385      * Any filled frames already written or released to the buffer are unaltered, and pending
    386      * releasable frames from obtain() may be release()ed.  However subsequent write() and obtain()
    387      * will be limited such that the total filled frame count is <= the effective buffer size.
    388      * The default effective buffer size is mFifo.mFrameCount.
    389      * Reducing the effective buffer size may update the hysteresis levels; see getHysteresis().
    390      *
    391      * \param frameCount    effective buffer size in frames. Capped to range [0, mFifo.mFrameCount].
    392      */
    393     void resize(uint32_t frameCount);
    394 
    395     /**
    396      * Get the current effective buffer size.
    397      * This value is not exposed to reader(s), and so must be conveyed via an out-of-band channel.
    398      *
    399      * \return effective buffer size in frames
    400      */
    401     uint32_t size() const;
    402 
    403     /**
    404      * Set the hysteresis levels for the writer to wake blocked readers.
    405      * Hysteresis can decrease the number of context switches between writer and a blocking reader.
    406      * A non-empty write() or release() will wake readers
    407      * only if the fill level was < \p armLevel before the write() or release(),
    408      * and then the fill level became > \p triggerLevel afterwards.
    409      * The default value for \p armLevel is mFifo.mFrameCount, which means always armed.
    410      * The default value for \p triggerLevel is zero,
    411      * which means every write() or release() will wake the readers.
    412      * For hysteresis, \p armLevel must be <= \p triggerLevel + 1.
    413      * Increasing \p armLevel will arm for wakeup, regardless of the current fill level.
    414      *
    415      * \param armLevel      Arm for wakeup when fill level < this value.
    416      *                      Capped to range [0, effective buffer size].
    417      * \param triggerLevel  Trigger wakeup when armed and fill level > this value.
    418      *                      Capped to range [0, effective buffer size].
    419      */
    420     void setHysteresis(uint32_t armLevel, uint32_t triggerLevel);
    421 
    422     /**
    423      * Get the hysteresis levels for waking readers.
    424      *
    425      * \param armLevel      Set to the current arm level in frames.
    426      * \param triggerLevel  Set to the current trigger level in frames.
    427      */
    428     void getHysteresis(uint32_t *armLevel, uint32_t *triggerLevel) const;
    429 
    430 private:
    431     // Accessed by writer only using ordinary operations
    432     uint32_t    mLocalRear; // frame index of next frame slot available to write, or write index
    433 
    434     // TODO make a separate class and associate with the synchronization object
    435     uint32_t    mArmLevel;          // arm if filled < arm level before release()
    436     uint32_t    mTriggerLevel;      // trigger if armed and filled > trigger level after release()
    437     bool        mIsArmed;           // whether currently armed
    438 
    439     uint32_t    mEffectiveFrames;   // current effective buffer size, <= mFifo.mFrameCount
    440 };
    441 
    442 ////////////////////////////////////////////////////////////////////////////////
    443 
    444 /**
    445  * Used to read from a FIFO.  There can be one or more readers per FIFO,
    446  * and at most one of those readers can throttle the writer.
    447  * All other readers must keep up with the writer or they will lose frames.
    448  * Each reader is multi-thread safe with respect to the writer and any other readers,
    449  * but not with respect to multiple threads calling the reader API.
    450  */
    451 class audio_utils_fifo_reader : public audio_utils_fifo_provider {
    452 
    453 public:
    454     /**
    455      * Single-process and multi-process use same constructor here,
    456      * but different FIFO constructors.
    457      *
    458      * \param fifo            Associated FIFO.  Passed by reference because it must be non-NULL.
    459      * \param throttlesWriter Whether this reader throttles the writer.
    460      *                        At most one reader can specify throttlesWriter == true.
    461      *                        A non-throttling reader does not see any data written
    462      *                        prior to construction of the reader.
    463      * \param flush           Whether to flush (discard) the entire buffer on -EOVERFLOW.
    464      *                        The advantage of flushing is that it increases the chance that next
    465      *                        read will be successful.  The disadvantage is that it loses more data.
    466      */
    467     explicit audio_utils_fifo_reader(audio_utils_fifo& fifo, bool throttlesWriter = true,
    468                                      bool flush = false);
    469     virtual ~audio_utils_fifo_reader();
    470 
    471     /**
    472      * Read from FIFO.  Resets the number of releasable frames to zero.
    473      *
    474      * \param buffer  Pointer to destination buffer to be filled with up to \p count frames of data.
    475      *                Pointer must be non-NULL if \p count is greater than zero.
    476      * \param count   Desired number of frames to read.
    477      * \param timeout Indicates the maximum time to block for at least one frame.
    478      *                NULL and {0, 0} both mean non-blocking.
    479      *                Time is expressed as relative CLOCK_MONOTONIC.
    480      *                As an optimization, if \p timeout->tv_sec is the maximum positive value for
    481      *                time_t (LONG_MAX), then the implementation treats it as infinite timeout.
    482      *                See fifo_index.h for explanation of why representation is struct timespec.
    483      * \param lost    If non-NULL, set to the approximate number of frames lost before
    484      *                re-synchronization when -EOVERFLOW occurs, or set to zero when no frames lost.
    485      *
    486      * \return Actual number of frames read, if greater than or equal to zero.
    487      *         Guaranteed to be <= \p count.
    488      *         The actual transfer count may be zero if the FIFO is empty,
    489      *         or partial if the FIFO was almost empty.
    490      *  \retval -EIO        corrupted indices, no recovery is possible
    491      *  \retval -EOVERFLOW  reader doesn't throttle writer, and frames were lost because reader
    492      *                      isn't keeping up with writer; see \p lost
    493      *  \retval -ETIMEDOUT  count is greater than zero, timeout is non-NULL and not {0, 0},
    494      *                      timeout expired, and no frames were available after the timeout.
    495      *  \retval -EINTR      count is greater than zero, timeout is non-NULL and not {0, 0}, timeout
    496      *                      was interrupted by a signal, and no frames were available after signal.
    497      *  \retval -EWOULDBLOCK count is greater than zero, timeout is non-NULL and not {0, 0},
    498      *                      futex wait failed due to benign race, and unable to converge after
    499      *                      retrying.  Should usually handle like -EINTR.
    500      */
    501     ssize_t read(void *buffer, size_t count, const struct timespec *timeout = NULL,
    502             size_t *lost = NULL);
    503 
    504     // Implement audio_utils_fifo_provider
    505     virtual ssize_t obtain(audio_utils_iovec iovec[2], size_t count,
    506             const struct timespec *timeout = NULL);
    507     virtual void release(size_t count);
    508     virtual ssize_t available();
    509 
    510     /**
    511      * Same as audio_utils_fifo_provider::obtain, except has an additional parameter \p lost.
    512      *
    513      * \param iovec   See audio_utils_fifo_provider::obtain.
    514      * \param count   See audio_utils_fifo_provider::obtain.
    515      * \param timeout See audio_utils_fifo_provider::obtain.
    516      * \param lost    If non-NULL, set to the approximate number of frames lost before
    517      *                re-synchronization when -EOVERFLOW occurs, or set to zero when no frames lost.
    518      * \return See audio_utils_fifo_provider::obtain for 'Returns' and 'Return values'.
    519      */
    520     ssize_t obtain(audio_utils_iovec iovec[2], size_t count, const struct timespec *timeout,
    521             size_t *lost);
    522 
    523     /**
    524      * Determine the number of frames that could be obtained or read without blocking.
    525      * There's an inherent race condition: the value may soon be obsolete so shouldn't be trusted.
    526      * available() may be called after obtain(), but doesn't affect the number of releasable frames.
    527      *
    528      * \param lost    If non-NULL, set to the approximate number of frames lost before
    529      *                re-synchronization when -EOVERFLOW occurs, or set to zero when no frames lost.
    530      *
    531      * \return Number of available frames, if greater than or equal to zero.
    532      *  \retval -EIO        corrupted indices, no recovery is possible
    533      *  \retval -EOVERFLOW  reader doesn't throttle writer, and frames were lost because reader
    534      *                      isn't keeping up with writer; see \p lost
    535      */
    536     ssize_t available(size_t *lost);
    537 
    538     /**
    539      * Flush (discard) all frames that could be obtained or read without blocking.
    540      * Note that flush is a method on a reader, so if the writer wants to flush
    541      * then it must communicate the request to the reader(s) via an out-of-band channel.
    542      *
    543      * \param lost    If non-NULL, set to the approximate number of frames lost before
    544      *                re-synchronization when -EOVERFLOW occurs, or set to zero when no frames lost.
    545      *
    546      * \return Number of flushed frames, if greater than or equal to zero.
    547      *         This number does not include any lost frames.
    548      *  \retval -EIO        corrupted indices, no recovery is possible
    549      *  \retval -EOVERFLOW  reader doesn't throttle writer, and frames were lost because reader
    550      *                      isn't keeping up with writer; see \p lost
    551      */
    552     ssize_t flush(size_t *lost = NULL);
    553 
    554     /**
    555      * Set the hysteresis levels for a throttling reader to wake a blocked writer.
    556      * Hysteresis can decrease the number of context switches between reader and a blocking writer.
    557      * A non-empty read() or release() by a throttling reader will wake the writer
    558      * only if the fill level was > \p armLevel before the read() or release(),
    559      * and then the fill level became < \p triggerLevel afterwards.
    560      * The default value for \p armLevel is -1, which means always armed.
    561      * The default value for \p triggerLevel is mFifo.mFrameCount,
    562      * which means every read() or release() will wake the writer.
    563      * For hysteresis, \p armLevel must be >= \p triggerLevel - 1.
    564      * Decreasing \p armLevel will arm for wakeup, regardless of the current fill level.
    565      * Note that the throttling reader is not directly aware of the writer's effective buffer size,
    566      * so any change in effective buffer size must be communicated indirectly.
    567      *
    568      * \param armLevel      Arm for wakeup when fill level > this value.
    569      *                      Capped to range [-1, mFifo.mFrameCount].
    570      * \param triggerLevel  Trigger wakeup when armed and fill level < this value.
    571      *                      Capped to range [0, mFifo.mFrameCount].
    572      */
    573     void setHysteresis(int32_t armLevel, uint32_t triggerLevel);
    574 
    575     /**
    576      * Get the hysteresis levels for waking readers.
    577      *
    578      * \param armLevel      Set to the current arm level in frames.
    579      * \param triggerLevel  Set to the current trigger level in frames.
    580      */
    581     void getHysteresis(int32_t *armLevel, uint32_t *triggerLevel) const;
    582 
    583     /**
    584      * Return the total number of lost frames since construction, due to reader not keeping up with
    585      * writer.  Does not include flushed frames.
    586      * It is necessary to call read(), obtain(), or flush() prior to calling this method,
    587      * in order to observe an increase in the total,
    588      * but it is not necessary for the 'lost' parameter of those prior calls to be non-NULL.
    589      *
    590      * \return Total lost frames.
    591      */
    592     uint64_t totalLost() const
    593             { return mTotalLost; }
    594 
    595     /**
    596      * Return the total number of flushed frames since construction.
    597      * Does not include lost frames.
    598      *
    599      * \return Total flushed frames.
    600      */
    601     uint64_t totalFlushed() const
    602             { return mTotalFlushed; }
    603 
    604 private:
    605     // Accessed by reader only using ordinary operations
    606     uint32_t     mLocalFront;   // frame index of first frame slot available to read, or read index
    607 
    608     // Points to shared front index if this reader throttles writer, or NULL if we don't throttle
    609     // FIXME consider making it a boolean
    610     audio_utils_fifo_index*     mThrottleFront;
    611 
    612     bool        mFlush;             // whether to flush the entire buffer on -EOVERFLOW
    613 
    614     int32_t     mArmLevel;          // arm if filled > arm level before release()
    615     uint32_t    mTriggerLevel;      // trigger if armed and filled < trigger level after release()
    616     bool        mIsArmed;           // whether currently armed
    617 
    618     uint64_t    mTotalLost;         // total lost frames, does not include flushed frames
    619     uint64_t    mTotalFlushed;      // total flushed frames, does not include lost frames
    620 };
    621 
    622 #endif  // !ANDROID_AUDIO_FIFO_H
    623