// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "media/audio/mac/audio_manager_mac.h"

#include <limits>
#include <memory>
#include <utility>
#include <vector>

#include "base/command_line.h"
#include "base/containers/flat_set.h"
#include "base/functional/bind.h"
#include "base/mac/mac_logging.h"
#include "base/mac/mac_util.h"
#include "base/mac/scoped_cftyperef.h"
#include "base/memory/free_deleter.h"
#include "base/power_monitor/power_monitor.h"
#include "base/power_monitor/power_observer.h"
#include "base/ranges/algorithm.h"
#include "base/strings/string_split.h"
#include "base/strings/sys_string_conversions.h"
#include "base/task/bind_post_task.h"
#include "base/threading/thread_checker.h"
#include "base/time/time.h"
#include "media/audio/audio_device_description.h"
#include "media/audio/mac/audio_auhal_mac.h"
#include "media/audio/mac/audio_input_mac.h"
#include "media/audio/mac/audio_low_latency_input_mac.h"
#include "media/audio/mac/core_audio_util_mac.h"
#include "media/audio/mac/coreaudio_dispatch_override.h"
#include "media/audio/mac/scoped_audio_unit.h"
#include "media/base/audio_parameters.h"
#include "media/base/audio_timestamp_helper.h"
#include "media/base/channel_layout.h"
#include "media/base/limits.h"
#include "media/base/mac/audio_latency_mac.h"
#include "media/base/media_switches.h"
#include "third_party/abseil-cpp/absl/types/optional.h"

