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      */
capacity()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      */
frameSize()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      */
buffer()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      */
capacity()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      */
totalReleased()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      */
totalLost()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      */
totalFlushed()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