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