namespace media {

BASE_FEATURE(kMonitorOutputSampleRateChangesMac,
             "MonitorOutputSampleRateChangesMac",
             base::FEATURE_ENABLED_BY_DEFAULT);

// Maximum number of output streams that can be open simultaneously.
static const int kMaxOutputStreams = 50;

// Default sample-rate on most Apple hardware.
static const int kFallbackSampleRate = 44100;

static bool GetDeviceChannels(AudioUnit audio_unit,
                              AUElement element,
                              int* channels);

// Helper method to construct AudioObjectPropertyAddress structure given
// property selector and scope. The property element is always set to
// kAudioObjectPropertyElementMain.
static AudioObjectPropertyAddress GetAudioObjectPropertyAddress(
    AudioObjectPropertySelector selector,
    bool is_input) {
  AudioObjectPropertyScope scope = is_input ? kAudioObjectPropertyScopeInput
                                            : kAudioObjectPropertyScopeOutput;
  AudioObjectPropertyAddress property_address = {
      selector, scope, kAudioObjectPropertyElementMain};
  return property_address;
}

static const AudioObjectPropertyAddress kNoiseReductionPropertyAddress = {
    'nzca', kAudioDevicePropertyScopeInput, kAudioObjectPropertyElementMain};

// Get IO buffer size range from HAL given device id and scope.
static OSStatus GetIOBufferFrameSizeRange(AudioDeviceID device_id,
                                          bool is_input,
                                          UInt32* minimum,
                                          UInt32* maximum) {
  DCHECK(AudioManager::Get()->GetTaskRunner()->BelongsToCurrentThread());
  AudioObjectPropertyAddress address = GetAudioObjectPropertyAddress(
      kAudioDevicePropertyBufferFrameSizeRange, is_input);
  AudioValueRange range = {0, 0};
  UInt32 data_size = sizeof(AudioValueRange);
  OSStatus result = AudioObjectGetPropertyData(device_id, &address, 0, NULL,
                                               &data_size, &range);
  if (result != noErr) {
    OSSTATUS_DLOG(WARNING, result)
        << "Failed to query IO buffer size range for device: " << std::hex
        << device_id;
  } else {
    *minimum = range.mMinimum;
    *maximum = range.mMaximum;
  }
  return result;
}

static bool HasAudioHardware(AudioObjectPropertySelector selector) {
  DCHECK(AudioManager::Get()->GetTaskRunner()->BelongsToCurrentThread());
  AudioDeviceID output_device_id = kAudioObjectUnknown;
  const AudioObjectPropertyAddress property_address = {
      selector,
      kAudioObjectPropertyScopeGlobal,  // mScope
      kAudioObjectPropertyElementMain   // mElement
  };
  UInt32 output_device_id_size = static_cast<UInt32>(sizeof(output_device_id));
  OSStatus err = AudioObjectGetPropertyData(kAudioObjectSystemObject,
                                            &property_address,
                                            0,     // inQualifierDataSize
                                            NULL,  // inQualifierData
                                            &output_device_id_size,
                                            &output_device_id);
  return err == kAudioHardwareNoError &&
      output_device_id != kAudioObjectUnknown;
}

static std::string GetAudioDeviceNameFromDeviceId(AudioDeviceID device_id,
                                                  bool is_input) {
  DCHECK(AudioManager::Get()->GetTaskRunner()->BelongsToCurrentThread());
  CFStringRef device_name = nullptr;
  UInt32 data_size = sizeof(device_name);
  AudioObjectPropertyAddress property_address = GetAudioObjectPropertyAddress(
      kAudioDevicePropertyDeviceNameCFString, is_input);
  OSStatus result = AudioObjectGetPropertyData(
      device_id, &property_address, 0, nullptr, &data_size, &device_name);
  std::string device;
  if (result == noErr) {
    device = base::SysCFStringRefToUTF8(device_name);
    CFRelease(device_name);
  }
  return device;
}

// Retrieves information on audio devices, and prepends the default
// device to the list if the list is non-empty.
static void GetAudioDeviceInfo(bool is_input,
                               media::AudioDeviceNames* device_names) {
  DCHECK(AudioManager::Get()->GetTaskRunner()->BelongsToCurrentThread());
  std::vector<AudioObjectID> device_ids =
      core_audio_mac::GetAllAudioDeviceIDs();
  for (AudioObjectID device_id : device_ids) {
    const bool is_valid_for_direction =
        (is_input ? core_audio_mac::IsInputDevice(device_id)
                  : core_audio_mac::IsOutputDevice(device_id));

    if (!is_valid_for_direction)
      continue;

    absl::optional<std::string> unique_id =
        core_audio_mac::GetDeviceUniqueID(device_id);
    if (!unique_id)
      continue;

    absl::optional<std::string> label =
        core_audio_mac::GetDeviceLabel(device_id, is_input);
    if (!label)
      continue;

    // Filter out aggregate devices, e.g. those that get created by using
    // kAudioUnitSubType_VoiceProcessingIO.
    if (core_audio_mac::IsPrivateAggregateDevice(device_id))
      continue;

    device_names->emplace_back(std::move(*label), std::move(*unique_id));
  }

  if (!device_names->empty()) {
    // Prepend the default device to the list since we always want it to be
    // on the top of the list for all platforms. There is no duplicate
    // counting here since the default device has been abstracted out before.
    device_names->push_front(media::AudioDeviceName::CreateDefault());
  }
}

AudioDeviceID AudioManagerMac::GetAudioDeviceIdByUId(
    bool is_input,
    const std::string& device_id) {
  DCHECK(AudioManager::Get()->GetTaskRunner()->BelongsToCurrentThread());
  AudioObjectPropertyAddress property_address = {
      kAudioHardwarePropertyDevices, kAudioObjectPropertyScopeGlobal,
      kAudioObjectPropertyElementMain};
  AudioDeviceID audio_device_id = kAudioObjectUnknown;
  UInt32 device_size = sizeof(audio_device_id);
  OSStatus result = -1;

  if (AudioDeviceDescription::IsDefaultDevice(device_id)) {
    // Default Device.
    property_address.mSelector = is_input ?
        kAudioHardwarePropertyDefaultInputDevice :
        kAudioHardwarePropertyDefaultOutputDevice;

    result = AudioObjectGetPropertyData(kAudioObjectSystemObject,
                                        &property_address,
                                        0,
                                        0,
                                        &device_size,
                                        &audio_device_id);
  } else {
    // Non-default device.
    base::ScopedCFTypeRef<CFStringRef> uid(
        base::SysUTF8ToCFStringRef(device_id));
    AudioValueTranslation value;
    value.mInputData = &uid;
    value.mInputDataSize = sizeof(CFStringRef);
    value.mOutputData = &audio_device_id;
    value.mOutputDataSize = device_size;
    UInt32 translation_size = sizeof(AudioValueTranslation);

    property_address.mSelector = kAudioHardwarePropertyDeviceForUID;
    result = AudioObjectGetPropertyData(kAudioObjectSystemObject,
                                        &property_address,
                                        0,
                                        0,
                                        &translation_size,
                                        &value);
  }

  if (result) {
    OSSTATUS_DLOG(WARNING, result) << "Unable to query device " << device_id
                                   << " for AudioDeviceID";
  }

  return audio_device_id;
}

static bool GetDefaultDevice(AudioDeviceID* device, bool input) {
  DCHECK(AudioManager::Get()->GetTaskRunner()->BelongsToCurrentThread());
  CHECK(device);

  // Obtain the AudioDeviceID of the default input or output AudioDevice.
  AudioObjectPropertyAddress pa;
  pa.mSelector = input ? kAudioHardwarePropertyDefaultInputDevice
                       : kAudioHardwarePropertyDefaultOutputDevice;
  pa.mScope = kAudioObjectPropertyScopeGlobal;
  pa.mElement = kAudioObjectPropertyElementMain;

  UInt32 size = sizeof(*device);
  OSStatus result = AudioObjectGetPropertyData(kAudioObjectSystemObject, &pa, 0,
                                               0, &size, device);
  if ((result != kAudioHardwareNoError) || (*device == kAudioDeviceUnknown)) {
    DLOG(ERROR) << "Error getting default AudioDevice.";
    return false;
  }
  return true;
}

bool AudioManagerMac::GetDefaultOutputDevice(AudioDeviceID* device) {
  return GetDefaultDevice(device, false);
}

// Returns the total number of channels on a device; regardless of what the
// device's preferred rendering layout looks like. Should only be used for the
// channel count when a device has more than kMaxConcurrentChannels.
static bool GetDeviceTotalChannelCount(AudioDeviceID device,
                                       AudioObjectPropertyScope scope,
                                       int* channels) {
  DCHECK(AudioManager::Get()->GetTaskRunner()->BelongsToCurrentThread());
  CHECK(channels);

  // Get the stream configuration of the device in an AudioBufferList (with the
  // buffer pointers set to nullptr) which describes the list of streams and the
  // number of channels in each stream.
  AudioObjectPropertyAddress pa = {kAudioDevicePropertyStreamConfiguration,
                                   scope, kAudioObjectPropertyElementMain};

  UInt32 size;
  OSStatus result = AudioObjectGetPropertyDataSize(device, &pa, 0, 0, &size);
  if (result != noErr || !size)
    return false;

  std::unique_ptr<uint8_t[]> list_storage(new uint8_t[size]);
  AudioBufferList* buffer_list =
      reinterpret_cast<AudioBufferList*>(list_storage.get());

  result = AudioObjectGetPropertyData(device, &pa, 0, 0, &size, buffer_list);
  if (result != noErr)
    return false;

  // Determine number of channels based on the AudioBufferList.
  // |mNumberBuffers] is the  number of interleaved channels in the buffer.
  // If the number is 1, the buffer is noninterleaved.
  *channels = 0;
  for (UInt32 i = 0; i < buffer_list->mNumberBuffers; ++i)
    *channels += buffer_list->mBuffers[i].mNumberChannels;

  DVLOG(1) << __FUNCTION__
           << (scope == kAudioDevicePropertyScopeInput ? " Input" : " Output")
           << " total channels: " << *channels;
  return true;
}

// Returns the channel count from the |audio_unit|'s stream format for input
// scope / input element or output scope / output element.
static bool GetAudioUnitStreamFormatChannelCount(AudioUnit audio_unit,
                                                 AUElement element,
                                                 int* channels) {
  AudioStreamBasicDescription stream_format;
  UInt32 size = sizeof(stream_format);
  OSStatus result =
      AudioUnitGetProperty(audio_unit, kAudioUnitProperty_StreamFormat,
                           element == AUElement::OUTPUT ? kAudioUnitScope_Output
                                                        : kAudioUnitScope_Input,
                           element, &stream_format, &size);
  if (result != noErr) {
    OSSTATUS_DLOG(ERROR, result) << "Failed to get AudioUnit stream format.";
    return false;
  }

  *channels = stream_format.mChannelsPerFrame;
  return true;
}

// Returns the channel layout for |device| as provided by the AudioUnit attached
// to that device matching |element|. Returns true if the count could be pulled
// from the AudioUnit successfully, false otherwise.
static bool GetDeviceChannels(AudioDeviceID device,
                              AUElement element,
                              int* channels) {
  DCHECK(AudioManager::Get()->GetTaskRunner()->BelongsToCurrentThread());
  CHECK(channels);

  // For input, get the channel count directly from the AudioUnit's stream
  // format.
  // TODO(https://crbug.com/796163): Find out if we can use channel layout on
  // input element, or confirm that we can't.
  if (element == AUElement::INPUT) {
    ScopedAudioUnit au(device, element);
    if (!au.is_valid())
      return false;

    if (!GetAudioUnitStreamFormatChannelCount(au.audio_unit(), element,
                                              channels)) {
      return false;
    }

    DVLOG(2) << __FUNCTION__ << " Input channels: " << *channels;
    return true;
  }

  // For output, use the channel layout to determine channel count.
  DCHECK(element == AUElement::OUTPUT);

  // If the device has more channels than possible for layouts to express, use
  // the total count of channels on the device; as of this writing, macOS will
  // only return up to 8 channels in any layout. To allow WebAudio to work with
  // > 8 channel devices, we must use the total channel count instead of the
  // channel count of the preferred layout.
  int total_channel_count = 0;
  if (GetDeviceTotalChannelCount(device,
                                 element == AUElement::OUTPUT
                                     ? kAudioDevicePropertyScopeOutput
                                     : kAudioDevicePropertyScopeInput,
                                 &total_channel_count) &&
      total_channel_count > kMaxConcurrentChannels) {
    *channels = total_channel_count;
    return true;
  }

  ScopedAudioUnit au(device, element);
  if (!au.is_valid())
    return false;

  return GetDeviceChannels(au.audio_unit(), element, channels);
}

static bool GetDeviceChannels(AudioUnit audio_unit,
                              AUElement element,
                              int* channels) {
  // Attempt to retrieve the channel layout from the AudioUnit.
  //
  // Note: We don't use kAudioDevicePropertyPreferredChannelLayout on the device
  // because it is not available on all devices.
  UInt32 size;
  Boolean writable;
  OSStatus result = AudioUnitGetPropertyInfo(
      audio_unit, kAudioUnitProperty_AudioChannelLayout, kAudioUnitScope_Output,
      element, &size, &writable);
  if (result != noErr) {
    OSSTATUS_DLOG(ERROR, result)
        << "Failed to get property info for AudioUnit channel layout.";
  }

  std::unique_ptr<uint8_t[]> layout_storage(new uint8_t[size]);
  AudioChannelLayout* layout =
      reinterpret_cast<AudioChannelLayout*>(layout_storage.get());

  result =
      AudioUnitGetProperty(audio_unit, kAudioUnitProperty_AudioChannelLayout,
                           kAudioUnitScope_Output, element, layout, &size);
  if (result != noErr) {
    OSSTATUS_LOG(ERROR, result) << "Failed to get AudioUnit channel layout.";
    return false;
  }

  // We don't want to have to know about all channel layout tags, so force OSX
  // to give us the channel descriptions from the bitmap or tag if necessary.
  const AudioChannelLayoutTag tag = layout->mChannelLayoutTag;
  if (tag != kAudioChannelLayoutTag_UseChannelDescriptions) {
    const bool is_bitmap = tag == kAudioChannelLayoutTag_UseChannelBitmap;
    const AudioFormatPropertyID fa =
        is_bitmap ? kAudioFormatProperty_ChannelLayoutForBitmap
                  : kAudioFormatProperty_ChannelLayoutForTag;

    if (is_bitmap) {
      result = AudioFormatGetPropertyInfo(fa, sizeof(UInt32),
                                          &layout->mChannelBitmap, &size);
    } else {
      result = AudioFormatGetPropertyInfo(fa, sizeof(AudioChannelLayoutTag),
                                          &tag, &size);
    }
    if (result != noErr || !size) {
      OSSTATUS_DLOG(ERROR, result)
          << "Failed to get AudioFormat property info, size=" << size;
      return false;
    }

    layout_storage.reset(new uint8_t[size]);
    layout = reinterpret_cast<AudioChannelLayout*>(layout_storage.get());
    if (is_bitmap) {
      result = AudioFormatGetProperty(fa, sizeof(UInt32),
                                      &layout->mChannelBitmap, &size, layout);
    } else {
      result = AudioFormatGetProperty(fa, sizeof(AudioChannelLayoutTag), &tag,
                                      &size, layout);
    }
    if (result != noErr) {
      OSSTATUS_DLOG(ERROR, result) << "Failed to get AudioFormat property.";
      return false;
    }
  }

  // There is no channel info for stereo, assume so for mono as well.
  if (layout->mNumberChannelDescriptions <= 2) {
    *channels = layout->mNumberChannelDescriptions;
  } else {
    *channels = 0;
    for (UInt32 i = 0; i < layout->mNumberChannelDescriptions; ++i) {
      if (layout->mChannelDescriptions[i].mChannelLabel !=
          kAudioChannelLabel_Unknown)
        (*channels)++;
    }
  }

  DVLOG(2) << __FUNCTION__ << " Output channels: " << *channels;
  return true;
}

class AudioManagerMac::AudioPowerObserver : public base::PowerSuspendObserver {
 public:
  AudioPowerObserver()
      : is_suspending_(false),
        is_monitoring_(base::PowerMonitor::IsInitialized()),
        num_resume_notifications_(0) {
    // The PowerMonitor requires significant setup (a CFRunLoop and preallocated
    // IO ports) so it's not available under unit tests.  See the OSX impl of
    // base::PowerMonitorDeviceSource for more details.
    if (!is_monitoring_)
      return;
    base::PowerMonitor::AddPowerSuspendObserver(this);
  }

