tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

cubeb_aaudio.cpp (69734B)


      1 /* ex: set tabstop=2 shiftwidth=2 expandtab:
      2 * Copyright © 2019 Jan Kelling
      3 *
      4 * This program is made available under an ISC-style license.  See the
      5 * accompanying file LICENSE for details.
      6 */
      7 #include "cubeb-internal.h"
      8 #include "cubeb/cubeb.h"
      9 #include "cubeb_android.h"
     10 #include "cubeb_log.h"
     11 #include "cubeb_resampler.h"
     12 #include "cubeb_triple_buffer.h"
     13 #include <aaudio/AAudio.h>
     14 #include <android/api-level.h>
     15 #include <atomic>
     16 #include <cassert>
     17 #include <chrono>
     18 #include <condition_variable>
     19 #include <cstdint>
     20 #include <cstring>
     21 #include <dlfcn.h>
     22 #include <inttypes.h>
     23 #include <limits>
     24 #include <memory>
     25 #include <mutex>
     26 #include <thread>
     27 #include <variant>
     28 #include <vector>
     29 
     30 using namespace std;
     31 
     32 #ifdef DISABLE_LIBAAUDIO_DLOPEN
     33 #define WRAP(x) x
     34 #else
     35 #define WRAP(x) AAudioLibrary::get().x
     36 #define LIBAAUDIO_API_VISIT(X)                                                 \
     37  X(AAudio_convertResultToText)                                                \
     38  X(AAudio_convertStreamStateToText)                                           \
     39  X(AAudio_createStreamBuilder)                                                \
     40  X(AAudioStreamBuilder_openStream)                                            \
     41  X(AAudioStreamBuilder_setChannelCount)                                       \
     42  X(AAudioStreamBuilder_setBufferCapacityInFrames)                             \
     43  X(AAudioStreamBuilder_setDirection)                                          \
     44  X(AAudioStreamBuilder_setFormat)                                             \
     45  X(AAudioStreamBuilder_setSharingMode)                                        \
     46  X(AAudioStreamBuilder_setPerformanceMode)                                    \
     47  X(AAudioStreamBuilder_setSampleRate)                                         \
     48  X(AAudioStreamBuilder_delete)                                                \
     49  X(AAudioStreamBuilder_setDataCallback)                                       \
     50  X(AAudioStreamBuilder_setErrorCallback)                                      \
     51  X(AAudioStream_close)                                                        \
     52  X(AAudioStream_read)                                                         \
     53  X(AAudioStream_requestStart)                                                 \
     54  X(AAudioStream_requestPause)                                                 \
     55  X(AAudioStream_getTimestamp)                                                 \
     56  X(AAudioStream_requestFlush)                                                 \
     57  X(AAudioStream_requestStop)                                                  \
     58  X(AAudioStream_getPerformanceMode)                                           \
     59  X(AAudioStream_getSharingMode)                                               \
     60  X(AAudioStream_getBufferSizeInFrames)                                        \
     61  X(AAudioStream_getBufferCapacityInFrames)                                    \
     62  X(AAudioStream_getSampleRate)                                                \
     63  X(AAudioStream_waitForStateChange)                                           \
     64  X(AAudioStream_getFramesRead)                                                \
     65  X(AAudioStream_getState)                                                     \
     66  X(AAudioStream_getFramesWritten)                                             \
     67  X(AAudioStream_getFramesPerBurst)                                            \
     68  X(AAudioStream_setBufferSizeInFrames)                                        \
     69  X(AAudioStreamBuilder_setInputPreset)                                        \
     70  X(AAudioStreamBuilder_setUsage)                                              \
     71  X(AAudioStreamBuilder_setFramesPerDataCallback)
     72 
     73 class AAudioLibrary {
     74 public:
     75  static AAudioLibrary & get()
     76  {
     77    static AAudioLibrary singleton;
     78    return singleton;
     79  }
     80 
     81  bool load()
     82  {
     83    lock_guard lock(mutex);
     84    if (state != State::Uninitialized) {
     85      return state == State::Loaded;
     86    }
     87 
     88    libaaudio = dlopen("libaaudio.so", RTLD_NOW);
     89    if (!libaaudio) {
     90      LOG("AAudio: Failed to open libaaudio.so: %s", dlerror());
     91      state = State::Failed;
     92      return false;
     93    }
     94 
     95 #define LOAD(x)                                                                \
     96  x = reinterpret_cast<decltype(::x) *>(dlsym(libaaudio, #x));                 \
     97  if (!x) {                                                                    \
     98    LOG("AAudio: Failed to load symbol %s: %s", #x, dlerror());                \
     99    dlclose(libaaudio);                                                        \
    100    libaaudio = nullptr;                                                       \
    101    state = State::Failed;                                                     \
    102    return false;                                                              \
    103  }
    104    LIBAAUDIO_API_VISIT(LOAD)
    105 #undef LOAD
    106 
    107    state = State::Loaded;
    108    return true;
    109  }
    110 
    111 #define DECLARE(x) decltype(::x) * x = nullptr;
    112  LIBAAUDIO_API_VISIT(DECLARE)
    113 #undef DECLARE
    114 
    115 private:
    116  enum class State { Uninitialized, Loaded, Failed };
    117 
    118  AAudioLibrary() = default;
    119 
    120  ~AAudioLibrary()
    121  {
    122    if (libaaudio) {
    123      dlclose(libaaudio);
    124    }
    125  }
    126 
    127  AAudioLibrary(const AAudioLibrary &) = delete;
    128  AAudioLibrary & operator=(const AAudioLibrary &) = delete;
    129 
    130  void * libaaudio = nullptr;
    131  State state = State::Uninitialized;
    132  mutex mutex;
    133 };
    134 #endif
    135 
    136 const uint8_t MAX_STREAMS = 16;
    137 const int64_t NS_PER_S = static_cast<int64_t>(1e9);
    138 
    139 static void
    140 aaudio_stream_destroy(cubeb_stream * stm);
    141 static int
    142 aaudio_stream_start(cubeb_stream * stm);
    143 static int
    144 aaudio_stream_stop(cubeb_stream * stm);
    145 
    146 static int
    147 aaudio_stream_init_impl(cubeb_stream * stm, lock_guard<mutex> & lock);
    148 static int
    149 aaudio_stream_stop_locked(cubeb_stream * stm, lock_guard<mutex> & lock);
    150 static void
    151 aaudio_stream_destroy_locked(cubeb_stream * stm, lock_guard<mutex> & lock);
    152 static int
    153 aaudio_stream_start_locked(cubeb_stream * stm, lock_guard<mutex> & lock);
    154 
    155 static void
    156 reinitialize_stream(cubeb_stream * stm);
    157 
    158 enum class stream_state {
    159  INIT = 0,
    160  STOPPED,
    161  STOPPING,
    162  STARTED,
    163  STARTING,
    164  DRAINING,
    165  ERROR,
    166  SHUTDOWN,
    167 };
    168 
    169 struct AAudioTimingInfo {
    170  // The timestamp at which the audio engine last called the calback.
    171  uint64_t tstamp;
    172  // The number of output frames sent to the engine.
    173  uint64_t output_frame_index;
    174  // The current output latency in frames. 0 if there is no output stream.
    175  uint32_t output_latency;
    176  // The current input latency in frames. 0 if there is no input stream.
    177  uint32_t input_latency;
    178 };
    179 
    180 /* To guess the current position of the stream when it's playing, the elapsed
    181 * time between the last callback and now is used. However, when the stream was
    182 * stopped and there was no new callback after playing restarted yet, the time
    183 * spent in stopped state should be excluded. It's also necessary to track the
    184 * number of audio frames written to stream before reinitialization so it can be
    185 * used to offset the position later, because
    186 * `AAudioTimingInfo.output_frame_index` will restart from zero after
    187 * reinitializing.
    188 * This class defines an internal state machine that takes the stream state
    189 * changes and callback emissions as events to changes it own states and
    190 * estimates played time accordingly.
    191 *
    192 * A simplified |stream_state| transitions of playing looks like:
    193 * INIT -> [STARTING/STARTED -> callback* -> STOPPING/STOPPED]* -> SHUTDOWN|INIT
    194 *
    195 * Internal states:
    196 * - None: the initial state.
    197 * - Play: stream is playing.
    198 * - Pause: stream is not playing. Holds stop timestamp.
    199 * - Resume: stream is playing after stopping and no callback emitted yet. Holds
    200 *           time elapsed in the previous Pause state.
    201 * Transitions:
    202 * - None -(STARTING)-> Play
    203 * - Play -(STOPPING)-> Pause
    204 * - Pause -(STARTING)-> Resume
    205 * - Resume -(callback)-> Play
    206 * - Resume -(STARTING)-> Resume
    207 * - Pause -(INIT)-> None
    208 */
    209 class position_estimate {
    210 public:
    211  // Called with the current time when stopping the stream.
    212  void stop(uint64_t timestamp)
    213  {
    214    assert(in_state<Play>() || in_state<Resume>());
    215    // Change to Pause and save the current time in it. Timestamp offset by the
    216    // elapsed time in previous Pause if stream stops again before any callback
    217    // clears it.
    218    set_pause_timestamp(in_state<Play>() ? timestamp
    219                                         : timestamp - get_pause_time());
    220  }
    221 
    222  // Called with the current time when starting the stream.
    223  void start(uint64_t timestamp)
    224  {
    225    assert(in_state<None>() || in_state<Pause>());
    226    if (in_state<Pause>()) {
    227      // Change to Resume and record elapsed time in it.
    228      set_pause_time(timestamp - get_pause_timestamp());
    229    } else {
    230      set_state<Play>();
    231    }
    232  }
    233 
    234  // Calculate how much time the stream bas been playing since last callback.
    235  uint64_t elapsed_time_since_callback(uint64_t now,
    236                                       uint64_t last_callback_timestamp)
    237  {
    238    if (in_state<Play>()) {
    239      if (callback_timestamp != last_callback_timestamp) {
    240        callback_timestamp = last_callback_timestamp;
    241      }
    242      return now - last_callback_timestamp;
    243    } else if (in_state<Resume>()) {
    244      if (callback_timestamp == last_callback_timestamp) {
    245        // Stream was stopped and no callback emited yet: exclude elapsed time
    246        // in Pause state.
    247        return now - last_callback_timestamp - get_pause_time();
    248      }
    249      // Callback emitted: update callback timestamp and change to Play.
    250      callback_timestamp = last_callback_timestamp;
    251      set_state<Play>();
    252      return now - last_callback_timestamp;
    253    } else if (in_state<Pause>()) {
    254      assert(callback_timestamp == last_callback_timestamp);
    255      // Use recorded timestamps when Paused.
    256      return get_pause_timestamp() - callback_timestamp;
    257    } else {
    258      assert(in_state<None>());
    259      return 0;
    260    }
    261  }
    262 
    263  // Called when reinitializing stream. The input parameter is how many frames
    264  // have already been written to AAudio since the first initialization.
    265  void reinit(uint64_t position)
    266  {
    267    init_position = position;
    268    state = None{};
    269    callback_timestamp = 0;
    270  }
    271 
    272  // Frame index when last reinitialized.
    273  uint64_t initial_position() { return init_position; }
    274 
    275 private:
    276  template <typename T> void set_state() { state.emplace<T>(); }
    277 
    278  template <typename T> bool in_state()
    279  {
    280    return std::holds_alternative<T>(state);
    281  }
    282 
    283  void set_pause_time(uint64_t time) { state.emplace<Resume>(time); }
    284 
    285  uint64_t get_pause_time()
    286  {
    287    assert(in_state<Resume>());
    288    return std::get<Resume>(state).pause_time;
    289  }
    290 
    291  void set_pause_timestamp(uint64_t timestamp)
    292  {
    293    state.emplace<Pause>(timestamp);
    294  }
    295 
    296  uint64_t get_pause_timestamp()
    297  {
    298    assert(in_state<Pause>());
    299    return std::get<Pause>(state).timestamp;
    300  }
    301 
    302  struct None {};
    303  struct Play {};
    304  struct Pause {
    305    Pause() = delete;
    306    explicit Pause(uint64_t timestamp) : timestamp(timestamp) {}
    307    uint64_t timestamp; // The time when stopping stream.
    308  };
    309  struct Resume {
    310    Resume() = delete;
    311    explicit Resume(uint64_t time) : pause_time(time) {}
    312    uint64_t pause_time; // Elapsed time from stopping to starting stream.
    313  };
    314  std::variant<None, Play, Pause, Resume> state;
    315  // Track input callback timestamp to detect callback emission.
    316  uint64_t callback_timestamp{0};
    317  // Track number of written frames to adjust position after reinitialization.
    318  uint64_t init_position{0};
    319 };
    320 
    321 struct cubeb_stream {
    322  /* Note: Must match cubeb_stream layout in cubeb.c. */
    323  cubeb * context{};
    324  void * user_ptr{};
    325 
    326  std::atomic<bool> in_use{false};
    327  std::atomic<bool> latency_metrics_available{false};
    328  std::atomic<int64_t> drain_target{-1};
    329  std::atomic<stream_state> state{stream_state::INIT};
    330  std::atomic<bool> in_data_callback{false};
    331  triple_buffer<AAudioTimingInfo> timing_info;
    332 
    333  AAudioStream * ostream{};
    334  AAudioStream * istream{};
    335  cubeb_data_callback data_callback{};
    336  cubeb_state_callback state_callback{};
    337  cubeb_resampler * resampler{};
    338 
    339  // mutex synchronizes access to the stream from the state thread
    340  // and user-called functions. Everything that is accessed in the
    341  // aaudio data (or error) callback is synchronized only via atomics.
    342  // This lock is acquired for the entirety of the reinitialization period, when
    343  // changing device.
    344  std::mutex mutex;
    345 
    346  std::vector<uint8_t> in_buf;
    347  unsigned in_frame_size{}; // size of one input frame
    348 
    349  unique_ptr<cubeb_stream_params> output_stream_params;
    350  unique_ptr<cubeb_stream_params> input_stream_params;
    351  uint32_t latency_frames{};
    352  cubeb_sample_format out_format{};
    353  uint32_t sample_rate{};
    354  std::atomic<float> volume{1.f};
    355  unsigned out_channels{};
    356  unsigned out_frame_size{};
    357  bool voice_input{};
    358  bool voice_output{};
    359  uint64_t previous_clock{};
    360  position_estimate pos_estimate;
    361 };
    362 
    363 struct cubeb {
    364  struct cubeb_ops const * ops{};
    365 
    366  struct {
    367    // The state thread: it waits for state changes and stops
    368    // drained streams.
    369    std::thread thread;
    370    std::thread notifier;
    371    std::mutex mutex;
    372    std::condition_variable cond;
    373    std::atomic<bool> join{false};
    374    std::atomic<bool> waiting{false};
    375  } state;
    376 
    377  // streams[i].in_use signals whether a stream is used
    378  struct cubeb_stream streams[MAX_STREAMS];
    379 };
    380 
    381 struct AutoInCallback {
    382  AutoInCallback(cubeb_stream * stm) : stm(stm)
    383  {
    384    stm->in_data_callback.store(true);
    385  }
    386  ~AutoInCallback() { stm->in_data_callback.store(false); }
    387  cubeb_stream * stm;
    388 };
    389 
    390 // Returns when aaudio_stream's state is equal to desired_state.
    391 // poll_frequency_ns is the duration that is slept in between asking for
    392 // state updates and getting the new state.
    393 // When waiting for a stream to stop, it is best to pick a value similar
    394 // to the callback time because STOPPED will happen after
    395 // draining.
    396 static int
    397 wait_for_state_change(AAudioStream * aaudio_stream,
    398                      aaudio_stream_state_t * desired_state,
    399                      int64_t poll_frequency_ns)
    400 {
    401  aaudio_stream_state_t new_state;
    402  do {
    403    // See the docs of aaudio getState/waitForStateChange for details,
    404    // why we are passing STATE_UNKNOWN.
    405    aaudio_result_t res = WRAP(AAudioStream_waitForStateChange)(
    406        aaudio_stream, AAUDIO_STREAM_STATE_UNKNOWN, &new_state,
    407        poll_frequency_ns);
    408    if (res != AAUDIO_OK) {
    409      LOG("AAudioStream_waitForStateChange: %s",
    410          WRAP(AAudio_convertResultToText)(res));
    411      return CUBEB_ERROR;
    412    }
    413  } while (*desired_state != AAUDIO_STREAM_STATE_UNINITIALIZED &&
    414           new_state != *desired_state);
    415 
    416  *desired_state = new_state;
    417 
    418  LOG("wait_for_state_change: current state now: %s",
    419      WRAP(AAudio_convertStreamStateToText)(new_state));
    420 
    421  return CUBEB_OK;
    422 }
    423 
    424 // Only allowed from state thread, while mutex on stm is locked
    425 static void
    426 shutdown_with_error(cubeb_stream * stm)
    427 {
    428  if (stm->istream) {
    429    WRAP(AAudioStream_requestStop)(stm->istream);
    430  }
    431  if (stm->ostream) {
    432    WRAP(AAudioStream_requestStop)(stm->ostream);
    433  }
    434 
    435  int64_t poll_frequency_ns = NS_PER_S * stm->out_frame_size / stm->sample_rate;
    436  int rv;
    437  if (stm->istream) {
    438    aaudio_stream_state_t state = AAUDIO_STREAM_STATE_STOPPED;
    439    rv = wait_for_state_change(stm->istream, &state, poll_frequency_ns);
    440    if (rv != CUBEB_OK) {
    441      LOG("Failure when waiting for stream change on the input side when "
    442          "shutting down in error");
    443      // Not much we can do, carry on
    444    }
    445  }
    446  if (stm->ostream) {
    447    aaudio_stream_state_t state = AAUDIO_STREAM_STATE_STOPPED;
    448    rv = wait_for_state_change(stm->ostream, &state, poll_frequency_ns);
    449    if (rv != CUBEB_OK) {
    450      LOG("Failure when waiting for stream change on the output side when "
    451          "shutting down in error");
    452      // Not much we can do, carry on
    453    }
    454  }
    455 
    456  assert(!stm->in_data_callback.load());
    457  stm->state_callback(stm, stm->user_ptr, CUBEB_STATE_ERROR);
    458  stm->state.store(stream_state::SHUTDOWN);
    459 }
    460 
    461 // Returns whether the given state is one in which we wait for
    462 // an asynchronous change
    463 static bool
    464 waiting_state(stream_state state)
    465 {
    466  switch (state) {
    467  case stream_state::DRAINING:
    468  case stream_state::STARTING:
    469  case stream_state::STOPPING:
    470    return true;
    471  default:
    472    return false;
    473  }
    474 }
    475 
    476 static void
    477 update_state(cubeb_stream * stm)
    478 {
    479  // Fast path for streams that don't wait for state change or are invalid
    480  enum stream_state old_state = stm->state.load();
    481  if (old_state == stream_state::INIT || old_state == stream_state::STARTED ||
    482      old_state == stream_state::STOPPED ||
    483      old_state == stream_state::SHUTDOWN) {
    484    return;
    485  }
    486 
    487  // Requeue a state update if stream is already locked.
    488  unique_lock lock(stm->mutex, std::try_to_lock);
    489  if (!lock.owns_lock()) {
    490    stm->context->state.waiting.store(true);
    491    stm->context->state.cond.notify_one();
    492    return;
    493  }
    494 
    495  // check again: if this is true now, the stream was destroyed or
    496  // changed between our fast path check and locking the mutex
    497  old_state = stm->state.load();
    498  if (old_state == stream_state::INIT || old_state == stream_state::STARTED ||
    499      old_state == stream_state::STOPPED ||
    500      old_state == stream_state::SHUTDOWN) {
    501    return;
    502  }
    503 
    504  // We compute the new state the stream has and then compare_exchange it
    505  // if it has changed. This way we will never just overwrite state
    506  // changes that were set from the audio thread in the meantime,
    507  // such as a DRAINING or error state.
    508  enum stream_state new_state;
    509  do {
    510    if (old_state == stream_state::SHUTDOWN) {
    511      return;
    512    }
    513 
    514    if (old_state == stream_state::ERROR) {
    515      shutdown_with_error(stm);
    516      return;
    517    }
    518 
    519    new_state = old_state;
    520 
    521    aaudio_stream_state_t istate = AAUDIO_STREAM_STATE_UNINITIALIZED;
    522    aaudio_stream_state_t ostate = AAUDIO_STREAM_STATE_UNINITIALIZED;
    523 
    524    // We use waitForStateChange (with zero timeout) instead of just
    525    // getState since only the former internally updates the state.
    526    if (stm->istream) {
    527      int res = wait_for_state_change(stm->istream, &istate, 0);
    528      if (res != CUBEB_OK) {
    529        return;
    530      }
    531      assert(istate);
    532    }
    533 
    534    if (stm->ostream) {
    535      int res = wait_for_state_change(stm->ostream, &ostate, 0);
    536      if (res != CUBEB_OK) {
    537        return;
    538      }
    539      assert(ostate);
    540    }
    541 
    542    // handle invalid stream states
    543    if (istate == AAUDIO_STREAM_STATE_FLUSHING ||
    544        istate == AAUDIO_STREAM_STATE_FLUSHED ||
    545        istate == AAUDIO_STREAM_STATE_UNKNOWN ||
    546        istate == AAUDIO_STREAM_STATE_DISCONNECTED) {
    547      LOG("Unexpected android input stream state %s",
    548          WRAP(AAudio_convertStreamStateToText)(istate));
    549      shutdown_with_error(stm);
    550      return;
    551    }
    552 
    553    if (ostate == AAUDIO_STREAM_STATE_FLUSHING ||
    554        ostate == AAUDIO_STREAM_STATE_FLUSHED ||
    555        ostate == AAUDIO_STREAM_STATE_UNKNOWN ||
    556        ostate == AAUDIO_STREAM_STATE_DISCONNECTED) {
    557      LOG("Unexpected android output stream state %s",
    558          WRAP(AAudio_convertStreamStateToText)(ostate));
    559      shutdown_with_error(stm);
    560      return;
    561    }
    562 
    563    switch (old_state) {
    564    case stream_state::STARTING:
    565      if ((!istate || istate == AAUDIO_STREAM_STATE_STARTED) &&
    566          (!ostate || ostate == AAUDIO_STREAM_STATE_STARTED)) {
    567        stm->state_callback(stm, stm->user_ptr, CUBEB_STATE_STARTED);
    568        new_state = stream_state::STARTED;
    569      }
    570      break;
    571    case stream_state::DRAINING:
    572      // The DRAINING state means that we want to stop the streams but
    573      // may not have done so yet.
    574      if (ostate && ostate == AAUDIO_STREAM_STATE_STARTED) {
    575        int64_t read = WRAP(AAudioStream_getFramesRead)(stm->ostream);
    576        int64_t target = stm->drain_target.load();
    577        LOGV("Output stream DRAINING. Remaining frames: %" PRId64 ".",
    578             target - read);
    579        if (read < target) {
    580          // requestStop says it will wait for buffered data to be drained.
    581          // We have observed the end of the stream's written data getting
    582          // truncated however, suggesting there is some buffer that it does
    583          // not drain. Wait for all written frames to have been read before
    584          // draining.
    585          return;
    586        }
    587      }
    588      // The aaudio docs state that returning STOP from the callback isn't
    589      // enough, the stream has to be stopped from another thread
    590      // afterwards.
    591      // No callbacks are triggered anymore when requestStop returns.
    592      // That is important as we otherwise might read from a closed istream
    593      // for a duplex stream.
    594      // Therefor it is important to close ostream first.
    595      if (ostate && ostate != AAUDIO_STREAM_STATE_STOPPING &&
    596          ostate != AAUDIO_STREAM_STATE_STOPPED) {
    597        LOGV("Output stream DRAINING. Stopping.");
    598        aaudio_result_t res = WRAP(AAudioStream_requestStop)(stm->ostream);
    599        if (res != AAUDIO_OK) {
    600          LOG("AAudioStream_requestStop: %s",
    601              WRAP(AAudio_convertResultToText)(res));
    602          return;
    603        }
    604      }
    605      if (istate && istate != AAUDIO_STREAM_STATE_STOPPING &&
    606          istate != AAUDIO_STREAM_STATE_STOPPED) {
    607        LOGV("Input stream DRAINING. Stopping");
    608        aaudio_result_t res = WRAP(AAudioStream_requestStop)(stm->istream);
    609        if (res != AAUDIO_OK) {
    610          LOG("AAudioStream_requestStop: %s",
    611              WRAP(AAudio_convertResultToText)(res));
    612          return;
    613        }
    614      }
    615 
    616      // we always wait until both streams are stopped until we
    617      // send CUBEB_STATE_DRAINED. Then we can directly transition
    618      // our logical state to STOPPED, not triggering
    619      // an additional CUBEB_STATE_STOPPED callback (which might
    620      // be unexpected for the user).
    621      if ((!ostate || ostate == AAUDIO_STREAM_STATE_STOPPED) &&
    622          (!istate || istate == AAUDIO_STREAM_STATE_STOPPED)) {
    623        new_state = stream_state::STOPPED;
    624        stm->drain_target.store(-1);
    625        stm->state_callback(stm, stm->user_ptr, CUBEB_STATE_DRAINED);
    626      }
    627      break;
    628    case stream_state::STOPPING:
    629      // If stream_stop happens while the stream is still starting, we may see
    630      // STARTING/STARTED, ignore these and handle STATE_STOPPED once we reach
    631      // PAUSED.
    632      assert(!istate || istate == AAUDIO_STREAM_STATE_STARTING ||
    633             istate == AAUDIO_STREAM_STATE_STARTED ||
    634             istate == AAUDIO_STREAM_STATE_PAUSING ||
    635             istate == AAUDIO_STREAM_STATE_PAUSED);
    636      assert(!ostate || ostate == AAUDIO_STREAM_STATE_STARTING ||
    637             ostate == AAUDIO_STREAM_STATE_STARTED ||
    638             ostate == AAUDIO_STREAM_STATE_PAUSING ||
    639             ostate == AAUDIO_STREAM_STATE_PAUSED);
    640      if ((!istate || istate == AAUDIO_STREAM_STATE_PAUSED) &&
    641          (!ostate || ostate == AAUDIO_STREAM_STATE_PAUSED)) {
    642        stm->state_callback(stm, stm->user_ptr, CUBEB_STATE_STOPPED);
    643        new_state = stream_state::STOPPED;
    644      }
    645      break;
    646    default:
    647      assert(false && "Unreachable: invalid state");
    648    }
    649  } while (old_state != new_state &&
    650           !stm->state.compare_exchange_strong(old_state, new_state));
    651 }
    652 
    653 // See https://nyorain.github.io/lock-free-wakeup.html for a note
    654 // why this is needed. The audio thread notifies the state thread about
    655 // state changes and must not block. The state thread on the other hand should
    656 // sleep until there is work to be done. So we need a lockfree producer
    657 // and blocking producer. This can only be achieved safely with a new thread
    658 // that only serves as notifier backup (in case the notification happens
    659 // right between the state thread checking and going to sleep in which case
    660 // this thread will kick in and signal it right again).
    661 static void
    662 notifier_thread(cubeb * ctx)
    663 {
    664  unique_lock lock(ctx->state.mutex);
    665 
    666  while (!ctx->state.join.load()) {
    667    ctx->state.cond.wait(lock);
    668    if (ctx->state.waiting.load()) {
    669      // This must signal our state thread since there is no other
    670      // thread currently waiting on the condition variable.
    671      // The state change thread is guaranteed to be waiting since
    672      // we hold the mutex it locks when awake.
    673      ctx->state.cond.notify_one();
    674    }
    675  }
    676 
    677  // make sure other thread joins as well
    678  ctx->state.cond.notify_one();
    679  LOG("Exiting notifier thread");
    680 }
    681 
    682 static void
    683 state_thread(cubeb * ctx)
    684 {
    685  unique_lock lock(ctx->state.mutex);
    686 
    687  bool waiting = false;
    688  while (!ctx->state.join.load()) {
    689    waiting |= ctx->state.waiting.load();
    690    if (waiting) {
    691      ctx->state.waiting.store(false);
    692      waiting = false;
    693      for (auto & stream : ctx->streams) {
    694        cubeb_stream * stm = &stream;
    695        update_state(stm);
    696        waiting |= waiting_state(atomic_load(&stm->state));
    697      }
    698 
    699      // state changed from another thread, update again immediately
    700      if (ctx->state.waiting.load()) {
    701        waiting = true;
    702        continue;
    703      }
    704 
    705      // Not waiting for any change anymore: we can wait on the
    706      // condition variable without timeout
    707      if (!waiting) {
    708        continue;
    709      }
    710 
    711      // while any stream is waiting for state change we sleep with regular
    712      // timeouts. But we wake up immediately if signaled.
    713      // This might seem like a poor man's implementation of state change
    714      // waiting but (as of october 2020), the implementation of
    715      // AAudioStream_waitForStateChange is just sleeping with regular
    716      // timeouts as well:
    717      // https://android.googlesource.com/platform/frameworks/av/+/refs/heads/master/media/libaaudio/src/core/AudioStream.cpp
    718      auto dur = std::chrono::milliseconds(5);
    719      ctx->state.cond.wait_for(lock, dur);
    720    } else {
    721      ctx->state.cond.wait(lock);
    722    }
    723  }
    724 
    725  // make sure other thread joins as well
    726  ctx->state.cond.notify_one();
    727  LOG("Exiting state thread");
    728 }
    729 
    730 static char const *
    731 aaudio_get_backend_id(cubeb * /* ctx */)
    732 {
    733  return "aaudio";
    734 }
    735 
    736 static int
    737 aaudio_get_max_channel_count(cubeb * ctx, uint32_t * max_channels)
    738 {
    739  assert(ctx && max_channels);
    740  // NOTE: we might get more, AAudio docs don't specify anything.
    741  *max_channels = 2;
    742  return CUBEB_OK;
    743 }
    744 
    745 static void
    746 aaudio_destroy(cubeb * ctx)
    747 {
    748  assert(ctx);
    749 
    750 #ifndef NDEBUG
    751  // make sure all streams were destroyed
    752  for (auto & stream : ctx->streams) {
    753    assert(!stream.in_use.load());
    754  }
    755 #endif
    756 
    757  // broadcast joining to both threads
    758  // they will additionally signal each other before joining
    759  ctx->state.join.store(true);
    760  ctx->state.cond.notify_all();
    761 
    762  if (ctx->state.thread.joinable()) {
    763    ctx->state.thread.join();
    764  }
    765  if (ctx->state.notifier.joinable()) {
    766    ctx->state.notifier.join();
    767  }
    768  delete ctx;
    769 }
    770 
    771 static void
    772 apply_volume(cubeb_stream * stm, void * audio_data, uint32_t num_frames)
    773 {
    774  float volume = stm->volume.load();
    775  // optimization: we don't have to change anything in this case
    776  if (volume == 1.f) {
    777    return;
    778  }
    779 
    780  switch (stm->out_format) {
    781  case CUBEB_SAMPLE_S16NE: {
    782    int16_t * integer_data = static_cast<int16_t *>(audio_data);
    783    for (uint32_t i = 0u; i < num_frames * stm->out_channels; ++i) {
    784      integer_data[i] =
    785          static_cast<int16_t>(static_cast<float>(integer_data[i]) * volume);
    786    }
    787    break;
    788  }
    789  case CUBEB_SAMPLE_FLOAT32NE:
    790    for (uint32_t i = 0u; i < num_frames * stm->out_channels; ++i) {
    791      (static_cast<float *>(audio_data))[i] *= volume;
    792    }
    793    break;
    794  default:
    795    assert(false && "Unreachable: invalid stream out_format");
    796  }
    797 }
    798 
    799 uint64_t
    800 now_ns()
    801 {
    802  using namespace std::chrono;
    803  return duration_cast<nanoseconds>(steady_clock::now().time_since_epoch())
    804      .count();
    805 }
    806 
    807 // To be called from the real-time audio callback
    808 uint64_t
    809 aaudio_get_latency(cubeb_stream * stm, aaudio_direction_t direction,
    810                   uint64_t tstamp_ns)
    811 {
    812  bool is_output = direction == AAUDIO_DIRECTION_OUTPUT;
    813  int64_t hw_frame_index;
    814  int64_t hw_tstamp;
    815  AAudioStream * stream = is_output ? stm->ostream : stm->istream;
    816  // For an output stream (resp. input stream), get the number of frames
    817  // written to (resp read from) the hardware.
    818  int64_t app_frame_index = is_output
    819                                ? WRAP(AAudioStream_getFramesWritten)(stream)
    820                                : WRAP(AAudioStream_getFramesRead)(stream);
    821 
    822  assert(tstamp_ns < std::numeric_limits<uint64_t>::max());
    823  int64_t signed_tstamp_ns = static_cast<int64_t>(tstamp_ns);
    824 
    825  // Get a timestamp for a particular frame index written to or read from the
    826  // hardware.
    827  auto result = WRAP(AAudioStream_getTimestamp)(stream, CLOCK_MONOTONIC,
    828                                                &hw_frame_index, &hw_tstamp);
    829  if (result != AAUDIO_OK) {
    830    LOG("AAudioStream_getTimestamp failure for %s: %s",
    831        is_output ? "output" : "input",
    832        WRAP(AAudio_convertResultToText)(result));
    833    return 0;
    834  }
    835 
    836  // Compute the difference between the app and the hardware indices.
    837  int64_t frame_index_delta = app_frame_index - hw_frame_index;
    838  // Convert to ns
    839  int64_t frame_time_delta = (frame_index_delta * NS_PER_S) / stm->sample_rate;
    840  // Extrapolate from the known timestamp for a particular frame presented.
    841  int64_t app_frame_hw_time = hw_tstamp + frame_time_delta;
    842  // For an output stream, the latency is positive, for an input stream, it's
    843  // negative. It can happen in some instances, e.g. around start of the stream
    844  // that the latency for output is negative, return 0 in this case.
    845  int64_t latency_ns = is_output
    846                           ? std::max(static_cast<int64_t>(0),
    847                                      app_frame_hw_time - signed_tstamp_ns)
    848                           : signed_tstamp_ns - app_frame_hw_time;
    849  int64_t latency_frames = stm->sample_rate * latency_ns / NS_PER_S;
    850 
    851  LOGV("Latency in frames (%s): %ld (%fms)", is_output ? "output" : "input",
    852       latency_frames, latency_ns / 1e6);
    853 
    854  return latency_frames;
    855 }
    856 
    857 void
    858 compute_and_report_latency_metrics(cubeb_stream * stm)
    859 {
    860  AAudioTimingInfo info = {};
    861 
    862  info.tstamp = now_ns();
    863 
    864  if (stm->ostream) {
    865    uint64_t latency_frames =
    866        aaudio_get_latency(stm, AAUDIO_DIRECTION_OUTPUT, info.tstamp);
    867    if (latency_frames) {
    868      info.output_latency = latency_frames;
    869      info.output_frame_index =
    870          WRAP(AAudioStream_getFramesWritten)(stm->ostream);
    871    }
    872  }
    873  if (stm->istream) {
    874    uint64_t latency_frames =
    875        aaudio_get_latency(stm, AAUDIO_DIRECTION_INPUT, info.tstamp);
    876    if (latency_frames) {
    877      info.input_latency = latency_frames;
    878    }
    879  }
    880 
    881  if (info.output_latency || info.input_latency) {
    882    stm->latency_metrics_available = true;
    883    stm->timing_info.write(info);
    884  }
    885 }
    886 
    887 // Returning AAUDIO_CALLBACK_RESULT_STOP seems to put the stream in
    888 // an invalid state. Seems like an AAudio bug/bad documentation.
    889 // We therefore only return it on error.
    890 
    891 static aaudio_data_callback_result_t
    892 aaudio_duplex_data_cb(AAudioStream * astream, void * user_data,
    893                      void * audio_data, int32_t num_frames)
    894 {
    895  cubeb_stream * stm = (cubeb_stream *)user_data;
    896  AutoInCallback aic(stm);
    897  assert(stm->ostream == astream);
    898  assert(stm->istream);
    899  assert(num_frames >= 0);
    900 
    901  stream_state state = atomic_load(&stm->state);
    902  int istate = WRAP(AAudioStream_getState)(stm->istream);
    903  int ostate = WRAP(AAudioStream_getState)(stm->ostream);
    904 
    905  // all other states may happen since the callback might be called
    906  // from within requestStart
    907  assert(state != stream_state::SHUTDOWN);
    908 
    909  // This might happen when we started draining but not yet actually
    910  // stopped the stream from the state thread.
    911  if (state == stream_state::DRAINING) {
    912    LOG("Draining in duplex callback");
    913    std::memset(audio_data, 0x0, num_frames * stm->out_frame_size);
    914    return AAUDIO_CALLBACK_RESULT_CONTINUE;
    915  }
    916 
    917  if (num_frames * stm->in_frame_size > stm->in_buf.size()) {
    918    LOG("Resizing input buffer in duplex callback");
    919    stm->in_buf.resize(num_frames * stm->in_frame_size);
    920  }
    921  // The aaudio docs state that AAudioStream_read must not be called on
    922  // the stream associated with a callback. But we call it on the input stream
    923  // while this callback is for the output stream so this is ok.
    924  // We also pass timeout 0, giving us strong non-blocking guarantees.
    925  // This is exactly how it's done in the aaudio duplex example code snippet.
    926  long in_num_frames =
    927      WRAP(AAudioStream_read)(stm->istream, stm->in_buf.data(), num_frames, 0);
    928  if (in_num_frames < 0) { // error
    929    if (in_num_frames == AAUDIO_ERROR_DISCONNECTED) {
    930      LOG("AAudioStream_read: %s (reinitializing)",
    931          WRAP(AAudio_convertResultToText)(in_num_frames));
    932      reinitialize_stream(stm);
    933    } else {
    934      stm->state.store(stream_state::ERROR);
    935      stm->context->state.waiting.store(true);
    936      stm->context->state.cond.notify_one();
    937    }
    938    LOG("AAudioStream_read: %s",
    939        WRAP(AAudio_convertResultToText)(in_num_frames));
    940    return AAUDIO_CALLBACK_RESULT_STOP;
    941  }
    942 
    943  ALOGV("aaudio duplex data cb on stream %p: state %ld (in: %d, out: %d), "
    944        "num_frames: %d, read: %ld",
    945        (void *)stm, state, istate, ostate, num_frames, in_num_frames);
    946 
    947  compute_and_report_latency_metrics(stm);
    948 
    949  // This can happen shortly after starting the stream. AAudio might immediately
    950  // begin to buffer output but not have any input ready yet. We could
    951  // block AAudioStream_read (passing a timeout > 0) but that leads to issues
    952  // since blocking in this callback is a bad idea in general and it might break
    953  // the stream when it is stopped by another thread shortly after being
    954  // started. We therefore simply send silent input to the application, as shown
    955  // in the AAudio duplex stream code example.
    956  if (in_num_frames < num_frames) {
    957    // LOG("AAudioStream_read returned not enough frames: %ld instead of %d",
    958    //   in_num_frames, num_frames);
    959    unsigned left = num_frames - in_num_frames;
    960    uint8_t * buf = stm->in_buf.data() + in_num_frames * stm->in_frame_size;
    961    std::memset(buf, 0x0, left * stm->in_frame_size);
    962    in_num_frames = num_frames;
    963  }
    964 
    965  long done_frames =
    966      cubeb_resampler_fill(stm->resampler, stm->in_buf.data(), &in_num_frames,
    967                           audio_data, num_frames);
    968 
    969  if (done_frames < 0 || done_frames > num_frames) {
    970    LOG("Error in data callback or resampler: %ld", done_frames);
    971    stm->state.store(stream_state::ERROR);
    972    stm->context->state.waiting.store(true);
    973    stm->context->state.cond.notify_one();
    974    return AAUDIO_CALLBACK_RESULT_STOP;
    975  }
    976  if (done_frames < num_frames) {
    977    stm->drain_target.store(WRAP(AAudioStream_getFramesWritten)(stm->ostream) +
    978                            done_frames);
    979    stm->state.store(stream_state::DRAINING);
    980    stm->context->state.waiting.store(true);
    981    stm->context->state.cond.notify_one();
    982 
    983    char * begin =
    984        static_cast<char *>(audio_data) + done_frames * stm->out_frame_size;
    985    std::memset(begin, 0x0, (num_frames - done_frames) * stm->out_frame_size);
    986  }
    987 
    988  apply_volume(stm, audio_data, done_frames);
    989  return AAUDIO_CALLBACK_RESULT_CONTINUE;
    990 }
    991 
    992 static aaudio_data_callback_result_t
    993 aaudio_output_data_cb(AAudioStream * astream, void * user_data,
    994                      void * audio_data, int32_t num_frames)
    995 {
    996  cubeb_stream * stm = (cubeb_stream *)user_data;
    997  AutoInCallback aic(stm);
    998  assert(stm->ostream == astream);
    999  assert(!stm->istream);
   1000  assert(num_frames >= 0);
   1001 
   1002  stream_state state = stm->state.load();
   1003  int ostate = WRAP(AAudioStream_getState)(stm->ostream);
   1004  ALOGV("aaudio output data cb on stream %p: state %ld (%d), num_frames: %d",
   1005        stm, state, ostate, num_frames);
   1006 
   1007  // all other states may happen since the callback might be called
   1008  // from within requestStart
   1009  assert(state != stream_state::SHUTDOWN);
   1010 
   1011  // This might happen when we started draining but not yet actually
   1012  // stopped the stream from the state thread.
   1013  if (state == stream_state::DRAINING) {
   1014    std::memset(audio_data, 0x0, num_frames * stm->out_frame_size);
   1015    return AAUDIO_CALLBACK_RESULT_CONTINUE;
   1016  }
   1017 
   1018  compute_and_report_latency_metrics(stm);
   1019 
   1020  long done_frames = cubeb_resampler_fill(stm->resampler, nullptr, nullptr,
   1021                                          audio_data, num_frames);
   1022  if (done_frames < 0 || done_frames > num_frames) {
   1023    LOG("Error in data callback or resampler: %ld", done_frames);
   1024    stm->state.store(stream_state::ERROR);
   1025    stm->context->state.waiting.store(true);
   1026    stm->context->state.cond.notify_one();
   1027    return AAUDIO_CALLBACK_RESULT_STOP;
   1028  }
   1029 
   1030  if (done_frames < num_frames) {
   1031    stm->drain_target.store(WRAP(AAudioStream_getFramesWritten)(stm->ostream) +
   1032                            done_frames);
   1033    stm->state.store(stream_state::DRAINING);
   1034    stm->context->state.waiting.store(true);
   1035    stm->context->state.cond.notify_one();
   1036 
   1037    char * begin =
   1038        static_cast<char *>(audio_data) + done_frames * stm->out_frame_size;
   1039    std::memset(begin, 0x0, (num_frames - done_frames) * stm->out_frame_size);
   1040  }
   1041 
   1042  apply_volume(stm, audio_data, done_frames);
   1043  return AAUDIO_CALLBACK_RESULT_CONTINUE;
   1044 }
   1045 
   1046 static aaudio_data_callback_result_t
   1047 aaudio_input_data_cb(AAudioStream * astream, void * user_data,
   1048                     void * audio_data, int32_t num_frames)
   1049 {
   1050  cubeb_stream * stm = (cubeb_stream *)user_data;
   1051  AutoInCallback aic(stm);
   1052  assert(stm->istream == astream);
   1053  assert(!stm->ostream);
   1054  assert(num_frames >= 0);
   1055 
   1056  stream_state state = stm->state.load();
   1057  int istate = WRAP(AAudioStream_getState)(stm->istream);
   1058  ALOGV("aaudio input data cb on stream %p: state %ld (%d), num_frames: %d",
   1059        stm, state, istate, num_frames);
   1060 
   1061  // all other states may happen since the callback might be called
   1062  // from within requestStart
   1063  assert(state != stream_state::SHUTDOWN);
   1064 
   1065  // This might happen when we started draining but not yet actually
   1066  // STOPPED the stream from the state thread.
   1067  if (state == stream_state::DRAINING) {
   1068    return AAUDIO_CALLBACK_RESULT_CONTINUE;
   1069  }
   1070 
   1071  compute_and_report_latency_metrics(stm);
   1072 
   1073  long input_frame_count = num_frames;
   1074  long done_frames = cubeb_resampler_fill(stm->resampler, audio_data,
   1075                                          &input_frame_count, nullptr, 0);
   1076 
   1077  if (done_frames < 0 || done_frames > num_frames) {
   1078    LOG("Error in data callback or resampler: %ld", done_frames);
   1079    stm->state.store(stream_state::ERROR);
   1080    stm->context->state.waiting.store(true);
   1081    stm->context->state.cond.notify_one();
   1082    return AAUDIO_CALLBACK_RESULT_STOP;
   1083  }
   1084 
   1085  if (done_frames < input_frame_count) {
   1086    // we don't really drain an input stream, just have to
   1087    // stop it from the state thread. That is signaled via the
   1088    // DRAINING state.
   1089    stm->state.store(stream_state::DRAINING);
   1090    stm->context->state.waiting.store(true);
   1091    stm->context->state.cond.notify_one();
   1092  }
   1093 
   1094  return AAUDIO_CALLBACK_RESULT_CONTINUE;
   1095 }
   1096 
   1097 static void
   1098 reinitialize_stream(cubeb_stream * stm)
   1099 {
   1100  // This cannot be done from within the error callback, bounce to another
   1101  // thread.
   1102  // In this situation, the lock is acquired for the entire duration of the
   1103  // function, so that this reinitialization period is atomic.
   1104  std::thread([stm] {
   1105    lock_guard lock(stm->mutex);
   1106    stream_state state = stm->state.load();
   1107    bool was_playing = state == stream_state::STARTED ||
   1108                       state == stream_state::STARTING ||
   1109                       state == stream_state::DRAINING;
   1110    int err = aaudio_stream_stop_locked(stm, lock);
   1111    // Error ignored.
   1112 
   1113    // Get total number of written frames before destroying the stream.
   1114    uint64_t total_frames = stm->pos_estimate.initial_position();
   1115    if (stm->ostream) {
   1116      // For output-only and duplex, use the output stream.
   1117      total_frames += WRAP(AAudioStream_getFramesWritten)(stm->ostream);
   1118    } else if (stm->istream) {
   1119      // Input-only, we can only use the input stream.
   1120      total_frames += WRAP(AAudioStream_getFramesWritten)(stm->istream);
   1121    }
   1122 
   1123    aaudio_stream_destroy_locked(stm, lock);
   1124    err = aaudio_stream_init_impl(stm, lock);
   1125 
   1126    assert(stm->in_use.load());
   1127 
   1128    // Set the new initial position.
   1129    stm->pos_estimate.reinit(total_frames);
   1130 
   1131    if (err != CUBEB_OK) {
   1132      aaudio_stream_destroy_locked(stm, lock);
   1133      LOG("aaudio_stream_init_impl error while reiniting: %s",
   1134          WRAP(AAudio_convertResultToText)(err));
   1135      stm->state.store(stream_state::ERROR);
   1136      stm->context->state.waiting.store(true);
   1137      stm->context->state.cond.notify_one();
   1138      return;
   1139    }
   1140 
   1141    if (was_playing) {
   1142      err = aaudio_stream_start_locked(stm, lock);
   1143      stm->drain_target.store(-1);
   1144      if (err != CUBEB_OK) {
   1145        aaudio_stream_destroy_locked(stm, lock);
   1146        LOG("aaudio_stream_start error while reiniting: %s",
   1147            WRAP(AAudio_convertResultToText)(err));
   1148        stm->state.store(stream_state::ERROR);
   1149        stm->context->state.waiting.store(true);
   1150        stm->context->state.cond.notify_one();
   1151        return;
   1152      }
   1153    }
   1154  }).detach();
   1155 }
   1156 
   1157 static void
   1158 aaudio_error_cb(AAudioStream * astream, void * user_data, aaudio_result_t error)
   1159 {
   1160  cubeb_stream * stm = static_cast<cubeb_stream *>(user_data);
   1161  assert(stm->ostream == astream || stm->istream == astream);
   1162 
   1163  // Device change -- reinitialize on the new default device.
   1164  if (error == AAUDIO_ERROR_DISCONNECTED || error == AAUDIO_ERROR_TIMEOUT) {
   1165    LOG("Audio device change, reinitializing stream");
   1166    reinitialize_stream(stm);
   1167    return;
   1168  }
   1169 
   1170  LOG("AAudio error callback: %s", WRAP(AAudio_convertResultToText)(error));
   1171  stm->state.store(stream_state::ERROR);
   1172  stm->context->state.waiting.store(true);
   1173  stm->context->state.cond.notify_one();
   1174 }
   1175 
   1176 static int
   1177 realize_stream(AAudioStreamBuilder * sb, const cubeb_stream_params * params,
   1178               AAudioStream ** stream, unsigned * frame_size)
   1179 {
   1180  aaudio_result_t res;
   1181  assert(params->rate);
   1182  assert(params->channels);
   1183 
   1184  WRAP(AAudioStreamBuilder_setSampleRate)
   1185  (sb, static_cast<int32_t>(params->rate));
   1186  WRAP(AAudioStreamBuilder_setChannelCount)
   1187  (sb, static_cast<int32_t>(params->channels));
   1188 
   1189  aaudio_format_t fmt;
   1190  switch (params->format) {
   1191  case CUBEB_SAMPLE_S16NE:
   1192    fmt = AAUDIO_FORMAT_PCM_I16;
   1193    *frame_size = sizeof(int16_t) * params->channels;
   1194    break;
   1195  case CUBEB_SAMPLE_FLOAT32NE:
   1196    fmt = AAUDIO_FORMAT_PCM_FLOAT;
   1197    *frame_size = sizeof(float) * params->channels;
   1198    break;
   1199  default:
   1200    return CUBEB_ERROR_INVALID_FORMAT;
   1201  }
   1202 
   1203  WRAP(AAudioStreamBuilder_setFormat)(sb, fmt);
   1204  res = WRAP(AAudioStreamBuilder_openStream)(sb, stream);
   1205  if (res == AAUDIO_ERROR_INVALID_FORMAT) {
   1206    LOG("AAudio device doesn't support output format %d", fmt);
   1207    return CUBEB_ERROR_INVALID_FORMAT;
   1208  }
   1209 
   1210  if (params->rate && res == AAUDIO_ERROR_INVALID_RATE) {
   1211    // The requested rate is not supported.
   1212    // Just try again with default rate, we create a resampler anyways
   1213    WRAP(AAudioStreamBuilder_setSampleRate)(sb, AAUDIO_UNSPECIFIED);
   1214    res = WRAP(AAudioStreamBuilder_openStream)(sb, stream);
   1215    LOG("Requested rate of %u is not supported, inserting resampler",
   1216        params->rate);
   1217  }
   1218 
   1219  // When the app has no permission to record audio
   1220  // (android.permission.RECORD_AUDIO) but requested and input stream, this will
   1221  // return INVALID_ARGUMENT.
   1222  if (res != AAUDIO_OK) {
   1223    LOG("AAudioStreamBuilder_openStream: %s",
   1224        WRAP(AAudio_convertResultToText)(res));
   1225    return CUBEB_ERROR;
   1226  }
   1227 
   1228  return CUBEB_OK;
   1229 }
   1230 
   1231 static void
   1232 aaudio_stream_destroy(cubeb_stream * stm)
   1233 {
   1234  lock_guard lock(stm->mutex);
   1235  stm->in_use.store(false);
   1236  aaudio_stream_destroy_locked(stm, lock);
   1237 }
   1238 
   1239 static void
   1240 aaudio_stream_destroy_locked(cubeb_stream * stm, lock_guard<mutex> & lock)
   1241 {
   1242  assert(stm->state == stream_state::STOPPED ||
   1243         stm->state == stream_state::STOPPING ||
   1244         stm->state == stream_state::INIT ||
   1245         stm->state == stream_state::DRAINING ||
   1246         stm->state == stream_state::ERROR ||
   1247         stm->state == stream_state::SHUTDOWN);
   1248 
   1249  aaudio_result_t res;
   1250 
   1251  // No callbacks are triggered anymore when requestStop returns.
   1252  // That is important as we otherwise might read from a closed istream
   1253  // for a duplex stream.
   1254  if (stm->ostream) {
   1255    if (stm->state != stream_state::STOPPED &&
   1256        stm->state != stream_state::STOPPING &&
   1257        stm->state != stream_state::SHUTDOWN) {
   1258      res = WRAP(AAudioStream_requestStop)(stm->ostream);
   1259      if (res != AAUDIO_OK) {
   1260        LOG("AAudioStreamBuilder_requestStop: %s",
   1261            WRAP(AAudio_convertResultToText)(res));
   1262      }
   1263    }
   1264 
   1265    WRAP(AAudioStream_close)(stm->ostream);
   1266    stm->ostream = nullptr;
   1267  }
   1268 
   1269  if (stm->istream) {
   1270    if (stm->state != stream_state::STOPPED &&
   1271        stm->state != stream_state::STOPPING &&
   1272        stm->state != stream_state::SHUTDOWN) {
   1273      res = WRAP(AAudioStream_requestStop)(stm->istream);
   1274      if (res != AAUDIO_OK) {
   1275        LOG("AAudioStreamBuilder_requestStop: %s",
   1276            WRAP(AAudio_convertResultToText)(res));
   1277      }
   1278    }
   1279 
   1280    WRAP(AAudioStream_close)(stm->istream);
   1281    stm->istream = nullptr;
   1282  }
   1283 
   1284  stm->timing_info.invalidate();
   1285  stm->previous_clock = 0;
   1286  stm->pos_estimate = {};
   1287 
   1288  if (stm->resampler) {
   1289    cubeb_resampler_destroy(stm->resampler);
   1290    stm->resampler = nullptr;
   1291  }
   1292 
   1293  stm->in_buf = {};
   1294  stm->in_frame_size = {};
   1295  stm->out_format = {};
   1296  stm->out_channels = {};
   1297  stm->out_frame_size = {};
   1298 
   1299  stm->state.store(stream_state::INIT);
   1300 }
   1301 
   1302 static int
   1303 aaudio_stream_init_impl(cubeb_stream * stm, lock_guard<mutex> & lock)
   1304 {
   1305  assert(stm->state.load() == stream_state::INIT);
   1306 
   1307  cubeb_async_log_reset_threads();
   1308 
   1309  aaudio_result_t res;
   1310  AAudioStreamBuilder * sb;
   1311  res = WRAP(AAudio_createStreamBuilder)(&sb);
   1312  if (res != AAUDIO_OK) {
   1313    LOG("AAudio_createStreamBuilder: %s",
   1314        WRAP(AAudio_convertResultToText)(res));
   1315    return CUBEB_ERROR;
   1316  }
   1317 
   1318  // make sure the builder is always destroyed
   1319  struct StreamBuilderDestructor {
   1320    void operator()(AAudioStreamBuilder * sb)
   1321    {
   1322      WRAP(AAudioStreamBuilder_delete)(sb);
   1323    }
   1324  };
   1325 
   1326  std::unique_ptr<AAudioStreamBuilder, StreamBuilderDestructor> sbPtr(sb);
   1327 
   1328  WRAP(AAudioStreamBuilder_setErrorCallback)(sb, aaudio_error_cb, stm);
   1329  // Capacity should be at least twice the frames-per-callback to allow double
   1330  // buffering.
   1331  WRAP(AAudioStreamBuilder_setBufferCapacityInFrames)
   1332  (sb, static_cast<int32_t>(2 * stm->latency_frames));
   1333 
   1334  AAudioStream_dataCallback in_data_callback{};
   1335  AAudioStream_dataCallback out_data_callback{};
   1336  if (stm->output_stream_params && stm->input_stream_params) {
   1337    out_data_callback = aaudio_duplex_data_cb;
   1338    in_data_callback = nullptr;
   1339  } else if (stm->input_stream_params) {
   1340    in_data_callback = aaudio_input_data_cb;
   1341  } else if (stm->output_stream_params) {
   1342    out_data_callback = aaudio_output_data_cb;
   1343  } else {
   1344    LOG("Tried to open stream without input or output parameters");
   1345    return CUBEB_ERROR;
   1346  }
   1347 
   1348 #ifdef CUBEB_AAUDIO_EXCLUSIVE_STREAM
   1349  LOG("AAudio setting exclusive share mode for stream");
   1350  WRAP(AAudioStreamBuilder_setSharingMode)(sb, AAUDIO_SHARING_MODE_EXCLUSIVE);
   1351 #endif
   1352 
   1353  if (stm->latency_frames <= POWERSAVE_LATENCY_FRAMES_THRESHOLD) {
   1354    LOG("AAudio setting low latency mode for stream");
   1355    WRAP(AAudioStreamBuilder_setPerformanceMode)
   1356    (sb, AAUDIO_PERFORMANCE_MODE_LOW_LATENCY);
   1357  } else {
   1358    LOG("AAudio setting power saving mode for stream");
   1359    WRAP(AAudioStreamBuilder_setPerformanceMode)
   1360    (sb, AAUDIO_PERFORMANCE_MODE_POWER_SAVING);
   1361  }
   1362 
   1363  unsigned frame_size;
   1364 
   1365  // initialize streams
   1366  // output
   1367  cubeb_stream_params out_params;
   1368  if (stm->output_stream_params) {
   1369    int output_preset = stm->voice_output ? AAUDIO_USAGE_VOICE_COMMUNICATION
   1370                                          : AAUDIO_USAGE_MEDIA;
   1371    WRAP(AAudioStreamBuilder_setUsage)(sb, output_preset);
   1372    WRAP(AAudioStreamBuilder_setDirection)(sb, AAUDIO_DIRECTION_OUTPUT);
   1373    WRAP(AAudioStreamBuilder_setDataCallback)(sb, out_data_callback, stm);
   1374    assert(stm->latency_frames < std::numeric_limits<int32_t>::max());
   1375    LOG("Frames per callback set to %d for output", stm->latency_frames);
   1376    WRAP(AAudioStreamBuilder_setFramesPerDataCallback)
   1377    (sb, static_cast<int32_t>(stm->latency_frames));
   1378 
   1379    int res_err = realize_stream(sb, stm->output_stream_params.get(),
   1380                                 &stm->ostream, &frame_size);
   1381    if (res_err) {
   1382      return res_err;
   1383    }
   1384 
   1385    int rate = WRAP(AAudioStream_getSampleRate)(stm->ostream);
   1386    int32_t output_burst_frames =
   1387        WRAP(AAudioStream_getFramesPerBurst)(stm->ostream);
   1388    // 3 times the burst size seems fairly robust, use it as minimum.
   1389    int32_t output_buffer_size_frames = 3 * output_burst_frames;
   1390    if (stm->latency_frames > POWERSAVE_LATENCY_FRAMES_THRESHOLD) {
   1391      // FramesPerBurst is large in power saving mode, reduce the buffer size to
   1392      // 2 bursts.
   1393      output_buffer_size_frames = 2 * output_burst_frames;
   1394    }
   1395    // Make output buffer size a function of the requested latency so clients
   1396    // can adapt to their use case.
   1397    output_buffer_size_frames =
   1398        std::max(output_buffer_size_frames,
   1399                 static_cast<int32_t>(stm->latency_frames / 2));
   1400    int32_t output_final_buffer_size_frames =
   1401        WRAP(AAudioStream_setBufferSizeInFrames)(stm->ostream,
   1402                                                 output_buffer_size_frames);
   1403 
   1404    LOG("AAudio output stream sharing mode: %d",
   1405        WRAP(AAudioStream_getSharingMode)(stm->ostream));
   1406    LOG("AAudio output stream performance mode: %d",
   1407        WRAP(AAudioStream_getPerformanceMode)(stm->ostream));
   1408    LOG("AAudio output stream buffer capacity: %d",
   1409        WRAP(AAudioStream_getBufferCapacityInFrames)(stm->ostream));
   1410    LOG("AAudio output stream buffer size: %d",
   1411        output_final_buffer_size_frames);
   1412    LOG("AAudio output stream burst size: %d", output_burst_frames);
   1413    LOG("AAudio output stream sample-rate: %d", rate);
   1414 
   1415    stm->sample_rate = stm->output_stream_params->rate;
   1416    out_params = *stm->output_stream_params;
   1417    out_params.rate = rate;
   1418 
   1419    stm->out_channels = stm->output_stream_params->channels;
   1420    stm->out_format = stm->output_stream_params->format;
   1421    stm->out_frame_size = frame_size;
   1422    stm->volume.store(1.f);
   1423  }
   1424 
   1425  // input
   1426  cubeb_stream_params in_params;
   1427  if (stm->input_stream_params) {
   1428    // Match what the OpenSL backend does for now, we could use UNPROCESSED and
   1429    // VOICE_COMMUNICATION here, but we'd need to make it clear that
   1430    // application-level AEC and other voice processing should be disabled
   1431    // there.
   1432    int input_preset = stm->voice_input ? AAUDIO_INPUT_PRESET_VOICE_RECOGNITION
   1433                                        : AAUDIO_INPUT_PRESET_CAMCORDER;
   1434    WRAP(AAudioStreamBuilder_setInputPreset)(sb, input_preset);
   1435    WRAP(AAudioStreamBuilder_setDirection)(sb, AAUDIO_DIRECTION_INPUT);
   1436    WRAP(AAudioStreamBuilder_setDataCallback)(sb, in_data_callback, stm);
   1437    assert(stm->latency_frames < std::numeric_limits<int32_t>::max());
   1438    LOG("Frames per callback set to %d for input", stm->latency_frames);
   1439    WRAP(AAudioStreamBuilder_setFramesPerDataCallback)
   1440    (sb, static_cast<int32_t>(stm->latency_frames));
   1441    int res_err = realize_stream(sb, stm->input_stream_params.get(),
   1442                                 &stm->istream, &frame_size);
   1443    if (res_err) {
   1444      return res_err;
   1445    }
   1446 
   1447    int rate = WRAP(AAudioStream_getSampleRate)(stm->istream);
   1448    LOG("AAudio input stream burst size: %d",
   1449        WRAP(AAudioStream_getFramesPerBurst)(stm->istream));
   1450    LOG("AAudio input stream sharing mode: %d",
   1451        WRAP(AAudioStream_getSharingMode)(stm->istream));
   1452    LOG("AAudio input stream performance mode: %d",
   1453        WRAP(AAudioStream_getPerformanceMode)(stm->istream));
   1454    LOG("AAudio input stream buffer capacity: %d",
   1455        WRAP(AAudioStream_getBufferCapacityInFrames)(stm->istream));
   1456    LOG("AAudio input stream buffer size: %d",
   1457        WRAP(AAudioStream_getBufferSizeInFrames)(stm->istream));
   1458    LOG("AAudio input stream sample-rate: %d", rate);
   1459 
   1460    stm->in_buf.resize(stm->latency_frames * frame_size);
   1461    assert(!stm->sample_rate ||
   1462           stm->sample_rate == stm->input_stream_params->rate);
   1463 
   1464    stm->sample_rate = stm->input_stream_params->rate;
   1465    in_params = *stm->input_stream_params;
   1466    in_params.rate = rate;
   1467    stm->in_frame_size = frame_size;
   1468  }
   1469 
   1470  // initialize resampler
   1471  stm->resampler = cubeb_resampler_create(
   1472      stm, stm->input_stream_params ? &in_params : nullptr,
   1473      stm->output_stream_params ? &out_params : nullptr, stm->sample_rate,
   1474      stm->data_callback, stm->user_ptr, CUBEB_RESAMPLER_QUALITY_DEFAULT,
   1475      CUBEB_RESAMPLER_RECLOCK_NONE);
   1476 
   1477  if (!stm->resampler) {
   1478    LOG("Failed to create resampler");
   1479    return CUBEB_ERROR;
   1480  }
   1481 
   1482  // the stream isn't started initially. We don't need to differentiate
   1483  // between a stream that was just initialized and one that played
   1484  // already but was stopped.
   1485  stm->state.store(stream_state::STOPPED);
   1486  LOG("Cubeb stream (%p) INIT success", (void *)stm);
   1487  return CUBEB_OK;
   1488 }
   1489 
   1490 static int
   1491 aaudio_stream_init(cubeb * ctx, cubeb_stream ** stream,
   1492                   char const * /* stream_name */, cubeb_devid input_device,
   1493                   cubeb_stream_params * input_stream_params,
   1494                   cubeb_devid output_device,
   1495                   cubeb_stream_params * output_stream_params,
   1496                   unsigned int latency_frames,
   1497                   cubeb_data_callback data_callback,
   1498                   cubeb_state_callback state_callback, void * user_ptr)
   1499 {
   1500  assert(!input_device);
   1501  assert(!output_device);
   1502 
   1503  // atomically find a free stream.
   1504  cubeb_stream * stm = nullptr;
   1505  unique_lock<mutex> lock;
   1506  for (auto & stream : ctx->streams) {
   1507    // This check is only an optimization, we don't strictly need it
   1508    // since we check again after locking the mutex.
   1509    if (stream.in_use.load()) {
   1510      continue;
   1511    }
   1512 
   1513    // if this fails, another thread initialized this stream
   1514    // between our check of in_use and this.
   1515    lock = unique_lock(stream.mutex, std::try_to_lock);
   1516    if (!lock.owns_lock()) {
   1517      continue;
   1518    }
   1519 
   1520    if (stream.in_use.load()) {
   1521      lock = {};
   1522      continue;
   1523    }
   1524 
   1525    stm = &stream;
   1526    break;
   1527  }
   1528 
   1529  if (!stm) {
   1530    LOG("Error: maximum number of streams reached");
   1531    return CUBEB_ERROR;
   1532  }
   1533 
   1534  stm->in_use.store(true);
   1535  stm->context = ctx;
   1536  stm->user_ptr = user_ptr;
   1537  stm->data_callback = data_callback;
   1538  stm->state_callback = state_callback;
   1539  stm->voice_input = input_stream_params &&
   1540                     !!(input_stream_params->prefs & CUBEB_STREAM_PREF_VOICE);
   1541  stm->voice_output = output_stream_params &&
   1542                      !!(output_stream_params->prefs & CUBEB_STREAM_PREF_VOICE);
   1543  stm->previous_clock = 0;
   1544  stm->latency_frames = latency_frames;
   1545  if (output_stream_params) {
   1546    stm->output_stream_params = std::make_unique<cubeb_stream_params>();
   1547    *(stm->output_stream_params) = *output_stream_params;
   1548  } else {
   1549    stm->output_stream_params = nullptr;
   1550  }
   1551  if (input_stream_params) {
   1552    stm->input_stream_params = std::make_unique<cubeb_stream_params>();
   1553    *(stm->input_stream_params) = *input_stream_params;
   1554  } else {
   1555    stm->input_stream_params = nullptr;
   1556  }
   1557 
   1558  LOG("cubeb stream prefs: voice_input: %s voice_output: %s",
   1559      stm->voice_input ? "true" : "false",
   1560      stm->voice_output ? "true" : "false");
   1561 
   1562  // This is ok: the thread is marked as being in use
   1563  lock.unlock();
   1564  int err;
   1565 
   1566  {
   1567    lock_guard guard(stm->mutex);
   1568    err = aaudio_stream_init_impl(stm, guard);
   1569  }
   1570 
   1571  if (err != CUBEB_OK) {
   1572    aaudio_stream_destroy(stm);
   1573    return err;
   1574  }
   1575 
   1576  *stream = stm;
   1577  return CUBEB_OK;
   1578 }
   1579 
   1580 static int
   1581 aaudio_stream_start(cubeb_stream * stm)
   1582 {
   1583  lock_guard lock(stm->mutex);
   1584  return aaudio_stream_start_locked(stm, lock);
   1585 }
   1586 
   1587 static int
   1588 aaudio_stream_start_locked(cubeb_stream * stm, lock_guard<mutex> & lock)
   1589 {
   1590  assert(stm && stm->in_use.load());
   1591  stream_state state = stm->state.load();
   1592  int istate = stm->istream ? WRAP(AAudioStream_getState)(stm->istream) : 0;
   1593  int ostate = stm->ostream ? WRAP(AAudioStream_getState)(stm->ostream) : 0;
   1594  LOGV("STARTING stream %p: %d (%d %d)", (void *)stm, state, istate, ostate);
   1595 
   1596  switch (state) {
   1597  case stream_state::STARTED:
   1598  case stream_state::STARTING:
   1599    LOG("cubeb stream %p already STARTING/STARTED", (void *)stm);
   1600    return CUBEB_OK;
   1601  case stream_state::ERROR:
   1602  case stream_state::SHUTDOWN:
   1603    return CUBEB_ERROR;
   1604  case stream_state::INIT:
   1605    assert(false && "Invalid stream");
   1606    return CUBEB_ERROR;
   1607  case stream_state::STOPPED:
   1608  case stream_state::STOPPING:
   1609  case stream_state::DRAINING:
   1610    break;
   1611  }
   1612 
   1613  aaudio_result_t res;
   1614 
   1615  // Important to start istream before ostream.
   1616  // As soon as we start ostream, the callbacks might be triggered an we
   1617  // might read from istream (on duplex). If istream wasn't started yet
   1618  // this is a problem.
   1619  if (stm->istream) {
   1620    res = WRAP(AAudioStream_requestStart)(stm->istream);
   1621    if (res != AAUDIO_OK) {
   1622      LOG("AAudioStream_requestStart (istream): %s",
   1623          WRAP(AAudio_convertResultToText)(res));
   1624      stm->state.store(stream_state::ERROR);
   1625      return CUBEB_ERROR;
   1626    }
   1627  }
   1628 
   1629  if (stm->ostream) {
   1630    res = WRAP(AAudioStream_requestStart)(stm->ostream);
   1631    if (res != AAUDIO_OK) {
   1632      LOG("AAudioStream_requestStart (ostream): %s",
   1633          WRAP(AAudio_convertResultToText)(res));
   1634      stm->state.store(stream_state::ERROR);
   1635      return CUBEB_ERROR;
   1636    }
   1637  }
   1638 
   1639  int ret = CUBEB_OK;
   1640  bool success;
   1641 
   1642  while (!(success = stm->state.compare_exchange_strong(
   1643               state, stream_state::STARTING))) {
   1644    // we land here only if the state has changed in the meantime
   1645    switch (state) {
   1646    // If an error ocurred in the meantime, we can't change that.
   1647    // The stream will be stopped when shut down.
   1648    case stream_state::ERROR:
   1649      ret = CUBEB_ERROR;
   1650      break;
   1651    // The only situation in which the state could have switched to draining
   1652    // is if the callback was already fired and requested draining. Don't
   1653    // overwrite that. It's not an error either though.
   1654    case stream_state::DRAINING:
   1655      break;
   1656 
   1657    // If the state switched [DRAINING -> STOPPING] or [DRAINING/STOPPING ->
   1658    // STOPPED] in the meantime, we can simply overwrite that since we
   1659    // restarted the stream.
   1660    case stream_state::STOPPING:
   1661    case stream_state::STOPPED:
   1662      continue;
   1663 
   1664    // There is no situation in which the state could have been valid before
   1665    // but now in shutdown mode, since we hold the streams mutex.
   1666    // There is also no way that it switched *into* STARTING or
   1667    // STARTED mode.
   1668    default:
   1669      assert(false && "Invalid state change");
   1670      ret = CUBEB_ERROR;
   1671      break;
   1672    }
   1673 
   1674    break;
   1675  }
   1676 
   1677  if (success) {
   1678    stm->pos_estimate.start(now_ns());
   1679  }
   1680 
   1681  // Wake the state thread to trigger STARTED/ERROR state callback.
   1682  stm->context->state.waiting.store(true);
   1683  stm->context->state.cond.notify_one();
   1684 
   1685  return ret;
   1686 }
   1687 
   1688 static int
   1689 aaudio_stream_stop(cubeb_stream * stm)
   1690 {
   1691  assert(stm && stm->in_use.load());
   1692  lock_guard lock(stm->mutex);
   1693  return aaudio_stream_stop_locked(stm, lock);
   1694 }
   1695 
   1696 static int
   1697 aaudio_stream_stop_locked(cubeb_stream * stm, lock_guard<mutex> & lock)
   1698 {
   1699  assert(stm && stm->in_use.load());
   1700 
   1701  stream_state state = stm->state.load();
   1702  aaudio_stream_state_t istate = stm->istream
   1703                                     ? WRAP(AAudioStream_getState)(stm->istream)
   1704                                     : AAUDIO_STREAM_STATE_UNINITIALIZED;
   1705  aaudio_stream_state_t ostate = stm->ostream
   1706                                     ? WRAP(AAudioStream_getState)(stm->ostream)
   1707                                     : AAUDIO_STREAM_STATE_UNINITIALIZED;
   1708  LOG("STOPPING stream %p: %d (in: %s out: %s)", (void *)stm, state,
   1709      WRAP(AAudio_convertStreamStateToText)(istate),
   1710      WRAP(AAudio_convertStreamStateToText)(ostate));
   1711 
   1712  switch (state) {
   1713  case stream_state::STOPPED:
   1714  case stream_state::STOPPING:
   1715  case stream_state::DRAINING:
   1716    LOG("cubeb stream %p already STOPPING/STOPPED", (void *)stm);
   1717    return CUBEB_OK;
   1718  case stream_state::ERROR:
   1719  case stream_state::SHUTDOWN:
   1720    return CUBEB_ERROR;
   1721  case stream_state::INIT:
   1722    assert(false && "Invalid stream");
   1723    return CUBEB_ERROR;
   1724  case stream_state::STARTED:
   1725  case stream_state::STARTING:
   1726    break;
   1727  }
   1728 
   1729  aaudio_result_t res;
   1730 
   1731  // No callbacks are triggered anymore when requestPause returns.
   1732  // That is important as we otherwise might read from a closed istream
   1733  // for a duplex stream.
   1734  // Therefor it is important to close ostream first.
   1735  if (stm->ostream) {
   1736    // Could use pause + flush here as well, the public cubeb interface
   1737    // doesn't state behavior.
   1738    res = WRAP(AAudioStream_requestPause)(stm->ostream);
   1739    if (res != AAUDIO_OK) {
   1740      LOG("AAudioStream_requestPause (ostream): %s",
   1741          WRAP(AAudio_convertResultToText)(res));
   1742      stm->state.store(stream_state::ERROR);
   1743      return CUBEB_ERROR;
   1744    }
   1745  }
   1746 
   1747  if (stm->istream) {
   1748    res = WRAP(AAudioStream_requestPause)(stm->istream);
   1749    if (res != AAUDIO_OK) {
   1750      LOG("AAudioStream_requestPause (istream): %s",
   1751          WRAP(AAudio_convertResultToText)(res));
   1752      stm->state.store(stream_state::ERROR);
   1753      return CUBEB_ERROR;
   1754    }
   1755  }
   1756 
   1757  int ret = CUBEB_OK;
   1758  bool success;
   1759  while (!(success = atomic_compare_exchange_strong(&stm->state, &state,
   1760                                                    stream_state::STOPPING))) {
   1761    // we land here only if the state has changed in the meantime
   1762    switch (state) {
   1763    // If an error ocurred in the meantime, we can't change that.
   1764    // The stream will be STOPPED when shut down.
   1765    case stream_state::ERROR:
   1766      ret = CUBEB_ERROR;
   1767      break;
   1768    // If it was switched to DRAINING in the meantime, it was or
   1769    // will be STOPPED soon anyways. We don't interfere with
   1770    // the DRAINING process, no matter in which state.
   1771    // Not an error
   1772    case stream_state::DRAINING:
   1773    case stream_state::STOPPING:
   1774    case stream_state::STOPPED:
   1775      break;
   1776 
   1777    // If the state switched from STARTING to STARTED in the meantime
   1778    // we can simply overwrite that since we just STOPPED it.
   1779    case stream_state::STARTED:
   1780      continue;
   1781 
   1782    // There is no situation in which the state could have been valid before
   1783    // but now in shutdown mode, since we hold the streams mutex.
   1784    // There is also no way that it switched *into* STARTING mode.
   1785    default:
   1786      assert(false && "Invalid state change");
   1787      ret = CUBEB_ERROR;
   1788      break;
   1789    }
   1790 
   1791    break;
   1792  }
   1793 
   1794  if (success) {
   1795    stm->pos_estimate.stop(now_ns());
   1796    stm->context->state.waiting.store(true);
   1797    stm->context->state.cond.notify_one();
   1798  }
   1799 
   1800  return ret;
   1801 }
   1802 
   1803 static int
   1804 aaudio_stream_get_position(cubeb_stream * stm, uint64_t * position)
   1805 {
   1806  assert(stm && stm->in_use.load());
   1807  lock_guard lock(stm->mutex);
   1808 
   1809  stream_state state = stm->state.load();
   1810  uint64_t init_position = stm->pos_estimate.initial_position();
   1811  AAudioStream * stream = stm->ostream ? stm->ostream : stm->istream;
   1812  switch (state) {
   1813  case stream_state::ERROR:
   1814  case stream_state::SHUTDOWN:
   1815    return CUBEB_ERROR;
   1816  case stream_state::DRAINING:
   1817  case stream_state::STOPPED:
   1818  case stream_state::STOPPING:
   1819    // getTimestamp is only valid when the stream is playing.
   1820    // Simply return the number of frames passed to aaudio
   1821    *position = init_position + WRAP(AAudioStream_getFramesRead)(stream);
   1822    if (*position < stm->previous_clock) {
   1823      *position = stm->previous_clock;
   1824    } else {
   1825      stm->previous_clock = *position;
   1826    }
   1827    return CUBEB_OK;
   1828  case stream_state::INIT:
   1829    assert(false && "Invalid stream");
   1830    return CUBEB_ERROR;
   1831  case stream_state::STARTED:
   1832  case stream_state::STARTING:
   1833    break;
   1834  }
   1835 
   1836  // No callback yet, the stream hasn't really started.
   1837  if (stm->previous_clock == 0 && !stm->timing_info.updated()) {
   1838    LOG("Not timing info yet");
   1839    *position = init_position;
   1840    return CUBEB_OK;
   1841  }
   1842 
   1843  AAudioTimingInfo info = stm->timing_info.read();
   1844  LOGV("AAudioTimingInfo idx:%lu tstamp:%lu latency:%u",
   1845       info.output_frame_index, info.tstamp, info.output_latency);
   1846  // Interpolate client side since the last callback.
   1847  uint64_t interpolation =
   1848      (stm->sample_rate *
   1849       stm->pos_estimate.elapsed_time_since_callback(now_ns(), info.tstamp) /
   1850       NS_PER_S);
   1851  *position = init_position + info.output_frame_index + interpolation -
   1852              info.output_latency;
   1853  if (*position < stm->previous_clock) {
   1854    *position = stm->previous_clock;
   1855  } else {
   1856    stm->previous_clock = *position;
   1857  }
   1858 
   1859  LOG("aaudio_stream_get_position: %" PRIu64 " frames", *position);
   1860 
   1861  return CUBEB_OK;
   1862 }
   1863 
   1864 static int
   1865 aaudio_stream_get_latency(cubeb_stream * stm, uint32_t * latency)
   1866 {
   1867  if (!stm->ostream) {
   1868    LOG("error: aaudio_stream_get_latency on input-only stream");
   1869    return CUBEB_ERROR;
   1870  }
   1871 
   1872  if (!stm->latency_metrics_available) {
   1873    LOG("Not timing info yet (output)");
   1874    return CUBEB_OK;
   1875  }
   1876 
   1877  AAudioTimingInfo info = stm->timing_info.read();
   1878 
   1879  *latency = info.output_latency;
   1880  LOG("aaudio_stream_get_latency, %u frames", *latency);
   1881 
   1882  return CUBEB_OK;
   1883 }
   1884 
   1885 static int
   1886 aaudio_stream_get_input_latency(cubeb_stream * stm, uint32_t * latency)
   1887 {
   1888  if (!stm->istream) {
   1889    LOG("error: aaudio_stream_get_input_latency on an output-only stream");
   1890    return CUBEB_ERROR;
   1891  }
   1892 
   1893  if (!stm->latency_metrics_available) {
   1894    LOG("Not timing info yet (input)");
   1895    return CUBEB_OK;
   1896  }
   1897 
   1898  AAudioTimingInfo info = stm->timing_info.read();
   1899 
   1900  *latency = info.input_latency;
   1901  LOG("aaudio_stream_get_latency, %u frames", *latency);
   1902 
   1903  return CUBEB_OK;
   1904 }
   1905 
   1906 static int
   1907 aaudio_stream_set_volume(cubeb_stream * stm, float volume)
   1908 {
   1909  assert(stm && stm->in_use.load() && stm->ostream);
   1910  stm->volume.store(volume);
   1911  return CUBEB_OK;
   1912 }
   1913 
   1914 aaudio_data_callback_result_t
   1915 dummy_callback(AAudioStream * stream, void * userData, void * audioData,
   1916               int32_t numFrames)
   1917 {
   1918  return AAUDIO_CALLBACK_RESULT_STOP;
   1919 }
   1920 
   1921 // Returns a dummy stream with all default settings
   1922 static AAudioStream *
   1923 init_dummy_stream()
   1924 {
   1925  AAudioStreamBuilder * streamBuilder;
   1926  aaudio_result_t res;
   1927  res = WRAP(AAudio_createStreamBuilder)(&streamBuilder);
   1928  if (res != AAUDIO_OK) {
   1929    LOG("init_dummy_stream: AAudio_createStreamBuilder: %s",
   1930        WRAP(AAudio_convertResultToText)(res));
   1931    return nullptr;
   1932  }
   1933  WRAP(AAudioStreamBuilder_setDataCallback)
   1934  (streamBuilder, dummy_callback, nullptr);
   1935  WRAP(AAudioStreamBuilder_setPerformanceMode)
   1936  (streamBuilder, AAUDIO_PERFORMANCE_MODE_LOW_LATENCY);
   1937 
   1938  AAudioStream * stream;
   1939  res = WRAP(AAudioStreamBuilder_openStream)(streamBuilder, &stream);
   1940  if (res != AAUDIO_OK) {
   1941    LOG("init_dummy_stream: AAudioStreamBuilder_openStream %s",
   1942        WRAP(AAudio_convertResultToText)(res));
   1943    return nullptr;
   1944  }
   1945  WRAP(AAudioStreamBuilder_delete)(streamBuilder);
   1946 
   1947  return stream;
   1948 }
   1949 
   1950 static void
   1951 destroy_dummy_stream(AAudioStream * stream)
   1952 {
   1953  WRAP(AAudioStream_close)(stream);
   1954 }
   1955 
   1956 static int
   1957 aaudio_get_min_latency(cubeb * ctx, cubeb_stream_params params,
   1958                       uint32_t * latency_frames)
   1959 {
   1960  AAudioStream * stream = init_dummy_stream();
   1961 
   1962  if (!stream) {
   1963    return CUBEB_ERROR;
   1964  }
   1965 
   1966  // https://android.googlesource.com/platform/compatibility/cdd/+/refs/heads/master/5_multimedia/5_6_audio-latency.md
   1967  *latency_frames = WRAP(AAudioStream_getFramesPerBurst)(stream);
   1968 
   1969  LOG("aaudio_get_min_latency: %u frames", *latency_frames);
   1970 
   1971  destroy_dummy_stream(stream);
   1972 
   1973  return CUBEB_OK;
   1974 }
   1975 
   1976 int
   1977 aaudio_get_preferred_sample_rate(cubeb * ctx, uint32_t * rate)
   1978 {
   1979  AAudioStream * stream = init_dummy_stream();
   1980 
   1981  if (!stream) {
   1982    return CUBEB_ERROR;
   1983  }
   1984 
   1985  *rate = WRAP(AAudioStream_getSampleRate)(stream);
   1986 
   1987  LOG("aaudio_get_preferred_sample_rate %uHz", *rate);
   1988 
   1989  destroy_dummy_stream(stream);
   1990 
   1991  return CUBEB_OK;
   1992 }
   1993 
   1994 extern "C" int
   1995 aaudio_init(cubeb ** context, char const * context_name);
   1996 
   1997 const static struct cubeb_ops aaudio_ops = {
   1998    /*.init =*/aaudio_init,
   1999    /*.get_backend_id =*/aaudio_get_backend_id,
   2000    /*.get_max_channel_count =*/aaudio_get_max_channel_count,
   2001    /* .get_min_latency =*/aaudio_get_min_latency,
   2002    /*.get_preferred_sample_rate =*/aaudio_get_preferred_sample_rate,
   2003    /*.get_supported_input_processing_params =*/nullptr,
   2004    /*.enumerate_devices =*/nullptr,
   2005    /*.device_collection_destroy =*/nullptr,
   2006    /*.destroy =*/aaudio_destroy,
   2007    /*.stream_init =*/aaudio_stream_init,
   2008    /*.stream_destroy =*/aaudio_stream_destroy,
   2009    /*.stream_start =*/aaudio_stream_start,
   2010    /*.stream_stop =*/aaudio_stream_stop,
   2011    /*.stream_get_position =*/aaudio_stream_get_position,
   2012    /*.stream_get_latency =*/aaudio_stream_get_latency,
   2013    /*.stream_get_input_latency =*/aaudio_stream_get_input_latency,
   2014    /*.stream_set_volume =*/aaudio_stream_set_volume,
   2015    /*.stream_set_name =*/nullptr,
   2016    /*.stream_get_current_device =*/nullptr,
   2017    /*.stream_set_input_mute =*/nullptr,
   2018    /*.stream_set_input_processing_params =*/nullptr,
   2019    /*.stream_device_destroy =*/nullptr,
   2020    /*.stream_register_device_changed_callback =*/nullptr,
   2021    /*.register_device_collection_changed =*/nullptr};
   2022 
   2023 extern "C" /*static*/ int
   2024 aaudio_init(cubeb ** context, char const * /* context_name */)
   2025 {
   2026  if (android_get_device_api_level() <= 30) {
   2027    return CUBEB_ERROR;
   2028  }
   2029 #ifndef DISABLE_LIBAAUDIO_DLOPEN
   2030  if (!AAudioLibrary::get().load()) {
   2031    return CUBEB_ERROR;
   2032  }
   2033 #endif
   2034 
   2035  cubeb * ctx = new cubeb;
   2036  ctx->ops = &aaudio_ops;
   2037 
   2038  ctx->state.thread = std::thread(state_thread, ctx);
   2039 
   2040  // NOTE: using platform-specific APIs we could set the priority of the
   2041  // notifier thread lower than the priority of the state thread.
   2042  // This way, it's more likely that the state thread will be woken up
   2043  // by the condition variable signal when both are currently waiting
   2044  ctx->state.notifier = std::thread(notifier_thread, ctx);
   2045 
   2046  *context = ctx;
   2047  return CUBEB_OK;
   2048 }