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