  AudioPowerObserver(const AudioPowerObserver&) = delete;
  AudioPowerObserver& operator=(const AudioPowerObserver&) = delete;

  ~AudioPowerObserver() override {
    DCHECK(thread_checker_.CalledOnValidThread());
    if (!is_monitoring_)
      return;
    base::PowerMonitor::RemovePowerSuspendObserver(this);
  }

  bool IsSuspending() const {
    DCHECK(thread_checker_.CalledOnValidThread());
    return is_suspending_;
  }

  size_t num_resume_notifications() const { return num_resume_notifications_; }

  bool ShouldDeferStreamStart() const {
    DCHECK(thread_checker_.CalledOnValidThread());
    // Start() should be deferred if the system is in the middle of a suspend or
    // has recently started the process of resuming.
    return is_suspending_ || base::TimeTicks::Now() < earliest_start_time_;
  }

  bool IsOnBatteryPower() const {
    DCHECK(thread_checker_.CalledOnValidThread());
    return base::PowerMonitor::IsOnBatteryPower();
  }

 private:
  void OnSuspend() override {
    DCHECK(thread_checker_.CalledOnValidThread());
    DVLOG(1) << "AudioPowerObserver::" << __FUNCTION__;
    is_suspending_ = true;
  }

  void OnResume() override {
    DCHECK(thread_checker_.CalledOnValidThread());
    DVLOG(1) << "AudioPowerObserver::" << __FUNCTION__;
    ++num_resume_notifications_;
    is_suspending_ = false;
    earliest_start_time_ =
        base::TimeTicks::Now() + base::Seconds(kStartDelayInSecsForPowerEvents);
  }

