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. */
29enum 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 */
44class audio_utils_fifo_base {
45
46public:
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
56protected:
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 */
139class audio_utils_fifo : public audio_utils_fifo_base {
140
141    friend class audio_utils_fifo_reader;
142    friend class audio_utils_fifo_writer;
143    friend class audio_utils_fifo_writer32;
144
145public:
146
147    /**
148     * Construct a FIFO object: multi-process.
149     *
150     *  \param frameCount  Maximum usable frames to be stored in the FIFO > 0 && <= INT32_MAX,
151     *                     aka "capacity".
152     *                     If writes and reads always use the same count, and the count is a divisor
153     *                     of \p frameCount, then the writes and reads won't do a partial transfer.
154     *  \param frameSize   Size of each frame in bytes > 0,
155     *                     \p frameSize * \p frameCount <= INT32_MAX.
156     *  \param buffer      Pointer to a non-NULL caller-allocated buffer of \p frameCount frames.
157     *  \param writerRear  Writer's rear index.  Passed by reference because it must be non-NULL.
158     *  \param throttleFront Pointer to the front index of at most one reader that throttles the
159     *                       writer, or NULL for no throttling.
160     */
161    audio_utils_fifo(uint32_t frameCount, uint32_t frameSize, void *buffer,
162            audio_utils_fifo_index& writerRear, audio_utils_fifo_index *throttleFront = NULL);
163
164    /**
165     * Construct a FIFO object: single-process.
166     *  \param frameCount  Maximum usable frames to be stored in the FIFO > 0 && <= INT32_MAX,
167     *                     aka "capacity".
168     *                     If writes and reads always use the same count, and the count is a divisor
169     *                     of \p frameCount, then the writes and reads won't do a partial transfer.
170     *  \param frameSize   Size of each frame in bytes > 0,
171     *                     \p frameSize * \p frameCount <= INT32_MAX.
172     *  \param buffer      Pointer to a non-NULL caller-allocated buffer of \p frameCount frames.
173     *  \param throttlesWriter Whether there is one reader that throttles the writer.
174     */
175    audio_utils_fifo(uint32_t frameCount, uint32_t frameSize, void *buffer,
176            bool throttlesWriter = true);
177
178    /*virtual*/ ~audio_utils_fifo();
179
180    /**
181     * Return the frame size in bytes.
182     *
183     * \return frame size in bytes, always > 0.
184     */
185    uint32_t frameSize() const
186            { return mFrameSize; }
187
188    /**
189     * Return a pointer to the caller-allocated buffer.
190     *
191     * \return non-NULL pointer to buffer.
192     */
193    void *buffer() const
194            { return mBuffer; }
195
196private:
197    // These fields are const after initialization
198    const uint32_t mFrameSize;  // size of each frame in bytes
199    void * const   mBuffer;     // non-NULL pointer to caller-allocated buffer
200                                // of size mFrameCount frames
201
202    // only used for single-process constructor
203    audio_utils_fifo_index      mSingleProcessSharedRear;
204
205    // only used for single-process constructor when throttlesWriter == true
206    audio_utils_fifo_index      mSingleProcessSharedFront;
207};
208
209/**
210 * Describes one virtually contiguous fragment of a logically contiguous slice.
211 * Compare to struct iovec for readv(2) and writev(2).
212 */
213struct audio_utils_iovec {
214    /** Offset of fragment in frames, relative to mBuffer, undefined if mLength == 0 */
215    uint32_t    mOffset;
216    /** Length of fragment in frames, 0 means fragment is empty */
217    uint32_t    mLength;
218};
219
220////////////////////////////////////////////////////////////////////////////////
221
222/**
223 * Based on frameworks/av/include/media/AudioBufferProvider.h
224 */
225class audio_utils_fifo_provider {
226public:
227    audio_utils_fifo_provider(audio_utils_fifo& fifo);
228    virtual ~audio_utils_fifo_provider();
229
230    /**
231     * Obtain access to a logically contiguous slice of a stream, represented by \p iovec.
232     * For the reader(s), the slice is initialized and has read-only access.
233     * For the writer, the slice is uninitialized and has read/write access.
234     * It is permitted to call obtain() multiple times without an intervening release().
235     * Each call resets the notion of most recently obtained slice.
236     *
237     * \param iovec Non-NULL pointer to a pair of fragment descriptors.
238     *              On entry, the descriptors may be uninitialized.
239     *              On exit, the descriptors are initialized and refer to each of the two fragments.
240     *              iovec[0] describes the initial fragment of the slice, and
241     *              iovec[1] describes the remaining non-virtually-contiguous fragment.
242     *              Empty iovec[0] implies that iovec[1] is also empty.
243     *              iovec[0].mOffset and iovec[1].mOffset are always < capacity.
244     *              Typically iovec[1].mOffset is zero, but don't assume that.
245     * \param count The maximum number of frames to obtain.
246     *              See setHysteresis() for something which is close to, but not the same as,
247     *              a minimum.
248     * \param timeout Indicates the maximum time to block for at least one frame.
249     *                NULL and {0, 0} both mean non-blocking.
250     *                Time is expressed as relative CLOCK_MONOTONIC.
251     *                As an optimization, if \p timeout->tv_sec is the maximum positive value for
252     *                time_t (LONG_MAX), then the implementation treats it as infinite timeout.
253     *                See fifo_index.h for explanation of why representation is struct timespec.
254     *
255     * \return Actual number of frames available, if greater than or equal to zero.
256     *         Guaranteed to be <= \p count and == iovec[0].mLength + iovec[1].mLength.
257     *         For a reader this is also guaranteed to be <= capacity.
258     *         For a writer this is also guaranteed to be <= effective buffer size,
259     *         even if there is no reader that throttles writer.
260     *
261     *  \retval -EIO        corrupted indices, no recovery is possible
262     *  \retval -EOVERFLOW  reader doesn't throttle writer, and frames were lost because reader
263     *                      isn't keeping up with writer; see \p lost
264     *  \retval -ETIMEDOUT  count is greater than zero, timeout is non-NULL and not {0, 0},
265     *                      timeout expired, and no frames were available after the timeout.
266     *  \retval -EINTR      count is greater than zero, timeout is non-NULL and not {0, 0}, timeout
267     *                      was interrupted by a signal, and no frames were available after signal.
268     *  \retval -EWOULDBLOCK count is greater than zero, timeout is non-NULL and not {0, 0},
269     *                      futex wait failed due to benign race, and unable to converge after
270     *                      retrying.  Should usually handle like -EINTR.
271     *
272     * Applications should treat all of these as equivalent to zero available frames,
273     * except they convey extra information as to the cause.
274     * After any error, both iovec[0] and iovec[1] will be empty.
275     */
276    virtual ssize_t obtain(audio_utils_iovec iovec[2], size_t count,
277            const struct timespec *timeout = NULL) = 0;
278
279    /**
280     * Release access to a portion of the most recently obtained slice.
281     * It is permitted to call release() multiple times without an intervening obtain().
282     *
283     * \param count Number of frames to release.  The cumulative number of frames released must not
284     *              exceed the number of frames most recently obtained.
285     *              If it ever happens, then the FIFO will be marked unusable with shutdown().
286     */
287    virtual void release(size_t count) = 0;
288
289    /**
290     * Determine the number of frames that could be obtained or read/written without blocking.
291     * There's an inherent race condition: the value may soon be obsolete so shouldn't be trusted.
292     * available() may be called after obtain(), but doesn't affect the number of releasable frames.
293     *
294     * \return Number of available frames, if greater than or equal to zero.
295     *  \retval -EIO        corrupted indices, no recovery is possible
296     *  \retval -EOVERFLOW  reader doesn't throttle writer, and frames were lost because reader
297     *                      isn't keeping up with writer
298     */
299    virtual ssize_t available() = 0;
300
301    /**
302     * Return the capacity, or statically configured maximum frame count.
303     *
304     * \return The capacity in frames.
305     */
306    uint32_t capacity() const
307            { return mFifo.capacity(); }
308
309    /**
310     * Return the total number of frames released since construction.
311     * For a reader, this includes lost and flushed frames.
312     *
313     * \return Total frames released.
314     */
315    uint64_t totalReleased() const
316            { return mTotalReleased; }
317
318protected:
319    audio_utils_fifo&   mFifo;
320
321    /** Number of frames obtained at most recent obtain(), less total number of frames released. */
322    uint32_t    mObtained;
323
324    /** Number of times to retry a futex wait that fails with EWOULDBLOCK. */
325    static const int kRetries = 2;
326
327    /**
328     * Total number of frames released since construction.
329     * For a reader, this includes lost and flushed frames.
330     */
331    uint64_t    mTotalReleased;
332};
333
334////////////////////////////////////////////////////////////////////////////////
335
336/**
337 * Used to write to a FIFO.  There should be exactly one writer per FIFO.
338 * The writer is multi-thread safe with respect to reader(s),
339 * but not with respect to multiple threads calling the writer API.
340 */
341class audio_utils_fifo_writer : public audio_utils_fifo_provider {
342
343public:
344    /**
345     * Single-process and multi-process use same constructor here,
346     * but different FIFO constructors.
347     *
348     * \param fifo Associated FIFO.  Passed by reference because it must be non-NULL.
349     */
350    explicit audio_utils_fifo_writer(audio_utils_fifo& fifo);
351    virtual ~audio_utils_fifo_writer();
352
353    /**
354     * Write to FIFO.  Resets the number of releasable frames to zero.
355     *
356     * \param buffer  Pointer to source buffer containing \p count frames of data.
357     *                Pointer must be non-NULL if \p count is greater than zero.
358     * \param count   Desired number of frames to write.
359     * \param timeout Indicates the maximum time to block for at least one frame.
360     *                NULL and {0, 0} both mean non-blocking.
361     *                Time is expressed as relative CLOCK_MONOTONIC.
362     *                As an optimization, if \p timeout->tv_sec is the maximum positive value for
363     *                time_t (LONG_MAX), then the implementation treats it as infinite timeout.
364     *                See fifo_index.h for explanation of why representation is struct timespec.
365     *
366     * \return Actual number of frames written, if greater than or equal to zero.
367     *         Guaranteed to be <= \p count.
368     *         Also guaranteed to be <= effective buffer size,
369     *         even if there is no reader that throttles writer.
370     *         The actual transfer count may be zero if the FIFO is full,
371     *         or partial if the FIFO was almost full.
372     *  \retval -EIO       corrupted indices, no recovery is possible
373     *  \retval -ETIMEDOUT count is greater than zero, timeout is non-NULL and not {0, 0},
374     *                     timeout expired, and no frames were available after the timeout.
375     *  \retval -EINTR     count is greater than zero, timeout is non-NULL and not {0, 0}, timeout
376     *                     was interrupted by a signal, and no frames were available after signal.
377     *  \retval -EWOULDBLOCK count is greater than zero, timeout is non-NULL and not {0, 0},
378     *                      futex wait failed due to benign race, and unable to converge after
379     *                      retrying.  Should usually handle like -EINTR.
380     */
381    ssize_t write(const void *buffer, size_t count, const struct timespec *timeout = NULL);
382
383    // Implement audio_utils_fifo_provider
384    virtual ssize_t obtain(audio_utils_iovec iovec[2], size_t count,
385            const struct timespec *timeout = NULL);
386    virtual void release(size_t count);
387    virtual ssize_t available();
388
389    /**
390     * Set the current effective buffer size.
391     * Any filled frames already written or released to the buffer are unaltered, and pending
392     * releasable frames from obtain() may be release()ed.  However subsequent write() and obtain()
393     * will be limited such that the total filled frame count is <= the effective buffer size.
394     * The default effective buffer size is mFifo.mFrameCount.
395     * Reducing the effective buffer size may update the hysteresis levels; see getHysteresis().
396     *
397     * \param frameCount    effective buffer size in frames. Capped to range [0, mFifo.mFrameCount].
398     */
399    void resize(uint32_t frameCount);
400
401    /**
402     * Get the current effective buffer size.
403     * This value is not exposed to reader(s), and so must be conveyed via an out-of-band channel.
404     *
405     * \return effective buffer size in frames
406     */
407    uint32_t size() const;
408
409    /**
410     * Set the hysteresis levels for the writer to wake blocked readers.
411     * Hysteresis can decrease the number of context switches between writer and a blocking reader.
412     * A non-empty write() or release() will wake readers
413     * only if the fill level was < \p armLevel before the write() or release(),
414     * and then the fill level became > \p triggerLevel afterwards.
415     * The default value for \p armLevel is mFifo.mFrameCount, which means always armed.
416     * The default value for \p triggerLevel is zero,
417     * which means every write() or release() will wake the readers.
418     * For hysteresis, \p armLevel must be <= \p triggerLevel + 1.
419     * Increasing \p armLevel will arm for wakeup, regardless of the current fill level.
420     *
421     * \param armLevel      Arm for wakeup when fill level < this value.
422     *                      Capped to range [0, effective buffer size].
423     * \param triggerLevel  Trigger wakeup when armed and fill level > this value.
424     *                      Capped to range [0, effective buffer size].
425     */
426    void setHysteresis(uint32_t armLevel, uint32_t triggerLevel);
427
428    /**
429     * Get the hysteresis levels for waking readers.
430     *
431     * \param armLevel      Set to the current arm level in frames.
432     * \param triggerLevel  Set to the current trigger level in frames.
433     */
434    void getHysteresis(uint32_t *armLevel, uint32_t *triggerLevel) const;
435
436private:
437    // Accessed by writer only using ordinary operations
438    uint32_t    mLocalRear; // frame index of next frame slot available to write, or write index
439
440    // TODO make a separate class and associate with the synchronization object
441    uint32_t    mArmLevel;          // arm if filled < arm level before release()
442    uint32_t    mTriggerLevel;      // trigger if armed and filled > trigger level after release()
443    bool        mIsArmed;           // whether currently armed
444
445    uint32_t    mEffectiveFrames;   // current effective buffer size, <= mFifo.mFrameCount
446};
447
448////////////////////////////////////////////////////////////////////////////////
449
450/**
451 * Used to read from a FIFO.  There can be one or more readers per FIFO,
452 * and at most one of those readers can throttle the writer.
453 * All other readers must keep up with the writer or they will lose frames.
454 * Each reader is multi-thread safe with respect to the writer and any other readers,
455 * but not with respect to multiple threads calling the reader API.
456 */
457class audio_utils_fifo_reader : public audio_utils_fifo_provider {
458
459public:
460    /**
461     * Single-process and multi-process use same constructor here,
462     * but different FIFO constructors.
463     *
464     * \param fifo            Associated FIFO.  Passed by reference because it must be non-NULL.
465     * \param throttlesWriter Whether this reader throttles the writer.
466     *                        At most one reader can specify throttlesWriter == true.
467     *                        A non-throttling reader does not see any data written
468     *                        prior to construction of the reader.
469     * \param flush           Whether to flush (discard) the entire buffer on -EOVERFLOW.
470     *                        The advantage of flushing is that it increases the chance that next
471     *                        read will be successful.  The disadvantage is that it loses more data.
472     */
473    explicit audio_utils_fifo_reader(audio_utils_fifo& fifo, bool throttlesWriter = true,
474                                     bool flush = false);
475    virtual ~audio_utils_fifo_reader();
476
477    /**
478     * Read from FIFO.  Resets the number of releasable frames to zero.
479     *
480     * \param buffer  Pointer to destination buffer to be filled with up to \p count frames of data.
481     *                Pointer must be non-NULL if \p count is greater than zero.
482     * \param count   Desired number of frames to read.
483     * \param timeout Indicates the maximum time to block for at least one frame.
484     *                NULL and {0, 0} both mean non-blocking.
485     *                Time is expressed as relative CLOCK_MONOTONIC.
486     *                As an optimization, if \p timeout->tv_sec is the maximum positive value for
487     *                time_t (LONG_MAX), then the implementation treats it as infinite timeout.
488     *                See fifo_index.h for explanation of why representation is struct timespec.
489     * \param lost    If non-NULL, set to the approximate number of frames lost before
490     *                re-synchronization when -EOVERFLOW occurs, or set to zero when no frames lost.
491     *
492     * \return Actual number of frames read, if greater than or equal to zero.
493     *         Guaranteed to be <= \p count.
494     *         Also guaranteed to be <= capacity.
495     *         The actual transfer count may be zero if the FIFO is empty,
496     *         or partial if the FIFO was almost empty.
497     *  \retval -EIO        corrupted indices, no recovery is possible
498     *  \retval -EOVERFLOW  reader doesn't throttle writer, and frames were lost because reader
499     *                      isn't keeping up with writer; see \p lost
500     *  \retval -ETIMEDOUT  count is greater than zero, timeout is non-NULL and not {0, 0},
501     *                      timeout expired, and no frames were available after the timeout.
502     *  \retval -EINTR      count is greater than zero, timeout is non-NULL and not {0, 0}, timeout
503     *                      was interrupted by a signal, and no frames were available after signal.
504     *  \retval -EWOULDBLOCK count is greater than zero, timeout is non-NULL and not {0, 0},
505     *                      futex wait failed due to benign race, and unable to converge after
506     *                      retrying.  Should usually handle like -EINTR.
507     */
508    ssize_t read(void *buffer, size_t count, const struct timespec *timeout = NULL,
509            size_t *lost = NULL);
510
511    // Implement audio_utils_fifo_provider
512    virtual ssize_t obtain(audio_utils_iovec iovec[2], size_t count,
513            const struct timespec *timeout = NULL);
514    virtual void release(size_t count);
515    virtual ssize_t available();
516
517    /**
518     * Same as audio_utils_fifo_provider::obtain, except has an additional parameter \p lost.
519     *
520     * \param iovec   See audio_utils_fifo_provider::obtain.
521     * \param count   See audio_utils_fifo_provider::obtain.
522     * \param timeout See audio_utils_fifo_provider::obtain.
523     * \param lost    If non-NULL, set to the approximate number of frames lost before
524     *                re-synchronization when -EOVERFLOW occurs, or set to zero when no frames lost.
525     * \return See audio_utils_fifo_provider::obtain for 'Returns' and 'Return values'.
526     */
527    ssize_t obtain(audio_utils_iovec iovec[2], size_t count, const struct timespec *timeout,
528            size_t *lost);
529
530    /**
531     * Determine the number of frames that could be obtained or read without blocking.
532     * There's an inherent race condition: the value may soon be obsolete so shouldn't be trusted.
533     * available() may be called after obtain(), but doesn't affect the number of releasable frames.
534     *
535     * \param lost    If non-NULL, set to the approximate number of frames lost before
536     *                re-synchronization when -EOVERFLOW occurs, or set to zero when no frames lost.
537     *
538     * \return Number of available frames, if greater than or equal to zero.
539     *  \retval -EIO        corrupted indices, no recovery is possible
540     *  \retval -EOVERFLOW  reader doesn't throttle writer, and frames were lost because reader
541     *                      isn't keeping up with writer; see \p lost
542     */
543    ssize_t available(size_t *lost);
544
545    /**
546     * Flush (discard) all frames that could be obtained or read without blocking.
547     * Note that flush is a method on a reader, so if the writer wants to flush
548     * then it must communicate the request to the reader(s) via an out-of-band channel.
549     *
550     * \param lost    If non-NULL, set to the approximate number of frames lost before
551     *                re-synchronization when -EOVERFLOW occurs, or set to zero when no frames lost.
552     *
553     * \return Number of flushed frames, if greater than or equal to zero.
554     *         This number does not include any lost frames.
555     *  \retval -EIO        corrupted indices, no recovery is possible
556     *  \retval -EOVERFLOW  reader doesn't throttle writer, and frames were lost because reader
557     *                      isn't keeping up with writer; see \p lost
558     */
559    ssize_t flush(size_t *lost = NULL);
560
561    /**
562     * Set the hysteresis levels for a throttling reader to wake a blocked writer.
563     * Hysteresis can decrease the number of context switches between reader and a blocking writer.
564     * A non-empty read() or release() by a throttling reader will wake the writer
565     * only if the fill level was > \p armLevel before the read() or release(),
566     * and then the fill level became < \p triggerLevel afterwards.
567     * The default value for \p armLevel is -1, which means always armed.
568     * The default value for \p triggerLevel is mFifo.mFrameCount,
569     * which means every read() or release() will wake the writer.
570     * For hysteresis, \p armLevel must be >= \p triggerLevel - 1.
571     * Decreasing \p armLevel will arm for wakeup, regardless of the current fill level.
572     * Note that the throttling reader is not directly aware of the writer's effective buffer size,
573     * so any change in effective buffer size must be communicated indirectly.
574     *
575     * \param armLevel      Arm for wakeup when fill level > this value.
576     *                      Capped to range [-1, mFifo.mFrameCount].
577     * \param triggerLevel  Trigger wakeup when armed and fill level < this value.
578     *                      Capped to range [0, mFifo.mFrameCount].
579     */
580    void setHysteresis(int32_t armLevel, uint32_t triggerLevel);
581
582    /**
583     * Get the hysteresis levels for waking readers.
584     *
585     * \param armLevel      Set to the current arm level in frames.
586     * \param triggerLevel  Set to the current trigger level in frames.
587     */
588    void getHysteresis(int32_t *armLevel, uint32_t *triggerLevel) const;
589
590    /**
591     * Return the total number of lost frames since construction, due to reader not keeping up with
592     * writer.  Does not include flushed frames.
593     * It is necessary to call read(), obtain(), or flush() prior to calling this method,
594     * in order to observe an increase in the total,
595     * but it is not necessary for the 'lost' parameter of those prior calls to be non-NULL.
596     *
597     * \return Total lost frames.
598     */
599    uint64_t totalLost() const
600            { return mTotalLost; }
601
602    /**
603     * Return the total number of flushed frames since construction.
604     * Does not include lost frames.
605     *
606     * \return Total flushed frames.
607     */
608    uint64_t totalFlushed() const
609            { return mTotalFlushed; }
610
611private:
612    // Accessed by reader only using ordinary operations
613    uint32_t     mLocalFront;   // frame index of first frame slot available to read, or read index
614
615    // Points to shared front index if this reader throttles writer, or NULL if we don't throttle
616    // FIXME consider making it a boolean
617    audio_utils_fifo_index*     mThrottleFront;
618
619    bool        mFlush;             // whether to flush the entire buffer on -EOVERFLOW
620
621    int32_t     mArmLevel;          // arm if filled > arm level before release()
622    uint32_t    mTriggerLevel;      // trigger if armed and filled < trigger level after release()
623    bool        mIsArmed;           // whether currently armed
624
625    uint64_t    mTotalLost;         // total lost frames, does not include flushed frames
626    uint64_t    mTotalFlushed;      // total flushed frames, does not include lost frames
627};
628
629#endif  // !ANDROID_AUDIO_FIFO_H
630