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