  bool is_suspending_;
  const bool is_monitoring_;
  base::TimeTicks earliest_start_time_;
  base::ThreadChecker thread_checker_;
  size_t num_resume_notifications_;
};

AudioManagerMac::AudioManagerMac(std::unique_ptr<AudioThread> audio_thread,
                                 AudioLogFactory* audio_log_factory)
    : AudioManagerBase(std::move(audio_thread), audio_log_factory),
      current_sample_rate_(0),
      current_output_device_(kAudioDeviceUnknown),
      in_shutdown_(false),
      weak_ptr_factory_(this) {
  SetMaxOutputStreamsAllowed(kMaxOutputStreams);

  // PostTask since AudioManager creation may be on the startup path and this
  // may be slow.
  GetTaskRunner()->PostTask(
      FROM_HERE, base::BindOnce(&AudioManagerMac::InitializeOnAudioThread,
                                weak_ptr_factory_.GetWeakPtr()));
}

AudioManagerMac::~AudioManagerMac() = default;

void AudioManagerMac::ShutdownOnAudioThread() {
  // We are now in shutdown mode. This flag disables MaybeChangeBufferSize()
  // and IncreaseIOBufferSizeIfPossible() which both touches native Core Audio
  // APIs and they can fail and disrupt tests during shutdown.
  in_shutdown_ = true;

  // Even if tasks to close the streams are enqueued, they would not run
  // leading to CHECKs getting hit in the destructor about open streams. Close
  // them explicitly here. crbug.com/608049.
  CloseAllInputStreams();
  CHECK(basic_input_streams_.empty());
  CHECK(low_latency_input_streams_.empty());

  // Deinitialize power observer on audio thread, since it's initialized on the
  // audio thread. Typically, constructor/destructor and
  // InitializeOnAudioThread/ShutdownOnAudioThread are all run on the main
  // thread, but this might not be true in testing.
  power_observer_.reset();

  AudioManagerBase::ShutdownOnAudioThread();
}

std::vector<AudioObjectID> AudioManagerMac::GetAllAudioDeviceIDs() {
  DCHECK(AudioManager::Get()->GetTaskRunner()->BelongsToCurrentThread());
  return core_audio_mac::GetAllAudioDeviceIDs();
}

std::vector<AudioObjectID> AudioManagerMac::GetRelatedNonBluetoothDeviceIDs(
    AudioObjectID device_id) {
  DCHECK(AudioManager::Get()->GetTaskRunner()->BelongsToCurrentThread());
  return core_audio_mac::GetRelatedDeviceIDs(device_id);
}

std::vector<AudioObjectID> AudioManagerMac::GetRelatedBluetoothDeviceIDs(
    AudioObjectID device_id) {
  DCHECK(AudioManager::Get()->GetTaskRunner()->BelongsToCurrentThread());
  std::vector<AudioObjectID> result_ids;

  // Get unique ID of input device which would be used to match with unique IDs
  // of all other devices.
  absl::optional<std::string> input_unique_id = GetDeviceUniqueID(device_id);
  if (!input_unique_id) {
    return result_ids;
  }

  // Get the base name from the unique ID by removing :input/:output from it.
  // A bluetooth audio input device uniqueID is of the format
  // "F3-A2-14-A9-1D-F8:input", while the corresponding output device uniqueID
  // is of the format "F3-A2-14-A9-1D-F8:output".
  std::vector<std::string> trimmed_input_vector =
      SplitString(input_unique_id.value(), ":", base::TRIM_WHITESPACE,
                  base::SPLIT_WANT_NONEMPTY);
  if (trimmed_input_vector.empty()) {
    return result_ids;
  }
  std::string& trimmed_input_unique_id = trimmed_input_vector[0];

  // Iterate through all device IDs and match the unique IDs base to find the
  // related devices.
  for (const auto& id : GetAllAudioDeviceIDs()) {
    absl::optional<std::string> unique_id = GetDeviceUniqueID(id);
    if (!unique_id) {
      continue;
    }

    std::vector<std::string> trimmed_vector =
        SplitString(unique_id.value(), ":", base::TRIM_WHITESPACE,
                    base::SPLIT_WANT_NONEMPTY);
    if (trimmed_vector.empty()) {
      continue;
    }

    std::string& trimmed_id = trimmed_vector[0];
    if (trimmed_id == trimmed_input_unique_id) {
      result_ids.push_back(id);
    }
  }
  return result_ids;
}

std::vector<AudioObjectID> AudioManagerMac::GetRelatedDeviceIDs(
    AudioObjectID device_id) {
  DCHECK(AudioManager::Get()->GetTaskRunner()->BelongsToCurrentThread());
  absl::optional<uint32_t> transport_type = GetDeviceTransportType(device_id);
  if (transport_type && *transport_type == kAudioDeviceTransportTypeBluetooth) {
    return GetRelatedBluetoothDeviceIDs(device_id);
  }
  return GetRelatedNonBluetoothDeviceIDs(device_id);
}

absl::optional<std::string> AudioManagerMac::GetDeviceUniqueID(
    AudioObjectID device_id) {
  DCHECK(AudioManager::Get()->GetTaskRunner()->BelongsToCurrentThread());
  return core_audio_mac::GetDeviceUniqueID(device_id);
}

absl::optional<uint32_t> AudioManagerMac::GetDeviceTransportType(
    AudioObjectID device_id) {
  DCHECK(AudioManager::Get()->GetTaskRunner()->BelongsToCurrentThread());
  return core_audio_mac::GetDeviceTransportType(device_id);
}

bool AudioManagerMac::HasAudioOutputDevices() {
  return HasAudioHardware(kAudioHardwarePropertyDefaultOutputDevice);
}

bool AudioManagerMac::HasAudioInputDevices() {
  return HasAudioHardware(kAudioHardwarePropertyDefaultInputDevice);
}

// static
int AudioManagerMac::HardwareSampleRateForDevice(AudioDeviceID device_id) {
  DCHECK(AudioManager::Get()->GetTaskRunner()->BelongsToCurrentThread());
  Float64 nominal_sample_rate;
  UInt32 info_size = sizeof(nominal_sample_rate);

  static const AudioObjectPropertyAddress kNominalSampleRateAddress = {
      kAudioDevicePropertyNominalSampleRate, kAudioObjectPropertyScopeGlobal,
      kAudioObjectPropertyElementMain};
  OSStatus result = AudioObjectGetPropertyData(device_id,
                                               &kNominalSampleRateAddress,
                                               0,
                                               0,
                                               &info_size,
                                               &nominal_sample_rate);
  if (result != noErr) {
    OSSTATUS_DLOG(WARNING, result)
        << "Could not get default sample rate for device: " << device_id;
    return 0;
  }

  return static_cast<int>(nominal_sample_rate);
}

// static
int AudioManagerMac::HardwareSampleRate() {
  // Determine the default output device's sample-rate.
  AudioDeviceID device_id = kAudioObjectUnknown;
  if (!GetDefaultOutputDevice(&device_id))
    return kFallbackSampleRate;

  return HardwareSampleRateForDevice(device_id);
}

void AudioManagerMac::GetAudioInputDeviceNames(
    media::AudioDeviceNames* device_names) {
  DCHECK(device_names->empty());
  GetAudioDeviceInfo(true, device_names);
}

void AudioManagerMac::GetAudioOutputDeviceNames(
    media::AudioDeviceNames* device_names) {
  DCHECK(device_names->empty());
  GetAudioDeviceInfo(false, device_names);
}

AudioParameters AudioManagerMac::GetInputStreamParameters(
    const std::string& device_id) {
  DCHECK(GetTaskRunner()->BelongsToCurrentThread());
  AudioDeviceID device = GetAudioDeviceIdByUId(true, device_id);
  if (device == kAudioObjectUnknown) {
    DLOG(ERROR) << "Invalid device " << device_id;
    return AudioParameters(AudioParameters::AUDIO_PCM_LOW_LATENCY,
                           ChannelLayoutConfig::Stereo(), kFallbackSampleRate,
                           ChooseBufferSize(true, kFallbackSampleRate));
  }

  int channels = 0;
  ChannelLayoutConfig channel_layout_config = ChannelLayoutConfig::Stereo();
  if (GetDeviceChannels(device, AUElement::INPUT, &channels) && channels <= 2) {
    channel_layout_config = ChannelLayoutConfig::Guess(channels);
  } else {
    DLOG(ERROR) << "Failed to get the device channels, use stereo as default "
                << "for device " << device_id;
  }

  int sample_rate = HardwareSampleRateForDevice(device);
  if (!sample_rate)
    sample_rate = kFallbackSampleRate;

  // Due to the sharing of the input and output buffer sizes, we need to choose
  // the input buffer size based on the output sample rate.  See
  // http://crbug.com/154352.
  const int buffer_size = ChooseBufferSize(true, sample_rate);

  // TODO(grunell): query the native channel layout for the specific device.
  AudioParameters params(
      AudioParameters::AUDIO_PCM_LOW_LATENCY, channel_layout_config,
      sample_rate, buffer_size,
      AudioParameters::HardwareCapabilities(
          GetMinAudioBufferSizeMacOS(limits::kMinAudioBufferSize, sample_rate),
          limits::kMaxAudioBufferSize));

  if (DeviceSupportsAmbientNoiseReduction(device)) {
    params.set_effects(AudioParameters::NOISE_SUPPRESSION);
  }

  // VoiceProcessingIO cannot be used on aggregate devices, since it creates an
  // aggregate device itself.  It also only runs in mono, but we allow upmixing
  // to stereo since we can't claim a device works either in stereo without echo
  // cancellation or mono with echo cancellation.
  if ((params.channel_layout() == CHANNEL_LAYOUT_MONO ||
       params.channel_layout() == CHANNEL_LAYOUT_STEREO) &&
      GetDeviceTransportType(device) != kAudioDeviceTransportTypeAggregate) {
    params.set_effects(params.effects() |
                       AudioParameters::EXPERIMENTAL_ECHO_CANCELLER);
  }

  return params;
}

std::string AudioManagerMac::GetAssociatedOutputDeviceID(
    const std::string& input_device_unique_id) {
  DCHECK(GetTaskRunner()->BelongsToCurrentThread());
  AudioObjectID input_device_id =
      GetAudioDeviceIdByUId(true, input_device_unique_id);
  if (input_device_id == kAudioObjectUnknown)
    return std::string();

  std::vector<AudioObjectID> related_device_ids =
      GetRelatedDeviceIDs(input_device_id);

  // Defined as a set as device IDs might be duplicated in
  // GetRelatedDeviceIDs().
  base::flat_set<AudioObjectID> related_output_device_ids;
  for (AudioObjectID device_id : related_device_ids) {
    if (core_audio_mac::GetNumStreams(device_id, false /* is_input */) > 0)
      related_output_device_ids.insert(device_id);
  }

  // Return the device ID if there is only one associated device.
  // When there are multiple associated devices, we currently do not have a way
  // to detect if a device (e.g. a digital output device) is actually connected
  // to an endpoint, so we cannot randomly pick a device.
  if (related_output_device_ids.size() == 1) {
    absl::optional<std::string> related_unique_id =
        GetDeviceUniqueID(*related_output_device_ids.begin());
    if (related_unique_id)
      return std::move(*related_unique_id);
  }

  return std::string();
}

const char* AudioManagerMac::GetName() {
  return "Mac";
}

AudioOutputStream* AudioManagerMac::MakeLinearOutputStream(
    const AudioParameters& params,
    const LogCallback& log_callback) {
  DCHECK(GetTaskRunner()->BelongsToCurrentThread());
  return MakeLowLatencyOutputStream(params, std::string(), log_callback);
}

AudioOutputStream* AudioManagerMac::MakeLowLatencyOutputStream(
    const AudioParameters& params,
    const std::string& device_id,
    const LogCallback& log_callback) {
  DCHECK(GetTaskRunner()->BelongsToCurrentThread());
  bool device_listener_first_init = false;
  // Lazily create the audio device listener on the first stream creation,
  // even if getting an audio device fails. Otherwise, if we have 0 audio
  // devices, the listener will never be initialized, and new valid devices
  // will never be detected.
  if (!output_device_listener_) {
    // NOTE: Use base::BindPostTaskToCurrentDefault() to ensure the callback is
    // always PostTask'd even if OSX calls us on the right thread.  Some
    // CoreAudio drivers will fire the callbacks during stream creation, leading
    // to re-entrancy issues otherwise.  See http://crbug.com/349604
    output_device_listener_ = AudioDeviceListenerMac::Create(
        base::BindPostTaskToCurrentDefault(base::BindRepeating(
            &AudioManagerMac::HandleDeviceChanges, base::Unretained(this))),
        /*monitor_sample_rate_changes=*/
        base::FeatureList::IsEnabled(kMonitorOutputSampleRateChangesMac),
        /*monitor_default_input=*/false,
        /*monitor_addition_removal=*/false,
        /*monitor_sources=*/false);
    device_listener_first_init = true;
  }

  AudioDeviceID device = GetAudioDeviceIdByUId(false, device_id);
  if (device == kAudioObjectUnknown) {
    DLOG(ERROR) << "Failed to open output device: " << device_id;
    return NULL;
  }

  // Only set the device and sample rate if we just initialized the device
  // listener.
  if (device_listener_first_init) {
    // Only set the current output device for the default device.
    if (AudioDeviceDescription::IsDefaultDevice(device_id))
      current_output_device_ = device;
    // Just use the current sample rate since we don't allow non-native sample
    // rates on OSX.
    current_sample_rate_ = params.sample_rate();
  }

  AUHALStream* stream = new AUHALStream(this, params, device, log_callback);
  output_streams_.push_back(stream);
  return stream;
}

std::string AudioManagerMac::GetDefaultOutputDeviceID() {
  DCHECK(GetTaskRunner()->BelongsToCurrentThread());
  return GetDefaultDeviceID(false /* is_input */);
}

std::string AudioManagerMac::GetDefaultInputDeviceID() {
  DCHECK(GetTaskRunner()->BelongsToCurrentThread());
  return GetDefaultDeviceID(true /* is_input */);
}

std::string AudioManagerMac::GetDefaultDeviceID(bool is_input) {
  DCHECK(GetTaskRunner()->BelongsToCurrentThread());
  AudioDeviceID device_id = kAudioObjectUnknown;
  if (!GetDefaultDevice(&device_id, is_input))
    return std::string();

  const AudioObjectPropertyAddress property_address = {
      kAudioDevicePropertyDeviceUID, kAudioObjectPropertyScopeGlobal,
      kAudioObjectPropertyElementMain};
  CFStringRef device_uid = NULL;
  UInt32 size = sizeof(device_uid);
  OSStatus status = AudioObjectGetPropertyData(device_id,
                                               &property_address,
                                               0,
                                               NULL,
                                               &size,
                                               &device_uid);
  if (status != kAudioHardwareNoError || !device_uid)
    return std::string();

  std::string ret(base::SysCFStringRefToUTF8(device_uid));
  CFRelease(device_uid);

  return ret;
}

AudioInputStream* AudioManagerMac::MakeLinearInputStream(
    const AudioParameters& params,
    const std::string& device_id,
    const LogCallback& log_callback) {
  DCHECK(GetTaskRunner()->BelongsToCurrentThread());
  DCHECK_EQ(AudioParameters::AUDIO_PCM_LINEAR, params.format());
  AudioInputStream* stream = new PCMQueueInAudioInputStream(this, params);
  basic_input_streams_.push_back(stream);
  return stream;
}

AudioInputStream* AudioManagerMac::MakeLowLatencyInputStream(
    const AudioParameters& params,
    const std::string& device_id,
    const LogCallback& log_callback) {
  DCHECK(GetTaskRunner()->BelongsToCurrentThread());
  DCHECK_EQ(AudioParameters::AUDIO_PCM_LOW_LATENCY, params.format());
  // Gets the AudioDeviceID that refers to the AudioInputDevice with the device
  // unique id. This AudioDeviceID is used to set the device for Audio Unit.
  AudioDeviceID audio_device_id = GetAudioDeviceIdByUId(true, device_id);
  if (audio_device_id == kAudioObjectUnknown) {
    return nullptr;
  }

  VoiceProcessingMode voice_processing_mode =
      (params.effects() & AudioParameters::ECHO_CANCELLER)
          ? VoiceProcessingMode::kEnabled
          : VoiceProcessingMode::kDisabled;

  auto* stream = new AUAudioInputStream(this, params, audio_device_id,
                                        log_callback, voice_processing_mode);
  low_latency_input_streams_.push_back(stream);
  return stream;
}

AudioParameters AudioManagerMac::GetPreferredOutputStreamParameters(
    const std::string& output_device_id,
    const AudioParameters& input_params) {
  DCHECK(GetTaskRunner()->BelongsToCurrentThread());
  const AudioDeviceID device = GetAudioDeviceIdByUId(false, output_device_id);
  if (device == kAudioObjectUnknown) {
    DLOG(ERROR) << "Invalid output device " << output_device_id;
    return input_params.IsValid()
               ? input_params
               : AudioParameters(AudioParameters::AUDIO_PCM_LOW_LATENCY,
                                 ChannelLayoutConfig::Stereo(),
                                 kFallbackSampleRate,
                                 ChooseBufferSize(false, kFallbackSampleRate));
  }

  const bool has_valid_input_params = input_params.IsValid();
  const int hardware_sample_rate = HardwareSampleRateForDevice(device);

  // Allow pass through buffer sizes.  If concurrent input and output streams
  // exist, they will use the smallest buffer size amongst them.  As such, each
  // stream must be able to FIFO requests appropriately when this happens.
  int buffer_size;
  if (has_valid_input_params) {
    // Ensure the latency asked for is maintained, even if the sample rate is
    // changed here.
    const int scaled_buffer_size = input_params.frames_per_buffer() *
                                   hardware_sample_rate /
                                   input_params.sample_rate();
    // If passed in via the input_params we allow buffer sizes to go as
    // low as the the kMinAudioBufferSize, ignoring what
    // ChooseBufferSize() normally returns.
    buffer_size =
        std::min(static_cast<int>(limits::kMaxAudioBufferSize),
                 std::max(scaled_buffer_size,
                          static_cast<int>(limits::kMinAudioBufferSize)));
  } else {
    buffer_size = ChooseBufferSize(false, hardware_sample_rate);
  }

  int hardware_channels;
  if (!GetDeviceChannels(device, AUElement::OUTPUT, &hardware_channels))
    hardware_channels = 2;

  // Use the input channel count and channel layout if possible.  Let OSX take
  // care of remapping the channels; this lets user specified channel layouts
  // work correctly.
  int output_channels = input_params.channels();
  ChannelLayout channel_layout = input_params.channel_layout();
  if (!has_valid_input_params || output_channels > hardware_channels) {
    output_channels = hardware_channels;
    channel_layout = GuessChannelLayout(output_channels);
    if (channel_layout == CHANNEL_LAYOUT_UNSUPPORTED)
      channel_layout = CHANNEL_LAYOUT_DISCRETE;
  }

  AudioParameters params(
      AudioParameters::AUDIO_PCM_LOW_LATENCY, {channel_layout, output_channels},
      hardware_sample_rate, buffer_size,
      AudioParameters::HardwareCapabilities(
          GetMinAudioBufferSizeMacOS(limits::kMinAudioBufferSize,
                                     hardware_sample_rate),
          limits::kMaxAudioBufferSize));
  return params;
}

void AudioManagerMac::InitializeOnAudioThread() {
  DCHECK(GetTaskRunner()->BelongsToCurrentThread());
  InitializeCoreAudioDispatchOverride();
  power_observer_ = std::make_unique<AudioPowerObserver>();
}

void AudioManagerMac::HandleDeviceChanges() {
  DCHECK(GetTaskRunner()->BelongsToCurrentThread());
  const int new_sample_rate = HardwareSampleRate();
  AudioDeviceID new_output_device;
  GetDefaultOutputDevice(&new_output_device);

  if (current_sample_rate_ == new_sample_rate &&
      current_output_device_ == new_output_device) {
    return;
  }

  DVLOG(1) << __func__
           << " device changed: " << (current_sample_rate_ != new_sample_rate)
           << " current sample rate: " << current_sample_rate_
           << " new sample rate: " << new_sample_rate;
  current_sample_rate_ = new_sample_rate;
  current_output_device_ = new_output_device;
  NotifyAllOutputDeviceChangeListeners();
}

int AudioManagerMac::ChooseBufferSize(bool is_input, int sample_rate) {
  // kMinAudioBufferSize is too small for the output side because
  // CoreAudio can get into under-run if the renderer fails delivering data
  // to the browser within the allowed time by the OS. The workaround is to
  // use 256 samples as the default output buffer size for sample rates
  // smaller than 96KHz.
  // TODO(xians): Remove this workaround after WebAudio supports user defined
  // buffer size.  See https://github.com/WebAudio/web-audio-api/issues/348
  // for details.
  int buffer_size =
      is_input ? limits::kMinAudioBufferSize : 2 * limits::kMinAudioBufferSize;
  const int user_buffer_size = GetUserBufferSize();
  buffer_size = user_buffer_size
                    ? user_buffer_size
                    : GetMinAudioBufferSizeMacOS(buffer_size, sample_rate);
  return buffer_size;
}

bool AudioManagerMac::IsSuspending() const {
  DCHECK(GetTaskRunner()->BelongsToCurrentThread());
  return power_observer_->IsSuspending();
}

bool AudioManagerMac::ShouldDeferStreamStart() const {
  DCHECK(GetTaskRunner()->BelongsToCurrentThread());
  return power_observer_->ShouldDeferStreamStart();
}
base::TimeDelta AudioManagerMac::GetDeferStreamStartTimeout() const {
  if (ShouldDeferStreamStart()) {
    return base::Seconds(AudioManagerMac::kStartDelayInSecsForPowerEvents);
  }
  return base::TimeDelta();
}

base::SingleThreadTaskRunner* AudioManagerMac::GetTaskRunner() const {
  return AudioManagerBase::GetTaskRunner();
}

void AudioManagerMac::StopAmplitudePeakTrace() {
  TraceAmplitudePeak(/*trace_start=*/false);
}

bool AudioManagerMac::IsOnBatteryPower() const {
  DCHECK(GetTaskRunner()->BelongsToCurrentThread());
  return power_observer_->IsOnBatteryPower();
}

size_t AudioManagerMac::GetNumberOfResumeNotifications() const {
  DCHECK(GetTaskRunner()->BelongsToCurrentThread());
  return power_observer_->num_resume_notifications();
}

bool AudioManagerMac::MaybeChangeBufferSize(AudioDeviceID device_id,
                                            AudioUnit audio_unit,
                                            AudioUnitElement element,
                                            size_t desired_buffer_size) {
  DCHECK(GetTaskRunner()->BelongsToCurrentThread());
  if (in_shutdown_) {
    DVLOG(1) << __FUNCTION__ << " Disabled since we are shutting down";
    return false;
  }
  const bool is_input = (element == 1);
  DVLOG(1) << __FUNCTION__ << " (id=0x" << std::hex << device_id
           << ", is_input=" << is_input << ", desired_buffer_size=" << std::dec
           << desired_buffer_size << ")";

  // Log the device name (and id) for debugging purposes.
  std::string device_name = GetAudioDeviceNameFromDeviceId(device_id, is_input);
  DVLOG(1) << __FUNCTION__ << " name: " << device_name << " (ID: 0x" << std::hex
           << device_id << ")";

  // Get the current size of the I/O buffer for the specified device. The
  // property is read on a global scope, hence using element 0. The default IO
  // buffer size on Mac OSX for OS X 10.9 and later is 512 audio frames.
  UInt32 buffer_size = 0;
  UInt32 property_size = sizeof(buffer_size);
  OSStatus result = AudioUnitGetProperty(
      audio_unit, kAudioDevicePropertyBufferFrameSize, kAudioUnitScope_Global,
      0, &buffer_size, &property_size);
  if (result != noErr) {
    OSSTATUS_DLOG(ERROR, result)
        << "AudioUnitGetProperty(kAudioDevicePropertyBufferFrameSize) failed.";
    return false;
  }

  DVLOG(1) << __FUNCTION__ << " current IO buffer size: " << buffer_size;
  DVLOG(1) << __FUNCTION__ << " #output streams: " << output_streams_.size();
  DVLOG(1) << __FUNCTION__
           << " #input streams: " << low_latency_input_streams_.size();

  // Check if a buffer size change is required. If the caller asks for a
  // reduced size (|desired_buffer_size| < |buffer_size|), the new lower size
  // will be set. For larger buffer sizes, we have to perform some checks to
  // see if the size can actually be changed. If there is any other active
  // streams on the same device, either input or output, a larger size than
  // their requested buffer size can't be set. The reason is that an existing
  // stream can't handle buffer size larger than its requested buffer size.
  // See http://crbug.com/428706 for a reason why.

  if (buffer_size == desired_buffer_size)
    return true;

  if (desired_buffer_size > buffer_size) {
    // Do NOT set the buffer size if there is another output stream using
    // the same device with a smaller requested buffer size.
    // Note, for the caller stream, its requested_buffer_size() will be the same
    // as |desired_buffer_size|, so it won't return true due to comparing with
    // itself.
    for (auto* stream : output_streams_) {
      if (stream->device_id() == device_id &&
          stream->requested_buffer_size() < desired_buffer_size) {
        return true;
      }
    }

    // Do NOT set the buffer size if there is another input stream using
    // the same device with a smaller buffer size.
    for (auto* stream : low_latency_input_streams_) {
      if (stream->device_id() == device_id &&
          stream->requested_buffer_size() < desired_buffer_size) {
        return true;
      }
    }
  }

  // In this scope we know that the IO buffer size should be modified. But
  // first, verify that |desired_buffer_size| is within the valid range and
  // modify the desired buffer size if it is outside this range.
  // Note that, we have found that AudioUnitSetProperty(PropertyBufferFrameSize)
  // does in fact do this limitation internally and report noErr even if the
  // user tries to set an invalid size. As an example, asking for a size of
  // 4410 will on most devices be limited to 4096 without any further notice.
  UInt32 minimum = buffer_size;
  UInt32 maximum = buffer_size;
  result = GetIOBufferFrameSizeRange(device_id, is_input, &minimum, &maximum);
  if (result != noErr) {
    // OS error is logged in GetIOBufferFrameSizeRange().
    return false;
  }
  DVLOG(1) << __FUNCTION__ << " valid IO buffer size range: [" << minimum
           << ", " << maximum << "]";
  buffer_size = desired_buffer_size;
  if (buffer_size < minimum)
    buffer_size = minimum;
  else if (buffer_size > maximum)
    buffer_size = maximum;
  DVLOG(1) << "validated desired buffer size: " << buffer_size;

  // Set new (and valid) I/O buffer size for the specified device. The property
  // is set on a global scope, hence using element 0.
  result = AudioUnitSetProperty(audio_unit, kAudioDevicePropertyBufferFrameSize,
                                kAudioUnitScope_Global, 0, &buffer_size,
                                sizeof(buffer_size));
  OSSTATUS_DLOG_IF(ERROR, result != noErr, result)
      << "AudioUnitSetProperty(kAudioDevicePropertyBufferFrameSize) failed.  "
      << "Size:: " << buffer_size;
  DVLOG_IF(1, result == noErr)
      << __FUNCTION__ << " IO buffer size changed to: " << buffer_size;
  // Store the currently used (after a change) I/O buffer frame size.
  return result == noErr;
}

bool AudioManagerMac::DeviceSupportsAmbientNoiseReduction(
    AudioDeviceID device_id) {
  return AudioObjectHasProperty(device_id, &kNoiseReductionPropertyAddress);
}

bool AudioManagerMac::SuppressNoiseReduction(AudioDeviceID device_id) {
  DCHECK(GetTaskRunner()->BelongsToCurrentThread());
  DCHECK(DeviceSupportsAmbientNoiseReduction(device_id));
  NoiseReductionState& state = device_noise_reduction_states_[device_id];
  if (state.suppression_count == 0) {
    UInt32 initially_enabled = 0;
    UInt32 size = sizeof(initially_enabled);
    OSStatus result =
        AudioObjectGetPropertyData(device_id, &kNoiseReductionPropertyAddress,
                                   0, nullptr, &size, &initially_enabled);
    if (result != noErr)
      return false;

    if (initially_enabled) {
      const UInt32 disable = 0;
      result =
          AudioObjectSetPropertyData(device_id, &kNoiseReductionPropertyAddress,
                                     0, nullptr, sizeof(disable), &disable);
      if (result != noErr) {
        OSSTATUS_DLOG(WARNING, result)
            << "Failed to disable ambient noise reduction for device: "
            << std::hex << device_id;
      }
      state.initial_state = NoiseReductionState::ENABLED;
    } else {
      state.initial_state = NoiseReductionState::DISABLED;
    }
  }

  // Only increase the counter if suppression succeeded or is already active.
  ++state.suppression_count;
  return true;
}

void AudioManagerMac::UnsuppressNoiseReduction(AudioDeviceID device_id) {
  DCHECK(GetTaskRunner()->BelongsToCurrentThread());
  NoiseReductionState& state = device_noise_reduction_states_[device_id];
  DCHECK_NE(state.suppression_count, 0);
  --state.suppression_count;
  if (state.suppression_count == 0) {
    if (state.initial_state == NoiseReductionState::ENABLED) {
      const UInt32 enable = 1;
      OSStatus result =
          AudioObjectSetPropertyData(device_id, &kNoiseReductionPropertyAddress,
                                     0, nullptr, sizeof(enable), &enable);
      if (result != noErr) {
        OSSTATUS_DLOG(WARNING, result)
            << "Failed to re-enable ambient noise reduction for device: "
            << std::hex << device_id;
      }
    }
  }
}

bool AudioManagerMac::AudioDeviceIsUsedForInput(AudioDeviceID device_id) {
  DCHECK(GetTaskRunner()->BelongsToCurrentThread());
  if (!basic_input_streams_.empty()) {
    // For Audio Queues and in the default case (Mac OS X), the audio comes
    // from the system’s default audio input device as set by a user in System
    // Preferences.
    AudioDeviceID default_id;
    GetDefaultDevice(&default_id, true);
    if (default_id == device_id)
      return true;
  }

  // Each low latency streams has its own device ID.
  for (auto* stream : low_latency_input_streams_) {
    if (stream->device_id() == device_id)
      return true;
  }
  return false;
}

void AudioManagerMac::ReleaseOutputStream(AudioOutputStream* stream) {
  DCHECK(GetTaskRunner()->BelongsToCurrentThread());
  output_streams_.remove(static_cast<AUHALStream*>(stream));
  AudioManagerBase::ReleaseOutputStream(stream);
}

void AudioManagerMac::ReleaseInputStream(AudioInputStream* stream) {
  DCHECK(GetTaskRunner()->BelongsToCurrentThread());
  auto stream_it = base::ranges::find(basic_input_streams_, stream);
  if (stream_it == basic_input_streams_.end()) {
    low_latency_input_streams_.remove(static_cast<AUAudioInputStream*>(stream));
  } else {
    basic_input_streams_.erase(stream_it);
  }

  AudioManagerBase::ReleaseInputStream(stream);
}

void AudioManagerMac::ReleaseOutputStreamUsingRealDevice(
    AudioOutputStream* stream,
    AudioDeviceID device_id) {
  DCHECK(GetTaskRunner()->BelongsToCurrentThread());
  DVLOG(1) << __FUNCTION__ << " Closing output stream with id=0x" << std::hex
           << device_id << " requested_buffer_size: "
           << static_cast<AUHALStream*>(stream)->requested_buffer_size();

  // Start by closing down the specified output stream.
  output_streams_.remove(static_cast<AUHALStream*>(stream));
  AudioManagerBase::ReleaseOutputStream(stream);
}

void AudioManagerMac::ReleaseInputStreamUsingRealDevice(
    AudioInputStream* stream) {
  DCHECK(GetTaskRunner()->BelongsToCurrentThread());
  auto stream_it = base::ranges::find(basic_input_streams_, stream);
  if (stream_it == basic_input_streams_.end())
    low_latency_input_streams_.remove(static_cast<AUAudioInputStream*>(stream));
  else
    basic_input_streams_.erase(stream_it);

  AudioManagerBase::ReleaseInputStream(stream);
}

std::unique_ptr<AudioManager> CreateAudioManager(
    std::unique_ptr<AudioThread> audio_thread,
    AudioLogFactory* audio_log_factory) {
  return std::make_unique<AudioManagerMac>(std::move(audio_thread),
                                           audio_log_factory);
}

}  // namespace media
