// Copyright 2016 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_device_manager.h"

#include <fbl/algorithm.h>

#include <string>

#include "src/media/audio/audio_core/audio_capturer_impl.h"
#include "src/media/audio/audio_core/audio_core_impl.h"
#include "src/media/audio/audio_core/audio_link.h"
#include "src/media/audio/audio_core/audio_output.h"
#include "src/media/audio/audio_core/audio_plug_detector.h"
#include "src/media/audio/audio_core/mixer/fx_loader.h"
#include "src/media/audio/audio_core/throttle_output.h"

namespace media::audio {

AudioDeviceManager::AudioDeviceManager(AudioCoreImpl* service)
    : service_(service) {}

AudioDeviceManager::~AudioDeviceManager() {
  Shutdown();
  FXL_DCHECK(devices_.is_empty());
}

// Configure this admin singleton object to manage audio device instances.
zx_status_t AudioDeviceManager::Init() {
  // Give AudioDeviceSettings a chance to ensure its storage is happy.
  AudioDeviceSettings::Initialize();

  // Instantiate and initialize the default throttle output.
  auto throttle_output = ThrottleOutput::Create(this);
  if (throttle_output == nullptr) {
    FXL_LOG(ERROR)
        << "AudioDeviceManager failed to create default throttle output!";
    return ZX_ERR_NO_MEMORY;
  }

  zx_status_t res = throttle_output->Startup();
  if (res != ZX_OK) {
    FXL_LOG(ERROR)
        << "AudioDeviceManager failed to initialize the throttle output (res "
        << res << ")";
    throttle_output->Shutdown();
  }
  throttle_output_ = std::move(throttle_output);

  // Start monitoring for plug/unplug events of pluggable audio output devices.
  res = plug_detector_.Start(this);
  if (res != ZX_OK) {
    FXL_LOG(ERROR) << "AudioDeviceManager failed to start plug detector (res "
                   << res << ")";
    return res;
  }

  // Initialize the FxLoader and load the device effect library, if present.
  res = fx_loader_.LoadLibrary();
  if (res == ZX_ERR_ALREADY_EXISTS) {
    FXL_LOG(ERROR) << "FxLoader already started!";
  } else if (res != ZX_OK) {
    FXL_LOG(WARNING) << "FxLoader::LoadLibrary failed (res: " << res << ")";
  }

  return res;
}

// We are no longer managing audio devices, unwind everything.
void AudioDeviceManager::Shutdown() {
  // Step #1: Stop monitoring plug/unplug events and cancel any pending settings
  // commit task.  We are shutting down and no longer care about these things.
  plug_detector_.Stop();
  commit_settings_task_.Cancel();

  // Step #2: Shut down each active AudioCapturer in the system.
  while (!audio_capturers_.is_empty()) {
    auto audio_capturer = audio_capturers_.pop_front();
    audio_capturer->Shutdown();
  }

  // Step #3: Shut down each active AudioRenderer in the system.
  while (!audio_renderers_.is_empty()) {
    auto audio_renderer = audio_renderers_.pop_front();
    audio_renderer->Shutdown();
  }

  // Step #4: Shut down each device which is waiting for initialization.
  while (!devices_pending_init_.is_empty()) {
    auto device = devices_pending_init_.pop_front();
    device->Shutdown();
  }

  // Step #5: Shut down each currently active device in the system.
  while (!devices_.is_empty()) {
    auto device = devices_.pop_front();
    device->Shutdown();
    FinalizeDeviceSettings(*device);
  }

  // Step #6: Close and unload the device effect library SO.
  fx_loader_.UnloadLibrary();

  // Step #7: Shut down the throttle output.
  throttle_output_->Shutdown();
  throttle_output_ = nullptr;
}

void AudioDeviceManager::AddDeviceEnumeratorClient(
    fidl::InterfaceRequest<fuchsia::media::AudioDeviceEnumerator> request) {
  bindings_.AddBinding(this, std::move(request));
}

zx_status_t AudioDeviceManager::AddDevice(
    const fbl::RefPtr<AudioDevice>& device) {
  FXL_DCHECK(device != nullptr);
  FXL_DCHECK(device != throttle_output_);
  FXL_DCHECK(!device->InContainer());

  zx_status_t res = device->Startup();
  if (res != ZX_OK) {
    device->Shutdown();
  } else {
    devices_pending_init_.insert(std::move(device));
  }

  return res;
}

void AudioDeviceManager::ActivateDevice(
    const fbl::RefPtr<AudioDevice>& device) {
  FXL_DCHECK(device != nullptr);
  FXL_DCHECK(device != throttle_output_);

  // Have we already been removed from the pending list?  If so, the device is
  // already shutting down and there is nothing to be done.
  if (!device->InContainer()) {
    return;
  }

  // TODO(johngro): remove this when system gain is fully deprecated.
  // For now, set each output "device" gain to the "system" gain value.
  if (device->is_output()) {
    UpdateDeviceToSystemGain(device);
  }

  // Determine whether this device's persistent settings are actually unique,
  // or if they collide with another device's unique ID.
  //
  // If these settings are currently unique in the system, attempt to load the
  // persisted settings from disk, or create a new persisted settings file for
  // this device if the file is either absent or corrupt.
  //
  // If these settings are not unique, then copy the settings of the device we
  // conflict with, and use them without persistence. Currently, when device
  // instances conflict, we persist only the first instance's settings.
  DeviceSettingsSet::iterator collision;
  fbl::RefPtr<AudioDeviceSettings> settings = device->device_settings();
  FXL_DCHECK(settings != nullptr);
  if (persisted_device_settings_.insert_or_find(settings, &collision)) {
    settings->InitFromDisk();
  } else {
    const uint8_t* id = settings->uid().data;
    char id_buf[33];
    std::snprintf(
        id_buf, sizeof(id_buf),
        "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
        id[0], id[1], id[2], id[3], id[4], id[5], id[6], id[7], id[8], id[9],
        id[10], id[11], id[12], id[13], id[14], id[15]);
    FXL_LOG(WARNING)
        << "Warning: Device ID (" << device->token()
        << ") shares a persistent unique ID (" << id_buf
        << ") with another device in the system.  Initial Settings "
           "will be cloned from this device, and not persisted";
    settings->InitFromClone(*collision);
  }

  // Is this device configured to be ignored? If so, remove (don't activate) it.
  if (settings->ignore_device()) {
    RemoveDevice(device);
    return;
  }

  // Move the device over to the set of active devices.
  devices_.insert(devices_pending_init_.erase(*device));
  device->SetActivated();

  // TODO(mpuryear): Create this device instance's FxProcessor here?

  // Now that we have our gain settings (restored from disk, cloned from
  // others, or default), reapply them via the device itself.  We do this in
  // order to allow the device the chance to apply its own internal limits,
  // which may not permit the values which had been read from disk.
  //
  // TODO(johngro): Clean this pattern up, it is really awkward.  On the one
  // hand, we would really like the settings to be completely independent from
  // the devices, but on the other hand, there are limits for various settings
  // which may be need imposed by the device's capabilities.
  constexpr uint32_t kAllSetFlags =
      ::fuchsia::media::SetAudioGainFlag_GainValid |
      ::fuchsia::media::SetAudioGainFlag_MuteValid |
      ::fuchsia::media::SetAudioGainFlag_AgcValid;
  ::fuchsia::media::AudioGainInfo gain_info;
  settings->GetGainInfo(&gain_info);
  device->SetGainInfo(gain_info, kAllSetFlags);

  // TODO(mpuryear): Configure the FxProcessor based on settings, here?

  // Notify interested users of this new device. Check whether this will become
  // the new default device, so we can set 'is_default' in the notification
  // properly. Right now, "default" device is defined simply as last-plugged.
  ::fuchsia::media::AudioDeviceInfo info;
  device->GetDeviceInfo(&info);

  auto last_plugged = FindLastPlugged(device->type());
  info.is_default =
      (last_plugged && (last_plugged->token() == device->token()));

  for (auto& client : bindings_.bindings()) {
    client->events().OnDeviceAdded(info);
  }

  // Reconsider our current routing policy now that a new device has arrived.
  if (device->plugged()) {
    zx_time_t plug_time = device->plug_time();
    OnDevicePlugged(device, plug_time);
  }

  // Check whether the default device has changed; if so, update users.
  UpdateDefaultDevice(device->is_input());

  // Commit (or schedule a commit for) any dirty settings.
  CommitDirtySettings();
}

void AudioDeviceManager::RemoveDevice(const fbl::RefPtr<AudioDevice>& device) {
  FXL_DCHECK(device != nullptr);
  FXL_DCHECK(device->is_output() || (device != throttle_output_));

  device->PreventNewLinks();
  device->Unlink();

  if (device->activated()) {
    OnDeviceUnplugged(device, device->plug_time());
  }

  // TODO(mpuryear): Persist any final remaining device-effect settings?

  device->Shutdown();
  FinalizeDeviceSettings(*device);

  // TODO(mpuryear): Delete this device instance's FxProcessor here?

  if (device->InContainer()) {
    auto& device_set = device->activated() ? devices_ : devices_pending_init_;
    device_set.erase(*device);

    // If device was active: reset the default & notify clients of the removal.
    if (device->activated()) {
      UpdateDefaultDevice(device->is_input());

      for (auto& client : bindings_.bindings()) {
        client->events().OnDeviceRemoved(device->token());
      }
    }
  }
}

void AudioDeviceManager::HandlePlugStateChange(
    const fbl::RefPtr<AudioDevice>& device, bool plugged, zx_time_t plug_time) {
  FXL_DCHECK(device != nullptr);

  // Update our bookkeeping for device's plug state. If no change, we're done.
  if (!device->UpdatePlugState(plugged, plug_time)) {
    return;
  }

  if (plugged) {
    OnDevicePlugged(device, plug_time);
  } else {
    OnDeviceUnplugged(device, plug_time);
  }

  // Check whether the default device has changed; if so, update users.
  UpdateDefaultDevice(device->is_input());
}

// SetSystemGain or SetSystemMute has been called. 'changed' tells us whether
// the System Gain / Mute values actually changed. If not, only update devices
// that (because of calls to SetDeviceGain) have diverged from System settings.
//
// We update link gains in Device::SetGainInfo rather than here, so that we
// catch changes to device gain coming from SetSystemGain OR SetDeviceGain.
void AudioDeviceManager::OnSystemGain(bool changed) {
  for (auto& device : devices_) {
    if (device.is_output() && (changed || device.system_gain_dirty)) {
      UpdateDeviceToSystemGain(fbl::WrapRefPtr(&device));
      NotifyDeviceGainChanged(device);
      device.system_gain_dirty = false;
    }
    // We intentionally route System Gain only to Output devices, not Inputs.
    // If needed, we could revisit this in the future.
  }
}

void AudioDeviceManager::GetDevices(GetDevicesCallback cbk) {
  std::vector<::fuchsia::media::AudioDeviceInfo> ret;

  for (const auto& dev : devices_) {
    if (dev.token() != ZX_KOID_INVALID) {
      ::fuchsia::media::AudioDeviceInfo info;
      dev.GetDeviceInfo(&info);
      info.is_default =
          (dev.token() ==
           (dev.is_input() ? default_input_token_ : default_output_token_));
      ret.push_back(std::move(info));
    }
  }

  cbk(fidl::VectorPtr<::fuchsia::media::AudioDeviceInfo>(std::move(ret)));
}

void AudioDeviceManager::GetDeviceGain(uint64_t device_token,
                                       GetDeviceGainCallback cbk) {
  auto dev = devices_.find(device_token);

  ::fuchsia::media::AudioGainInfo info = {0};
  if (dev.IsValid()) {
    FXL_DCHECK(dev->device_settings() != nullptr);
    dev->device_settings()->GetGainInfo(&info);
    cbk(device_token, info);
  } else {
    cbk(ZX_KOID_INVALID, info);
  }
}

void AudioDeviceManager::SetDeviceGain(
    uint64_t device_token, ::fuchsia::media::AudioGainInfo gain_info,
    uint32_t set_flags) {
  auto dev = devices_.find(device_token);

  if (!dev.IsValid()) {
    return;
  }
  // SetGainInfo clamps out-of-range values (e.g. +infinity) into the device-
  // allowed gain range. NAN is undefined (signless); handle it here and exit.
  if ((set_flags & ::fuchsia::media::SetAudioGainFlag_GainValid) &&
      isnan(gain_info.gain_db)) {
    FXL_DLOG(WARNING) << "Invalid device gain " << gain_info.gain_db
                      << " dB -- making no change";
    return;
  }

  dev->system_gain_dirty = true;

  // Change the gain and then report the new settings to our clients.
  dev->SetGainInfo(gain_info, set_flags);
  NotifyDeviceGainChanged(*dev);
  CommitDirtySettings();
}

void AudioDeviceManager::GetDefaultInputDevice(
    GetDefaultInputDeviceCallback cbk) {
  cbk(default_input_token_);
}

void AudioDeviceManager::GetDefaultOutputDevice(
    GetDefaultOutputDeviceCallback cbk) {
  cbk(default_output_token_);
}

void AudioDeviceManager::SelectOutputsForAudioRenderer(
    AudioRendererImpl* audio_renderer) {
  FXL_DCHECK(audio_renderer);
  FXL_DCHECK(audio_renderer->format_info_valid());
  FXL_DCHECK(ValidateRoutingPolicy(routing_policy_));

  // TODO(johngro): Add a way to assert that we are on the message loop thread.

  // Regardless of policy, link the special throttle output to every renderer.
  LinkOutputToAudioRenderer(throttle_output_.get(), audio_renderer);

  switch (routing_policy_) {
    case fuchsia::media::AudioOutputRoutingPolicy::ALL_PLUGGED_OUTPUTS: {
      for (auto& device : devices_) {
        FXL_DCHECK(device.is_input() || device.is_output());
        if (device.is_output() && device.plugged()) {
          LinkOutputToAudioRenderer(static_cast<AudioOutput*>(&device),
                                    audio_renderer);
        }
      }
    } break;

    case fuchsia::media::AudioOutputRoutingPolicy::LAST_PLUGGED_OUTPUT: {
      fbl::RefPtr<AudioOutput> last_plugged = FindLastPluggedOutput();
      if (last_plugged != nullptr) {
        LinkOutputToAudioRenderer(last_plugged.get(), audio_renderer);
      }

    } break;
  }

  // Figure out the initial minimum clock lead time requirement.
  audio_renderer->RecomputeMinClockLeadTime();
}

void AudioDeviceManager::LinkOutputToAudioRenderer(
    AudioOutput* output, AudioRendererImpl* audio_renderer) {
  FXL_DCHECK(output);
  FXL_DCHECK(audio_renderer);

  // Do not create any links if AudioRenderer's output format is not yet set.
  // Links will be created during SelectOutputsForAudioRenderer when the
  // AudioRenderer format is finally set via AudioRendererImpl::SetStreamType.
  if (!audio_renderer->format_info_valid())
    return;

  fbl::RefPtr<AudioLink> link = AudioObject::LinkObjects(
      fbl::WrapRefPtr(audio_renderer), fbl::WrapRefPtr(output));
  // TODO(johngro): get rid of the throttle output.  See MTWN-52
  if ((link != nullptr) && (output == throttle_output_.get())) {
    FXL_DCHECK(link->source_type() == AudioLink::SourceType::Packet);
    audio_renderer->SetThrottleOutput(
        fbl::RefPtr<AudioLinkPacketSource>::Downcast(std::move(link)));
  }
}

void AudioDeviceManager::AddAudioCapturer(
    const fbl::RefPtr<AudioCapturerImpl>& audio_capturer) {
  FXL_DCHECK(audio_capturer != nullptr);
  FXL_DCHECK(!audio_capturer->InContainer());
  audio_capturers_.push_back(audio_capturer);

  fbl::RefPtr<AudioDevice> source;
  if (audio_capturer->loopback()) {
    source = FindLastPluggedOutput(true);
  } else {
    source = FindLastPluggedInput(true);
  }

  if (source != nullptr) {
    FXL_DCHECK(source->driver() != nullptr);
    auto initial_format = source->driver()->GetSourceFormat();

    if (initial_format) {
      audio_capturer->SetInitialFormat(*initial_format);
    }

    if (source->plugged()) {
      AudioObject::LinkObjects(std::move(source), std::move(audio_capturer));
    }
  }
}

void AudioDeviceManager::RemoveAudioCapturer(
    AudioCapturerImpl* audio_capturer) {
  FXL_DCHECK(audio_capturer != nullptr);
  FXL_DCHECK(audio_capturer->InContainer());
  audio_capturers_.erase(*audio_capturer);
}

void AudioDeviceManager::ScheduleMainThreadTask(fit::closure task) {
  FXL_DCHECK(service_);
  service_->ScheduleMainThreadTask(std::move(task));
}

fbl::RefPtr<AudioDevice> AudioDeviceManager::FindLastPlugged(
    AudioObject::Type type, bool allow_unplugged) {
  FXL_DCHECK((type == AudioObject::Type::Output) ||
             (type == AudioObject::Type::Input));
  AudioDevice* best = nullptr;

  // TODO(johngro): Consider tracking last-plugged times in a fbl::WAVLTree, so
  // this operation becomes O(1). N is pretty low right now, so the benefits do
  // not currently outweigh the complexity of maintaining this index.
  for (auto& obj : devices_) {
    auto& device = static_cast<AudioDevice&>(obj);
    if ((device.type() != type) ||
        device.device_settings()->disallow_auto_routing()) {
      continue;
    }

    if ((best == nullptr) || (!best->plugged() && device.plugged()) ||
        ((best->plugged() == device.plugged()) &&
         (best->plug_time() < device.plug_time()))) {
      best = &device;
    }
  }

  FXL_DCHECK((best == nullptr) || (best->type() == type));
  if (!allow_unplugged && best && !best->plugged())
    return nullptr;

  return fbl::WrapRefPtr(best);
}

// Our policy governing the routing of audio outputs has changed. For the output
// considered "preferred" (because it was most-recently-added), nothing changes;
// all other outputs will toggle on or off, depending on the policy chosen.
void AudioDeviceManager::SetRoutingPolicy(
    fuchsia::media::AudioOutputRoutingPolicy routing_policy) {
  if (!ValidateRoutingPolicy(routing_policy)) {
    FXL_LOG(ERROR) << "Out-of-range RoutingPolicy("
                   << fidl::ToUnderlying(routing_policy) << ")";
    // TODO(mpuryear): Once AudioCore has a way to know which connection made
    // this request, terminate that connection now rather than doing nothing.
    return;
  }

  if (routing_policy == routing_policy_) {
    return;
  }

  routing_policy_ = routing_policy;
  fbl::RefPtr<AudioOutput> last_plugged_output = FindLastPluggedOutput();

  // Iterate thru all of our audio devices -- only a subset are affected.
  for (auto& dev_obj : devices_) {
    // Input devices are unaffected by changes in output-routing.
    if (dev_obj.is_input()) {
      continue;
    }

    // Only plugged-in (output) devices are affected by output-routing.
    auto& output = static_cast<AudioOutput&>(dev_obj);
    if (!output.plugged()) {
      continue;
    }

    // If device is most-recently plugged, it is unaffected by this policy
    // change. Either way, it will continue to be attached to every renderer.
    FXL_DCHECK(&output != throttle_output_.get());
    if (&output == last_plugged_output.get()) {
      continue;
    }

    // We've excluded inputs, unplugged outputs and the most-recently-plugged
    // output. For each remaining output (based on the new policy), we ...
    if (routing_policy ==
        fuchsia::media::AudioOutputRoutingPolicy::LAST_PLUGGED_OUTPUT) {
      // ...disconnect it (i.e. link each AudioRenderer to Last-Plugged only),
      // or...
      dev_obj.UnlinkSources();
    } else {
      // ...attach it (i.e. link each AudioRenderer to all output devices).
      for (auto& obj : audio_renderers_) {
        FXL_DCHECK(obj.is_audio_renderer());
        auto& audio_renderer = static_cast<AudioRendererImpl&>(obj);
        LinkOutputToAudioRenderer(&output, &audio_renderer);
      }
    }
  }

  // After a route change, recalculate minimum clock lead time requirements.
  for (auto& obj : audio_renderers_) {
    FXL_DCHECK(obj.is_audio_renderer());
    auto& audio_renderer = static_cast<AudioRendererImpl&>(obj);
    audio_renderer.RecomputeMinClockLeadTime();
  }
}

void AudioDeviceManager::OnDeviceUnplugged(
    const fbl::RefPtr<AudioDevice>& device, zx_time_t plug_time) {
  FXL_DCHECK(device);
  FXL_DCHECK(ValidateRoutingPolicy(routing_policy_));

  // First, see if the device is last-plugged (before updating its plug state).
  bool was_last_plugged = FindLastPlugged(device->type()) == device;

  // Update the device's plug state. If no change, then we are done.
  if (!device->UpdatePlugState(false, plug_time)) {
    return;
  }

  // This device is newly-unplugged. Unlink all its current connections.
  device->Unlink();

  // If the device which was unplugged was not the last plugged device in the
  // system, then there has been no change in who was the last plugged device,
  // and no updates to the routing state are needed.
  if (was_last_plugged) {
    if (device->is_output()) {
      // This was an output. If applying 'last plugged output' policy, link each
      // AudioRenderer to the most-recently-plugged output (if any). Then do the
      // same for each 'loopback' AudioCapturer. Note: our current (hack)
      // routing policy for inputs is always 'last plugged'.
      FXL_DCHECK(static_cast<AudioOutput*>(device.get()) !=
                 throttle_output_.get());

      fbl::RefPtr<AudioOutput> replacement = FindLastPluggedOutput();
      if (replacement) {
        if (routing_policy_ ==
            fuchsia::media::AudioOutputRoutingPolicy::LAST_PLUGGED_OUTPUT) {
          for (auto& audio_renderer : audio_renderers_) {
            LinkOutputToAudioRenderer(replacement.get(), &audio_renderer);
          }
        }

        LinkToAudioCapturers(std::move(replacement));
      }
    } else {
      // Removed device was the most-recently-plugged input device. Determine
      // the new most-recently-plugged input (if any remain), and iterate our
      // AudioCapturer list to link each non-loopback AudioCapturer to the new
      // default.
      FXL_DCHECK(device->is_input());

      fbl::RefPtr<AudioInput> replacement = FindLastPluggedInput();
      if (replacement) {
        LinkToAudioCapturers(std::move(replacement));
      }
    }
  }

  // If removed device was an output, recompute the renderer minimum lead time.
  if (device->is_output()) {
    for (auto& audio_renderer : audio_renderers_) {
      audio_renderer.RecomputeMinClockLeadTime();
    }
  }
}

void AudioDeviceManager::OnDevicePlugged(const fbl::RefPtr<AudioDevice>& device,
                                         zx_time_t plug_time) {
  FXL_DCHECK(device);

  if (device->is_output()) {
    // This new device is an output. Inspect the renderer list and "do the right
    // thing" based on our routing policy. If last-plugged policy, change each
    // renderer to target this device (assuming it IS most-recently-plugged).
    // If all-plugged policy, just add this output to the list.
    //
    // Then, apply last-plugged policy to all capturers with loopback sources.
    // The policy mentioned above currently only pertains to Output Routing.
    fbl::RefPtr<AudioOutput> last_plugged = FindLastPluggedOutput();
    auto output = fbl::RefPtr<AudioOutput>::Downcast(std::move(device));

    FXL_DCHECK(ValidateRoutingPolicy(routing_policy_));

    bool lp_policy =
        (routing_policy_ ==
         fuchsia::media::AudioOutputRoutingPolicy::LAST_PLUGGED_OUTPUT);
    bool is_lp = (output == last_plugged);

    if (is_lp && lp_policy) {
      for (auto& unlink_tgt : devices_) {
        if (unlink_tgt.is_output() && (&unlink_tgt != output.get())) {
          unlink_tgt.UnlinkSources();
        }
      }
    }
    if (is_lp || !lp_policy) {
      for (auto& audio_renderer : audio_renderers_) {
        LinkOutputToAudioRenderer(output.get(), &audio_renderer);

        // If we are adding a new link (regardless of whether we may or may
        // not have removed old links based on the specific active policy)
        // because of an output becoming plugged in, we need to recompute the
        // minimum clock lead time requirement, and perhaps update users as to
        // what it is supposed to be.
        //
        // TODO(johngro) : In theory, this could be optimized.  We don't
        // *technically* need to go over the entire set of links and find the
        // largest minimum lead time requirement if we know (for example) that
        // we just added a link, but didn't remove any.  Right now, we are
        // sticking to the simple approach because we know that N (the total
        // number of outputs an input is linked to) is small, and maintaining
        // optimized/specialized logic for computing this value would start to
        // become a real pain as we start to get more complicated in our
        // approach to policy based routing.
        audio_renderer.RecomputeMinClockLeadTime();
      }
    }

    // 'loopback' AudioCapturers should listen to this output now
    if (is_lp) {
      LinkToAudioCapturers(std::move(output));
    }
  } else {
    FXL_DCHECK(device->is_input());

    fbl::RefPtr<AudioInput> last_plugged = FindLastPluggedInput();
    auto& input = static_cast<AudioInput&>(*device);

    // non-'loopback' AudioCapturers should listen to this input now
    if (&input == last_plugged.get()) {
      LinkToAudioCapturers(std::move(device));
    }
  }
}

// New device arrived and is the most-recently-plugged.
// * If device is an output, all 'loopback' AudioCapturers should listen to this
// output going forward (it is the default output).
// * If device is an input, then all NON-'loopback' AudioCapturers should listen
// to this input going forward (it is the default input).
void AudioDeviceManager::LinkToAudioCapturers(
    const fbl::RefPtr<AudioDevice>& device) {
  bool link_to_loopbacks = device->is_output();

  for (auto& audio_capturer : audio_capturers_) {
    if (audio_capturer.loopback() == link_to_loopbacks) {
      audio_capturer.UnlinkSources();
      AudioObject::LinkObjects(std::move(device),
                               fbl::WrapRefPtr(&audio_capturer));
    }
  }
}

void AudioDeviceManager::FinalizeDeviceSettings(const AudioDevice& device) {
  const auto& settings = device.device_settings();
  if ((settings == nullptr) || !settings->InContainer()) {
    return;
  }

  settings->Commit(true);
  persisted_device_settings_.erase(*settings);
}

void AudioDeviceManager::NotifyDeviceGainChanged(const AudioDevice& device) {
  ::fuchsia::media::AudioGainInfo info;
  FXL_DCHECK(device.device_settings() != nullptr);
  device.device_settings()->GetGainInfo(&info);

  for (auto& client : bindings_.bindings()) {
    client->events().OnDeviceGainChanged(device.token(), info);
  }
}

void AudioDeviceManager::UpdateDefaultDevice(bool input) {
  const auto new_dev = FindLastPlugged(input ? AudioObject::Type::Input
                                             : AudioObject::Type::Output);
  uint64_t new_id = new_dev ? new_dev->token() : ZX_KOID_INVALID;
  uint64_t& old_id = input ? default_input_token_ : default_output_token_;

  if (old_id != new_id) {
    for (auto& client : bindings_.bindings()) {
      client->events().OnDefaultDeviceChanged(old_id, new_id);
    }
    old_id = new_id;
  }
}

void AudioDeviceManager::UpdateDeviceToSystemGain(
    const fbl::RefPtr<AudioDevice>& device) {
  constexpr uint32_t set_flags = ::fuchsia::media::SetAudioGainFlag_GainValid |
                                 ::fuchsia::media::SetAudioGainFlag_MuteValid;
  ::fuchsia::media::AudioGainInfo set_cmd = {
      service_->system_gain_db(),
      service_->system_muted() ? ::fuchsia::media::AudioGainInfoFlag_Mute : 0u};

  FXL_DCHECK(device != nullptr);
  device->SetGainInfo(set_cmd, set_flags);
  CommitDirtySettings();
}

void AudioDeviceManager::CommitDirtySettings() {
  zx::time next = zx::time::infinite();

  for (auto& settings : persisted_device_settings_) {
    zx::time tmp = settings.Commit();
    if (tmp < next) {
      next = tmp;
    }
  }

  // If our commit task is waiting to fire, try to cancel it.
  if (commit_settings_task_.is_pending()) {
    commit_settings_task_.Cancel();
  }

  // If we need to update in the future, schedule a commit task to do so.
  if (next != zx::time::infinite()) {
    commit_settings_task_.PostForTime(service_->dispatcher(), next);
  }
}

}  // namespace media::audio
