// Copyright 2017 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.

#include "src/media/audio/audio_core/audio_driver.h"

#include <lib/zx/clock.h>
#include <zircon/status.h>

#include <cstdio>
#include <iomanip>

#include <audio-proto-utils/format-utils.h>

#include "lib/fidl/cpp/clone.h"
#include "src/media/audio/audio_core/driver_utils.h"
#include "src/media/audio/lib/logging/logging.h"

namespace media::audio {

static constexpr zx_txid_t TXID = 1;

// Timeout values are chosen to be generous while still providing some guard-rails against hardware
// errors. Correctly functioning hardware and drivers should never result in any timeouts.
static constexpr zx_duration_t kDefaultShortCmdTimeout = ZX_SEC(1);
static constexpr zx_duration_t kDefaultLongCmdTimeout = ZX_SEC(4);

static constexpr bool kEnablePositionNotifications = true;
// To what extent should position notification messages be logged? If logging level is SPEW, every
// notification is logged (specified by Spew const). If TRACE, log less frequently, specified by
// Trace const. If INFO, even less frequently per Info const (INFO is default for DEBUG builds).
// Default for audio_core in NDEBUG builds is WARNING, so by default we do not log any of these
// messages on Release builds. Set to false to not log at all, even for unsolicited notifications.
static constexpr bool kLogPositionNotifications = true;
static constexpr uint16_t kPositionNotificationSpewInterval = 1;
static constexpr uint16_t kPositionNotificationTraceInterval = 60;
static constexpr uint16_t kPositionNotificationInfoInterval = 3600;

AudioDriver::AudioDriver(AudioDevice* owner) : owner_(owner) {
  FXL_DCHECK(owner_ != nullptr);
  stream_channel_ = dispatcher::Channel::Create();
  rb_channel_ = dispatcher::Channel::Create();
  cmd_timeout_ = dispatcher::Timer::Create();
}

zx_status_t AudioDriver::Init(zx::channel stream_channel) {
  FXL_DCHECK(state_ == State::Uninitialized);

  if ((stream_channel_ == nullptr) || (rb_channel_ == nullptr) || (cmd_timeout_ == nullptr)) {
    return ZX_ERR_NO_RESOURCES;
  }

  // Fetch the KOID of our stream channel. We use this unique ID as our device's device token.
  zx_status_t res;
  zx_info_handle_basic_t sc_info;
  res = stream_channel.get_info(ZX_INFO_HANDLE_BASIC, &sc_info, sizeof(sc_info), nullptr, nullptr);
  if (res != ZX_OK) {
    FXL_PLOG(ERROR, res) << "Failed to to fetch stream channel KOID";
    return res;
  }
  stream_channel_koid_ = sc_info.koid;

  // Activate the stream channel.
  dispatcher::Channel::ProcessHandler process_handler(
      [this](dispatcher::Channel* channel) -> zx_status_t {
        OBTAIN_EXECUTION_DOMAIN_TOKEN(token, owner_->mix_domain_);
        FXL_DCHECK(stream_channel_.get() == channel);
        return ProcessStreamChannelMessage();
      });

  dispatcher::Channel::ChannelClosedHandler channel_closed_handler(
      [this](const dispatcher::Channel* channel) {
        OBTAIN_EXECUTION_DOMAIN_TOKEN(token, owner_->mix_domain_);
        FXL_DCHECK(stream_channel_.get() == channel);
        ShutdownSelf("Stream channel closed unexpectedly", ZX_ERR_PEER_CLOSED);
      });

  res = stream_channel_->Activate(std::move(stream_channel), owner_->mix_domain_,
                                  std::move(process_handler), std::move(channel_closed_handler));
  if (res != ZX_OK) {
    FXL_PLOG(ERROR, res) << "Failed to activate stream channel for AudioDriver";
    return res;
  }

  // Activate the command timeout timer.
  dispatcher::Timer::ProcessHandler cmd_timeout_handler(
      [this](dispatcher::Timer* timer) -> zx_status_t {
        OBTAIN_EXECUTION_DOMAIN_TOKEN(token, owner_->mix_domain_);
        FXL_DCHECK(cmd_timeout_.get() == timer);
        ShutdownSelf("Unexpected command timeout", ZX_ERR_TIMED_OUT);
        return ZX_OK;
      });

  res = cmd_timeout_->Activate(owner_->mix_domain_, std::move(cmd_timeout_handler));
  if (res != ZX_OK) {
    FXL_PLOG(ERROR, res) << "Failed to activate command timeout timer for AudioDriver";
    return res;
  }

  // We are now initialized, but we don't know any fundamental driver level info, such as:
  //
  // 1) This device's persistent unique ID.
  // 2) The list of formats supported by this device.
  // 3) The user-visible strings for this device (manufacturer, product, etc...).
  state_ = State::MissingDriverInfo;
  return ZX_OK;
}

void AudioDriver::Cleanup() {
  fbl::RefPtr<DriverRingBuffer> ring_buffer;
  {
    std::lock_guard<std::mutex> lock(ring_buffer_state_lock_);
    ring_buffer = std::move(ring_buffer_);
    clock_mono_to_ring_pos_bytes_ = TimelineFunction();
    ring_buffer_state_gen_.Next();
  }
  ring_buffer.reset();

  stream_channel_->Deactivate();
  rb_channel_->Deactivate();
  cmd_timeout_->Deactivate();
}

void AudioDriver::SnapshotRingBuffer(RingBufferSnapshot* snapshot) const {
  FXL_DCHECK(snapshot);
  std::lock_guard<std::mutex> lock(ring_buffer_state_lock_);

  snapshot->ring_buffer = ring_buffer_;
  snapshot->clock_mono_to_ring_pos_bytes = clock_mono_to_ring_pos_bytes_;
  snapshot->position_to_end_fence_frames = owner_->is_input() ? fifo_depth_frames() : 0;
  snapshot->end_fence_to_start_fence_frames = end_fence_to_start_fence_frames_;
  snapshot->gen_id = ring_buffer_state_gen_.get();
}

fuchsia::media::AudioStreamTypePtr AudioDriver::GetSourceFormat() const {
  std::lock_guard<std::mutex> lock(configured_format_lock_);

  if (!configured_format_)
    return nullptr;

  fuchsia::media::AudioStreamTypePtr result;
  fidl::Clone(configured_format_, &result);
  return result;
}

zx_status_t AudioDriver::GetDriverInfo() {
  // TODO(MTWN-385): Figure out a better way to assert this!
  OBTAIN_EXECUTION_DOMAIN_TOKEN(token, owner_->mix_domain_);

  // We have to be operational in order to fetch supported formats.
  if (!operational()) {
    FXL_LOG(ERROR) << "Cannot fetch supported formats while non-operational (state = "
                   << static_cast<uint32_t>(state_) << ")";
    return ZX_ERR_BAD_STATE;
  }

  // If already fetching initial driver info, get out now and inform our owner when this completes.
  if (fetching_driver_info()) {
    return ZX_OK;
  }

  // Send the commands to do the following.
  //
  // 1) Fetch our persistent unique ID.
  // 2) Fetch our manufacturer string.
  // 3) Fetch our product string.
  // 4) Fetch our current gain state and capabilities.
  // 5) Fetch our supported format list.

  // Step #1, fetch unique IDs.
  {
    audio_stream_cmd_get_formats_req_t req;
    req.hdr.cmd = AUDIO_STREAM_CMD_GET_UNIQUE_ID;
    req.hdr.transaction_id = TXID;

    zx_status_t res = stream_channel_->Write(&req, sizeof(req));
    if (res != ZX_OK) {
      ShutdownSelf("Failed to request unique ID.", res);
      return res;
    }
  }

  // Steps #2-3, fetch strings.
  static const audio_stream_string_id_t kStringsToFetch[] = {
      AUDIO_STREAM_STR_ID_MANUFACTURER,
      AUDIO_STREAM_STR_ID_PRODUCT,
  };
  for (const auto string_id : kStringsToFetch) {
    audio_stream_cmd_get_string_req_t req;
    req.hdr.cmd = AUDIO_STREAM_CMD_GET_STRING;
    req.hdr.transaction_id = TXID;
    req.id = string_id;

    zx_status_t res = stream_channel_->Write(&req, sizeof(req));
    if (res != ZX_OK) {
      ShutdownSelf("Failed to request string.", res);
      return res;
    }
  }

  // Step #4. Fetch our current gain state.
  {
    audio_stream_cmd_get_gain_req_t req;
    req.hdr.cmd = AUDIO_STREAM_CMD_GET_GAIN;
    req.hdr.transaction_id = TXID;

    zx_status_t res = stream_channel_->Write(&req, sizeof(req));
    if (res != ZX_OK) {
      ShutdownSelf("Failed to request gain state.", res);
      return res;
    }
  }

  // Step #5. Fetch our list of supported formats.
  {
    FXL_DCHECK(format_ranges_.empty());

    // Actually send the request to the driver.
    audio_stream_cmd_get_formats_req_t req;
    req.hdr.cmd = AUDIO_STREAM_CMD_GET_FORMATS;
    req.hdr.transaction_id = TXID;

    zx_status_t res = stream_channel_->Write(&req, sizeof(req));
    if (res != ZX_OK) {
      ShutdownSelf("Failed to request supported format list.", res);
      return res;
    }
  }

  // Setup our command timeout.
  fetch_driver_info_timeout_ = zx_deadline_after(kDefaultShortCmdTimeout);
  SetupCommandTimeout();
  return ZX_OK;
}

zx_status_t AudioDriver::Configure(uint32_t frames_per_second, uint32_t channels,
                                   fuchsia::media::AudioSampleFormat fmt,
                                   zx_duration_t min_ring_buffer_duration) {
  // TODO(MTWN-385): Figure out a better way to assert this!
  OBTAIN_EXECUTION_DOMAIN_TOKEN(token, owner_->mix_domain_);

  // Sanity check arguments.
  audio_sample_format_t driver_format;
  if (!driver_utils::AudioSampleFormatToDriverSampleFormat(fmt, &driver_format)) {
    FXL_LOG(ERROR) << "Failed to convert Fmt 0x" << std::hex << static_cast<uint32_t>(fmt)
                   << " to driver format.";
    return ZX_ERR_INVALID_ARGS;
  }

  if (channels > std::numeric_limits<uint16_t>::max()) {
    FXL_LOG(ERROR) << "Bad channel count: " << channels;
    return ZX_ERR_INVALID_ARGS;
  }

  // TODO(MTWN-386): sanity check the min_ring_buffer_duration.

  // Check our known format list for compatibility.
  bool found_format = false;
  for (const auto& fmt_range : format_ranges_) {
    found_format =
        ::audio::utils::FormatIsCompatible(frames_per_second, channels, driver_format, fmt_range);
    if (found_format) {
      break;
    }
  }

  if (!found_format) {
    FXL_LOG(ERROR) << "No compatible format range found when setting format to "
                   << frames_per_second << " Hz " << channels << " Ch Fmt 0x" << std::hex
                   << static_cast<uint32_t>(fmt);
    return ZX_ERR_INVALID_ARGS;
  }

  // We must be in Unconfigured state to change formats.
  // TODO(MTWN-387): Also permit this if we are in Configured state.
  if (state_ != State::Unconfigured) {
    FXL_LOG(ERROR) << "Bad state while attempting to configure for " << frames_per_second << " Hz "
                   << channels << " Ch Fmt 0x" << std::hex << static_cast<uint32_t>(fmt)
                   << " (state = " << static_cast<uint32_t>(state_) << ")";
    return ZX_ERR_BAD_STATE;
  }

  // Record the details of our intended target format
  frames_per_sec_ = frames_per_second;
  channel_count_ = static_cast<uint16_t>(channels);
  sample_format_ = driver_format;
  bytes_per_frame_ = ::audio::utils::ComputeFrameSize(channel_count_, sample_format_);

  min_ring_buffer_duration_ = min_ring_buffer_duration;

  // Start the process of configuring by sending the message to set the format.
  audio_stream_cmd_set_format_req_t req;

  req.hdr.cmd = AUDIO_STREAM_CMD_SET_FORMAT;
  req.hdr.transaction_id = TXID;
  req.frames_per_second = frames_per_sec_;
  req.channels = channel_count_;
  req.sample_format = sample_format_;

  {
    std::lock_guard<std::mutex> lock(configured_format_lock_);
    configured_format_ = fuchsia::media::AudioStreamType::New();
    configured_format_->sample_format = fmt;
    configured_format_->channels = channels;
    configured_format_->frames_per_second = frames_per_second;
  }

  zx_status_t res = stream_channel_->Write(&req, sizeof(req));
  if (res != ZX_OK) {
    ShutdownSelf("Failed to send set format command", res);
    return res;
  }

  // Change state, setup our command timeout and we are finished.
  state_ = State::Configuring_SettingFormat;
  configuration_timeout_ = zx_deadline_after(kDefaultLongCmdTimeout);
  SetupCommandTimeout();

  return ZX_OK;
}

zx_status_t AudioDriver::Start() {
  // TODO(MTWN-385): Figure out a better way to assert this!
  OBTAIN_EXECUTION_DOMAIN_TOKEN(token, owner_->mix_domain_);

  // In order to start, we must be in the Configured state.
  //
  // Note: Attempting to start while already started is considered an error because (since we are
  // already started) we will never deliver the OnDriverStartComplete callback. It would be
  // confusing to call it directly from here -- before the user's call to Start even returned.
  if (state_ != State::Configured) {
    FXL_LOG(ERROR) << "Bad state while attempting start (state = " << static_cast<uint32_t>(state_)
                   << ")";
    return ZX_ERR_BAD_STATE;
  }

  // Send the command to start the ring buffer.
  audio_rb_cmd_start_req_t req;
  req.hdr.cmd = AUDIO_RB_CMD_START;
  req.hdr.transaction_id = TXID;
  zx_status_t res = rb_channel_->Write(&req, sizeof(req));
  if (res != ZX_OK) {
    ShutdownSelf("Failed to send set start command", res);
    return res;
  }

  // Change state, setup our command timeout and we are finished.
  state_ = State::Starting;
  configuration_timeout_ = zx_deadline_after(kDefaultShortCmdTimeout);
  SetupCommandTimeout();

  return ZX_OK;
}

zx_status_t AudioDriver::Stop() {
  // TODO(MTWN-385): Figure out a better way to assert this!
  OBTAIN_EXECUTION_DOMAIN_TOKEN(token, owner_->mix_domain_);

  // In order to stop, we must be in the Started state.
  // TODO(MTWN-388): make Stop idempotent. Allow Stop when Configured/Stopping; disallow if
  // Shutdown; consider what to do if Uninitialized/MissingDriverInfo/Unconfigured/Configuring. Most
  // importantly, if driver is Starting, queue the request until Start completes (as we cannot
  // cancel driver commands). Finally, handle multiple Stop calls to be in-flight concurrently.
  if (state_ != State::Started) {
    FXL_LOG(ERROR) << "Bad state while attempting stop (state = " << static_cast<uint32_t>(state_)
                   << ")";
    return ZX_ERR_BAD_STATE;
  }

  // Invalidate our timeline transformation here. To outside observers, we are now stopped.
  {
    std::lock_guard<std::mutex> lock(ring_buffer_state_lock_);
    clock_mono_to_ring_pos_bytes_ = TimelineFunction();
    ring_buffer_state_gen_.Next();
  }

  // Send the command to stop the ring buffer.
  audio_rb_cmd_start_req_t req;
  req.hdr.cmd = AUDIO_RB_CMD_STOP;
  req.hdr.transaction_id = TXID;
  zx_status_t res = rb_channel_->Write(&req, sizeof(req));
  if (res != ZX_OK) {
    ShutdownSelf("Failed to send set stop command", res);
    return res;
  }

  // We were recently in steady state, so assert that we have no configuration timeout at this time.
  FXL_DCHECK(configuration_timeout_ == ZX_TIME_INFINITE);

  // We are now in the Stopping state.
  state_ = State::Stopping;
  configuration_timeout_ = zx_deadline_after(kDefaultShortCmdTimeout);
  SetupCommandTimeout();

  return ZX_OK;
}

zx_status_t AudioDriver::SetPlugDetectEnabled(bool enabled) {
  // TODO(MTWN-385): Figure out a better way to assert this!
  OBTAIN_EXECUTION_DOMAIN_TOKEN(token, owner_->mix_domain_);

  if (enabled == pd_enabled_) {
    return ZX_OK;
  }

  audio_stream_cmd_plug_detect_req_t req;
  if (enabled) {
    req.hdr.cmd = AUDIO_STREAM_CMD_PLUG_DETECT;
    req.flags = AUDIO_PDF_ENABLE_NOTIFICATIONS;
    pd_enable_timeout_ = zx_deadline_after(kDefaultShortCmdTimeout);
  } else {
    req.hdr.cmd = static_cast<audio_cmd_t>(AUDIO_STREAM_CMD_PLUG_DETECT | AUDIO_FLAG_NO_ACK);
    req.flags = AUDIO_PDF_DISABLE_NOTIFICATIONS;
    pd_enable_timeout_ = ZX_TIME_INFINITE;
  }
  req.hdr.transaction_id = TXID;

  zx_status_t res = stream_channel_->Write(&req, sizeof(req));
  if (res != ZX_OK) {
    ShutdownSelf("Failed to request send plug state request", res);
    return res;
  }

  pd_enabled_ = enabled;
  SetupCommandTimeout();

  return ZX_OK;
}

zx_status_t AudioDriver::ReadMessage(dispatcher::Channel* channel, void* buf, uint32_t buf_size,
                                     uint32_t* bytes_read_out, zx::handle* handle_out) {
  FXL_DCHECK(buf != nullptr);
  FXL_DCHECK(bytes_read_out != nullptr);
  FXL_DCHECK(handle_out != nullptr);
  FXL_DCHECK(buf_size >= sizeof(audio_cmd_hdr_t));

  if (!operational()) {
    return ZX_ERR_BAD_STATE;
  }

  zx_status_t res;
  res = channel->Read(buf, buf_size, bytes_read_out, handle_out);
  if (res != ZX_OK) {
    ShutdownSelf("Error attempting to read channel response", res);
    return res;
  }

  if (*bytes_read_out < sizeof(audio_cmd_hdr_t)) {
    FXL_LOG(ERROR) << "Channel response is too small to hold even a "
                   << "message header (" << *bytes_read_out << " < " << sizeof(audio_cmd_hdr_t)
                   << ").";
    ShutdownSelf("Channel response too small", ZX_ERR_INVALID_ARGS);
    return ZX_ERR_INVALID_ARGS;
  }

  return ZX_OK;
}

#define CHECK_RESP(_ioctl, _payload, _expect_handle, _is_notif)                                \
  do {                                                                                         \
    if ((_expect_handle) != rxed_handle.is_valid()) {                                          \
      /* If SET_FORMAT, we will provide better error info later */                             \
      if (msg.hdr.cmd != AUDIO_STREAM_CMD_SET_FORMAT) {                                        \
        FXL_LOG(ERROR) << ((_expect_handle) ? "Missing" : "Unexpected")                        \
                       << " handle in " #_ioctl " response";                                   \
        return ZX_ERR_INVALID_ARGS;                                                            \
      }                                                                                        \
    }                                                                                          \
    if ((msg.hdr.transaction_id == AUDIO_INVALID_TRANSACTION_ID) != (_is_notif)) {             \
      FXL_LOG(ERROR) << "Bad txn id " << msg.hdr.transaction_id << " in " #_ioctl " response"; \
      return ZX_ERR_INVALID_ARGS;                                                              \
    }                                                                                          \
    if (bytes_read != sizeof(msg._payload)) {                                                  \
      FXL_LOG(ERROR) << "Bad " #_ioctl " response length (" << bytes_read                      \
                     << " != " << sizeof(msg._payload) << ")";                                 \
      return ZX_ERR_INVALID_ARGS;                                                              \
    }                                                                                          \
  } while (0)

zx_status_t AudioDriver::ProcessStreamChannelMessage() {
  zx_status_t res;
  zx::handle rxed_handle;
  uint32_t bytes_read;
  union {
    audio_cmd_hdr_t hdr;
    audio_stream_cmd_get_unique_id_resp_t get_unique_id;
    audio_stream_cmd_get_string_resp_t get_string;
    audio_stream_cmd_get_gain_resp_t get_gain;
    audio_stream_cmd_get_formats_resp_t get_formats;
    audio_stream_cmd_set_format_resp_t set_format;
    audio_stream_cmd_plug_detect_resp_t pd_resp;
    audio_stream_plug_detect_notify_t pd_notify;
  } msg;
  static_assert(sizeof(msg) <= 256, "Message buffer is becoming too large to hold on the stack!");

  res = ReadMessage(stream_channel_.get(), &msg, sizeof(msg), &bytes_read, &rxed_handle);
  if (res != ZX_OK) {
    return res;
  }

  bool plug_state;
  switch (msg.hdr.cmd) {
    case AUDIO_STREAM_CMD_GET_UNIQUE_ID:
      CHECK_RESP(AUDIO_STREAM_CMD_GET_UNIQUE_ID, get_unique_id, false, false);
      persistent_unique_id_ = msg.get_unique_id.unique_id;
      res = OnDriverInfoFetched(kDriverInfoHasUniqueId);
      break;

    case AUDIO_STREAM_CMD_GET_STRING:
      CHECK_RESP(AUDIO_STREAM_CMD_GET_STRING, get_string, false, false);
      res = ProcessGetStringResponse(msg.get_string);
      break;

    case AUDIO_STREAM_CMD_GET_GAIN:
      CHECK_RESP(AUDIO_STREAM_CMD_GET_GAIN, get_gain, false, false);
      res = ProcessGetGainResponse(msg.get_gain);
      break;

    case AUDIO_STREAM_CMD_GET_FORMATS:
      CHECK_RESP(AUDIO_STREAM_CMD_GET_FORMATS, get_formats, false, false);
      res = ProcessGetFormatsResponse(msg.get_formats);
      break;

    case AUDIO_STREAM_CMD_SET_FORMAT:
      CHECK_RESP(AUDIO_STREAM_CMD_SET_FORMAT, set_format, true, false);
      res = ProcessSetFormatResponse(msg.set_format, zx::channel(rxed_handle.release()));
      break;

    case AUDIO_STREAM_CMD_PLUG_DETECT:
      CHECK_RESP(AUDIO_STREAM_CMD_PLUG_DETECT, pd_resp, false, false);
      if ((msg.pd_resp.flags & AUDIO_PDNF_HARDWIRED) != 0) {
        plug_state = true;
      } else {
        plug_state = ((msg.pd_resp.flags & AUDIO_PDNF_PLUGGED) != 0);
        if ((msg.pd_resp.flags & AUDIO_PDNF_CAN_NOTIFY) == 0) {
          // TODO(MTWN-389): If we encounter hardware which must be polled for plug detection, set
          // a timer to periodically check this; don't just assume that output is always plugged in.
          FXL_LOG(WARNING) << "Stream is incapable of async plug detection notifications. Assuming "
                              "that the stream is always plugged in for now.";
          plug_state = true;
        }
      }

      ReportPlugStateChange(plug_state, msg.pd_resp.plug_state_time);

      pd_enable_timeout_ = ZX_TIME_INFINITE;
      SetupCommandTimeout();
      break;

    case AUDIO_STREAM_PLUG_DETECT_NOTIFY:
      CHECK_RESP(AUDIO_STREAM_CMD_PLUG_DETECT_NOTIFY, pd_notify, false, true);
      plug_state = ((msg.pd_notify.flags & AUDIO_PDNF_PLUGGED) != 0);
      ReportPlugStateChange(plug_state, msg.pd_notify.plug_state_time);
      break;

    default:
      FXL_LOG(ERROR) << "Unrecognized stream channel response 0x" << std::hex << msg.hdr.cmd;
      return ZX_ERR_BAD_STATE;
  }

  if (res != ZX_OK) {
    ShutdownSelf("Error while processing stream channel message", res);
  }

  return res;
}

zx_status_t AudioDriver::ProcessRingBufferChannelMessage() {
  zx_status_t res;
  zx::handle rxed_handle;
  uint32_t bytes_read;
  union {
    audio_cmd_hdr_t hdr;
    audio_rb_cmd_get_fifo_depth_resp_t get_fifo_depth;
    audio_rb_cmd_get_buffer_resp_t get_buffer;
    audio_rb_cmd_start_resp_t start;
    audio_rb_cmd_stop_resp_t stop;
    audio_rb_position_notify_t pos_notify;
  } msg;
  static_assert(sizeof(msg) <= 256, "Message buffer is becoming too large to hold on the stack!");

  res = ReadMessage(rb_channel_.get(), &msg, sizeof(msg), &bytes_read, &rxed_handle);
  if (res != ZX_OK) {
    return res;
  }

  switch (msg.hdr.cmd) {
    case AUDIO_RB_CMD_GET_FIFO_DEPTH:
      CHECK_RESP(AUDIO_RB_CMD_GET_FIFO_DEPTH, get_fifo_depth, false, false);
      res = ProcessGetFifoDepthResponse(msg.get_fifo_depth);
      break;

    case AUDIO_RB_CMD_GET_BUFFER:
      CHECK_RESP(AUDIO_RB_CMD_GET_BUFFER, get_buffer, true, false);
      res = ProcessGetBufferResponse(msg.get_buffer, zx::vmo(rxed_handle.release()));
      break;

    case AUDIO_RB_CMD_START:
      CHECK_RESP(AUDIO_RB_CMD_START, start, false, false);
      res = ProcessStartResponse(msg.start);
      break;

    case AUDIO_RB_CMD_STOP:
      CHECK_RESP(AUDIO_RB_CMD_STOP, stop, false, false);
      res = ProcessStopResponse(msg.stop);
      break;

    case AUDIO_RB_POSITION_NOTIFY:
      CHECK_RESP(AUDIO_RB_POSITION_NOTIFY, pos_notify, false, true);
      res = ProcessPositionNotify(msg.pos_notify);
      break;

    default:
      FXL_LOG(ERROR) << "Unrecognized ring buffer channel response 0x" << std::hex << msg.hdr.cmd;
      return ZX_ERR_BAD_STATE;
  }

  if (res != ZX_OK) {
    ShutdownSelf("Error while processing ring buffer message", res);
  }

  return res;
}
#undef CHECK_RESP

zx_status_t AudioDriver::ProcessGetStringResponse(audio_stream_cmd_get_string_resp_t& resp) {
  std::string* tgt_string;
  uint32_t info_bit;

  if (state_ != State::MissingDriverInfo) {
    FXL_LOG(ERROR) << "Bad state (" << static_cast<uint32_t>(state_)
                   << ") while handling get string response.";
    return ZX_ERR_BAD_STATE;
  }

  if (resp.result != ZX_OK) {
    FXL_LOG(WARNING) << "Error ( " << resp.result << ") attempting to fetch string id " << resp.id
                     << ". Replacing with <unknown>.";
    resp.strlen = static_cast<uint32_t>(
        snprintf(reinterpret_cast<char*>(resp.str), sizeof(resp.str), "<unknown>"));
  }

  switch (resp.id) {
    case AUDIO_STREAM_STR_ID_MANUFACTURER:
      info_bit = kDriverInfoHasMfrStr;
      tgt_string = &manufacturer_name_;
      break;

    case AUDIO_STREAM_STR_ID_PRODUCT:
      info_bit = kDriverInfoHasProdStr;
      tgt_string = &product_name_;
      break;

    default:
      FXL_LOG(ERROR) << "Unrecognized string id (" << resp.id << ").";
      return ZX_ERR_INVALID_ARGS;
  }

  if (resp.strlen > sizeof(resp.str)) {
    FXL_LOG(ERROR) << "Bad string length " << resp.strlen << " attempting to fetch string id "
                   << resp.id << ".";
    return ZX_ERR_INTERNAL;
  }

  // Stash the string we just received and update our progress in fetching our initial driver info.
  FXL_DCHECK(tgt_string != nullptr);
  tgt_string->assign(reinterpret_cast<char*>(resp.str), resp.strlen);
  return OnDriverInfoFetched(info_bit);
}

zx_status_t AudioDriver::ProcessGetGainResponse(audio_stream_cmd_get_gain_resp_t& resp) {
  hw_gain_state_.cur_mute = resp.cur_mute;
  hw_gain_state_.cur_agc = resp.cur_agc;
  hw_gain_state_.cur_gain = resp.cur_gain;
  hw_gain_state_.can_mute = resp.can_mute;
  hw_gain_state_.can_agc = resp.can_agc;
  hw_gain_state_.min_gain = resp.min_gain;
  hw_gain_state_.max_gain = resp.max_gain;
  hw_gain_state_.gain_step = resp.gain_step;

  return OnDriverInfoFetched(kDriverInfoHasGainState);
}

zx_status_t AudioDriver::ProcessGetFormatsResponse(
    const audio_stream_cmd_get_formats_resp_t& resp) {
  if (!fetching_driver_info()) {
    FXL_LOG(ERROR) << "Received unsolicited get formats response.";
    return ZX_ERR_BAD_STATE;
  }

  // Is this the first response? If so, resize our format vector before proceeding.
  if (resp.first_format_range_ndx == 0) {
    format_ranges_.reserve(resp.format_range_count);
  }

  // Sanity checks
  if (resp.format_range_count == 0) {
    FXL_LOG(ERROR) << "Driver reported that it supports no format ranges!";
    return ZX_ERR_INVALID_ARGS;
  }

  if (resp.first_format_range_ndx >= resp.format_range_count) {
    FXL_LOG(ERROR) << "Bad format range index in get formats response! (index "
                   << resp.first_format_range_ndx << " should be < total "
                   << resp.format_range_count << ")";
    return ZX_ERR_INVALID_ARGS;
  }

  if (resp.first_format_range_ndx != format_ranges_.size()) {
    FXL_LOG(ERROR) << "Out of order message in get formats response! (index "
                   << resp.first_format_range_ndx << " != the expected " << format_ranges_.size()
                   << ")";
    return ZX_ERR_INVALID_ARGS;
  }

  // Add this set of formats to our list.
  uint16_t todo = std::min<uint16_t>(resp.format_range_count - resp.first_format_range_ndx,
                                     AUDIO_STREAM_CMD_GET_FORMATS_MAX_RANGES_PER_RESPONSE);
  for (uint16_t i = 0; i < todo; ++i) {
    format_ranges_.emplace_back(resp.format_ranges[i]);
  }

  // Record that we have fetched our format list. This will transition us to Unconfigured state and
  // let our owner know if we are done fetching all the initial driver info needed to operate.
  return OnDriverInfoFetched(kDriverInfoHasFormats);
}

zx_status_t AudioDriver::ProcessSetFormatResponse(const audio_stream_cmd_set_format_resp_t& resp,
                                                  zx::channel rb_channel) {
  if (state_ != State::Configuring_SettingFormat) {
    FXL_LOG(ERROR) << "Received unexpected set format response while in state "
                   << static_cast<uint32_t>(state_);
    return ZX_ERR_BAD_STATE;
  }

  if (resp.result != ZX_OK) {
    FXL_PLOG(WARNING, resp.result)
        << "Error attempting to set format: " << frames_per_sec_ << " Hz, " << channel_count_
        << "-chan, 0x" << std::hex << sample_format_;
    if (resp.result == ZX_ERR_ACCESS_DENIED) {
      FXL_LOG(ERROR) << "Another client has likely already opened this device!";
    }
    return resp.result;
  }

  // TODO(MTWN-61): Update AudioCapturers and outputs to incorporate external delay when resampling.
  external_delay_nsec_ = resp.external_delay_nsec;

  // Activate our ring buffer channel in our execution domain.
  dispatcher::Channel::ProcessHandler process_handler(
      [this](dispatcher::Channel* channel) -> zx_status_t {
        OBTAIN_EXECUTION_DOMAIN_TOKEN(token, owner_->mix_domain_);
        FXL_DCHECK(rb_channel_.get() == channel);
        return ProcessRingBufferChannelMessage();
      });

  dispatcher::Channel::ChannelClosedHandler channel_closed_handler(
      [this](const dispatcher::Channel* channel) {
        OBTAIN_EXECUTION_DOMAIN_TOKEN(token, owner_->mix_domain_);
        FXL_DCHECK(rb_channel_.get() == channel);
        ShutdownSelf("Ring buffer channel closed");
      });

  zx_status_t res;
  res = rb_channel_->Activate(std::move(rb_channel), owner_->mix_domain_,
                              std::move(process_handler), std::move(channel_closed_handler));
  if (res != ZX_OK) {
    FXL_PLOG(ERROR, res) << "Failed to activate ring buffer channel";
    return res;
  }

  // Fetch the fifo depth of the ring buffer we just received. This determines how far ahead of
  // current playout position (in bytes) the hardware may read. We need to know this number, in
  // order to size the ring buffer vmo appropriately.
  audio_rb_cmd_get_fifo_depth_req req;

  req.hdr.cmd = AUDIO_RB_CMD_GET_FIFO_DEPTH;
  req.hdr.transaction_id = TXID;

  res = rb_channel_->Write(&req, sizeof(req));
  if (res != ZX_OK) {
    FXL_LOG(ERROR) << "Failed to request ring buffer fifo depth.";
    return res;
  }

  // Things went well, proceed to the next step in the state machine.
  state_ = State::Configuring_GettingFifoDepth;
  configuration_timeout_ = zx_deadline_after(kDefaultShortCmdTimeout);
  SetupCommandTimeout();
  return ZX_OK;
}

zx_status_t AudioDriver::ProcessGetFifoDepthResponse(
    const audio_rb_cmd_get_fifo_depth_resp_t& resp) {
  if (state_ != State::Configuring_GettingFifoDepth) {
    FXL_LOG(ERROR) << "Received unexpected fifo depth response while in state "
                   << static_cast<uint32_t>(state_);
    return ZX_ERR_BAD_STATE;
  }

  if (resp.result != ZX_OK) {
    FXL_PLOG(ERROR, resp.result) << "Error when fetching ring buffer fifo depth";
    return resp.result;
  }

  fifo_depth_bytes_ = resp.fifo_depth;
  fifo_depth_frames_ = (fifo_depth_bytes_ + bytes_per_frame_ - 1) / bytes_per_frame_;

  // Figure out how many frames we need in our ring buffer.
  int64_t min_frames_64 =
      TimelineRate::Scale(min_ring_buffer_duration_, bytes_per_frame_ * frames_per_sec_, ZX_SEC(1));
  int64_t overhead = static_cast<int64_t>(fifo_depth_bytes_) + bytes_per_frame_ - 1;
  bool overflow = ((min_frames_64 == TimelineRate::kOverflow) ||
                   (min_frames_64 > (std::numeric_limits<int64_t>::max() - overhead)));

  if (!overflow) {
    min_frames_64 += overhead;
    min_frames_64 /= bytes_per_frame_;
    overflow = min_frames_64 > std::numeric_limits<uint32_t>::max();
  }

  if (overflow) {
    FXL_LOG(ERROR) << "Overflow while attempting to compute ring buffer size in frames.";
    FXL_LOG(ERROR) << "duration        : " << min_ring_buffer_duration_;
    FXL_LOG(ERROR) << "bytes per frame : " << bytes_per_frame_;
    FXL_LOG(ERROR) << "frames per sec  : " << frames_per_sec_;
    FXL_LOG(ERROR) << "fifo depth      : " << fifo_depth_bytes_;
    FXL_LOG(ERROR) << "bytes per frame : " << bytes_per_frame_;
    return ZX_ERR_INTERNAL;
  }

  // Request the ring buffer.
  audio_rb_cmd_get_buffer_req_t req;
  req.hdr.cmd = AUDIO_RB_CMD_GET_BUFFER;
  req.hdr.transaction_id = TXID;
  req.min_ring_buffer_frames = static_cast<uint32_t>(min_frames_64);
  req.notifications_per_ring = (kEnablePositionNotifications ? 2 : 0);

  zx_status_t res = rb_channel_->Write(&req, sizeof(req));
  if (res != ZX_OK) {
    ShutdownSelf("Failed to request ring buffer vmo", res);
    return res;
  }

  state_ = State::Configuring_GettingRingBuffer;
  configuration_timeout_ = zx_deadline_after(kDefaultShortCmdTimeout);
  SetupCommandTimeout();
  return ZX_OK;
}

zx_status_t AudioDriver::ProcessGetBufferResponse(const audio_rb_cmd_get_buffer_resp_t& resp,
                                                  zx::vmo rb_vmo) {
  if (state_ != State::Configuring_GettingRingBuffer) {
    FXL_LOG(ERROR) << "Received unexpected get buffer response while in state "
                   << static_cast<uint32_t>(state_);
    return ZX_ERR_BAD_STATE;
  }

  if (resp.result != ZX_OK) {
    ShutdownSelf("Error when fetching ring buffer vmo", resp.result);
    return resp.result;
  }

  {
    std::lock_guard<std::mutex> lock(ring_buffer_state_lock_);

    ring_buffer_ = DriverRingBuffer::Create(std::move(rb_vmo), bytes_per_frame_,
                                            resp.num_ring_buffer_frames, owner_->is_input());
    if (ring_buffer_ == nullptr) {
      ShutdownSelf("Failed to allocate and map driver ring buffer", ZX_ERR_NO_MEMORY);
      return ZX_ERR_NO_MEMORY;
    }
    FXL_DCHECK(!clock_mono_to_ring_pos_bytes_.invertible());

    ring_buffer_state_gen_.Next();
  }

  // We are now Configured. Let our owner know about this important milestone.
  state_ = State::Configured;
  configuration_timeout_ = ZX_TIME_INFINITE;
  SetupCommandTimeout();
  owner_->OnDriverConfigComplete();
  return ZX_OK;
}

zx_status_t AudioDriver::ProcessStartResponse(const audio_rb_cmd_start_resp_t& resp) {
  if (state_ != State::Starting) {
    FXL_LOG(ERROR) << "Received unexpected start response while in state "
                   << static_cast<uint32_t>(state_);
    return ZX_ERR_BAD_STATE;
  }

  if (resp.result != ZX_OK) {
    ShutdownSelf("Error when starting ring buffer", resp.result);
    return resp.result;
  }

  // We are almost Started, so compute the translation from clock-monotonic to ring-buffer-position
  // (in bytes), then update the ring buffer state's transformation and bump the generation counter.
  TimelineFunction func(0, resp.start_time, frames_per_sec_ * bytes_per_frame_, ZX_SEC(1));
  {
    std::lock_guard<std::mutex> lock(ring_buffer_state_lock_);
    FXL_DCHECK(!clock_mono_to_ring_pos_bytes_.invertible());
    FXL_DCHECK(ring_buffer_ != nullptr);
    clock_mono_to_ring_pos_bytes_ = func;
    ring_buffer_state_gen_.Next();
  }

  // We are now Started. Let our owner know about this important milestone.
  state_ = State::Started;
  configuration_timeout_ = ZX_TIME_INFINITE;
  SetupCommandTimeout();
  owner_->OnDriverStartComplete();
  return ZX_OK;
}

zx_status_t AudioDriver::ProcessStopResponse(const audio_rb_cmd_stop_resp_t& resp) {
  if (state_ != State::Stopping) {
    FXL_LOG(ERROR) << "Received unexpected stop response while in state "
                   << static_cast<uint32_t>(state_);
    return ZX_ERR_BAD_STATE;
  }

  if (resp.result != ZX_OK) {
    ShutdownSelf("Error when stopping ring buffer", resp.result);
    return resp.result;
  }

  // We are now stopped and in Configured state. Let our owner know about this important milestone.
  state_ = State::Configured;
  configuration_timeout_ = ZX_TIME_INFINITE;
  SetupCommandTimeout();
  owner_->OnDriverStopComplete();
  return ZX_OK;
}

// Currently we ignore driver-reported position, using the system-internal clock instead. This is
// benign and can be safely ignored. However, we did not request it, so this may indicate some other
// problem in the driver state machine. Issue a (debug-only) warning, eat the msg, and continue.
zx_status_t AudioDriver::ProcessPositionNotify(const audio_rb_position_notify_t& notify) {
  if constexpr (kLogPositionNotifications) {
    if ((kPositionNotificationInfoInterval > 0) &&
        (position_notification_count_ % kPositionNotificationInfoInterval == 0)) {
      AUD_LOG_OBJ(INFO, this) << (kEnablePositionNotifications ? "Notification"
                                                               : "Unsolicited notification")
                              << " (1/" << kPositionNotificationInfoInterval
                              << ") Time:" << notify.monotonic_time << ", Pos:" << std::setw(6)
                              << notify.ring_buffer_pos;
    } else if ((kPositionNotificationTraceInterval > 0) &&
               (position_notification_count_ % kPositionNotificationTraceInterval == 0)) {
      AUD_VLOG_OBJ(TRACE, this) << (kEnablePositionNotifications ? "Notification"
                                                                 : "Unsolicited notification")
                                << " (1/" << kPositionNotificationTraceInterval
                                << ") Time:" << notify.monotonic_time << ",  Pos:" << std::setw(6)
                                << notify.ring_buffer_pos;
    } else if ((kPositionNotificationSpewInterval > 0) &&
               (position_notification_count_ % kPositionNotificationSpewInterval == 0)) {
      AUD_VLOG_OBJ(SPEW, this) << (kEnablePositionNotifications ? "Notification"
                                                                : "Unsolicited notification")
                               << " (1/" << kPositionNotificationSpewInterval
                               << ") Time:" << notify.monotonic_time << ", Pos:" << std::setw(6)
                               << notify.ring_buffer_pos;
    }
  }
  // Even if we don't log them, keep a running count of position notifications since START.
  ++position_notification_count_;

  return ZX_OK;
}

void AudioDriver::ShutdownSelf(const char* reason, zx_status_t status) {
  if (state_ == State::Shutdown) {
    return;
  }

  if (reason != nullptr) {
    FXL_LOG(INFO) << (owner_->is_input() ? " Input" : "Output") << " shutting down '" << reason
                  << "', status:" << status;
  }

  // Our owner will call our Cleanup function within this call.
  owner_->ShutdownSelf();
  state_ = State::Shutdown;
}

void AudioDriver::SetupCommandTimeout() {
  zx_time_t timeout;

  timeout = fetch_driver_info_timeout_;
  timeout = fbl::min(timeout, configuration_timeout_);
  timeout = fbl::min(timeout, pd_enable_timeout_);

  if (last_set_timeout_ != timeout) {
    if (timeout != ZX_TIME_INFINITE) {
      cmd_timeout_->Arm(timeout);
    } else {
      cmd_timeout_->Cancel();
    }
    last_set_timeout_ = timeout;
  }
}

void AudioDriver::ReportPlugStateChange(bool plugged, zx_time_t plug_time) {
  {
    fbl::AutoLock lock(&plugged_lock_);
    plugged_ = plugged;
    plug_time_ = plug_time;
  }

  if (pd_enabled_) {
    owner_->OnDriverPlugStateChange(plugged, plug_time);
  }
}

zx_status_t AudioDriver::OnDriverInfoFetched(uint32_t info) {
  // We should never fetch the same info twice.
  if (fetched_driver_info_ & info) {
    ShutdownSelf("Duplicate driver info fetch\n", ZX_ERR_BAD_STATE);
    return ZX_ERR_BAD_STATE;
  }

  // Record the new piece of info we just fetched.
  FXL_DCHECK(state_ == State::MissingDriverInfo);
  fetched_driver_info_ |= info;

  // Have we finished fetching our initial driver info? If so, cancel the timeout, transition to
  // Unconfigured state, and let our owner know that we have finished.
  if ((fetched_driver_info_ & kDriverInfoHasAll) == kDriverInfoHasAll) {
    // We are done. Clear the fetch driver info timeout and let our owner know.
    fetch_driver_info_timeout_ = ZX_TIME_INFINITE;
    state_ = State::Unconfigured;
    SetupCommandTimeout();
    owner_->OnDriverInfoFetched();
  }

  return ZX_OK;
}

zx_status_t AudioDriver::SendSetGain(const AudioDeviceSettings::GainState& gain_state,
                                     audio_set_gain_flags_t set_flags) {
  audio_stream_cmd_set_gain_req_t req;
  req.hdr.cmd = static_cast<audio_cmd_t>(AUDIO_STREAM_CMD_SET_GAIN | AUDIO_FLAG_NO_ACK);
  req.hdr.transaction_id = TXID;

  // clang-format off
  req.flags = static_cast<audio_set_gain_flags_t>(
      set_flags |
      (gain_state.muted ? AUDIO_SGF_MUTE : 0) |
      (gain_state.agc_enabled ? AUDIO_SGF_AGC : 0));
  // clang-format on
  req.gain = gain_state.gain_db;

  return stream_channel_->Write(&req, sizeof(req));
}

}  // namespace media::audio
