// 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 <optional>
#include <utility>
#include <vector>

#include "base/apple/foundation_util.h"
#include "base/apple/osstatus_logging.h"
#include "base/apple/scoped_cftyperef.h"
#include "base/command_line.h"
#include "base/containers/flat_set.h"
#include "base/containers/heap_array.h"
#include "base/functional/bind.h"
#include "base/mac/mac_util.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/stringprintf.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/apple/audio_auhal.h"
#include "media/audio/apple/audio_input.h"
#include "media/audio/apple/audio_low_latency_input.h"
#include "media/audio/apple/scoped_audio_unit.h"
#include "media/audio/audio_device_description.h"
#include "media/audio/mac/audio_loopback_input_mac.h"
#include "media/audio/mac/core_audio_util_mac.h"
#include "media/audio/mac/coreaudio_dispatch_override.h"
#include "media/audio/mac/screen_capture_kit_swizzler.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"

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 GetOutputDeviceChannelsAndLayout(AudioUnit audio_unit,
                                             int* channels,
                                             ChannelLayout* channel_layout);

// 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;
    }

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

    std::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::apple::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::GetDefaultInputDevice(AudioDeviceID* input_device) {
  return GetDefaultDevice(input_device, true);
}

bool AudioManagerMac::GetDefaultOutputDevice(AudioDeviceID* output_device) {
  return GetDefaultDevice(output_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;
  }

  auto list_storage = base::HeapArray<uint8_t>::Uninit(size);
  AudioBufferList* buffer_list =
      reinterpret_cast<AudioBufferList*>(list_storage.data());

  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 `channels` for `device` as provided by the AudioUnit attached
// to that input device. Returns true if the `channels` could be pulled
// from the AudioUnit successfully, otherwise return false and `channels` is
// untouched.
static bool GetInputDeviceChannels(AudioDeviceID device, int* channels) {
  DCHECK(AudioManager::Get()->GetTaskRunner()->BelongsToCurrentThread());
  CHECK(channels);

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

  if (!GetAudioUnitStreamFormatChannelCount(au.audio_unit(), AUElement::INPUT,
                                            channels)) {
    return false;
  }

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

// Returns the `channels` and `channel_layout` for `device` as provided by the
// AudioUnit attached to that output device. Returns true if the `channels` and
// `channel_layout` could be pulled from the AudioUnit successfully, otherwise
// return false and `channels` and `channel_layout` are untouched.
static bool GetOutputDeviceChannelsAndLayout(AudioDeviceID device,
                                             int* channels,
                                             ChannelLayout* channel_layout) {
  DCHECK(AudioManager::Get()->GetTaskRunner()->BelongsToCurrentThread());
  CHECK(channels);
  CHECK(channel_layout);

  // 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, kAudioDevicePropertyScopeOutput,
                                 &total_channel_count) &&
      total_channel_count > kMaxConcurrentChannels) {
    *channels = total_channel_count;
    *channel_layout = CHANNEL_LAYOUT_DISCRETE;
  } else {
    ScopedAudioUnit au(device, AUElement::OUTPUT);
    if (!au.is_valid()) {
      return false;
    }

    if (!GetOutputDeviceChannelsAndLayout(au.audio_unit(), channels,
                                          channel_layout)) {
      return false;
    }
  }

  DVLOG(2) << __FUNCTION__ << " Output channels: " << *channels
           << ", channel layout: " << ChannelLayoutToString(*channel_layout);
  return true;
}

static bool GetOutputDeviceChannelsAndLayout(AudioUnit audio_unit,
                                             int* channels,
                                             ChannelLayout* channel_layout) {
  // Attempt to retrieve the channel layout from the AudioUnit.
  std::unique_ptr<ScopedAudioChannelLayout> scoped_device_layout =
      AudioManagerApple::GetOutputDeviceChannelLayout(audio_unit);
  if (!scoped_device_layout) {
    DLOG(ERROR) << "Failed to retrieve output device channel layout.";
    return false;
  }
  AudioChannelLayout* device_layout = scoped_device_layout->layout();

  // There is no channel info for stereo, assume so for mono as well.
  if (device_layout->mNumberChannelDescriptions == 1 ||
      device_layout->mNumberChannelDescriptions == 2) {
    *channels = device_layout->mNumberChannelDescriptions;
    *channel_layout =
        *channels == 2 ? CHANNEL_LAYOUT_STEREO : CHANNEL_LAYOUT_MONO;
    return true;
  }

  *channels = 0;
  // use `CHANNEL_LAYOUT_DISCRETE` as the default layout if we can't
  // find out a matched one.
  *channel_layout = CHANNEL_LAYOUT_DISCRETE;

  std::vector<Channels> channels_to_match;
  for (UInt32 i = 0; i < device_layout->mNumberChannelDescriptions; i++) {
    AudioChannelLabel label =
        device_layout->mChannelDescriptions[i].mChannelLabel;
    if (label == kAudioChannelLabel_Unknown) {
      continue;
    }

    (*channels)++;

    Channels channel;
    if (AudioChannelLabelToChannel(label, &channel)) {
      channels_to_match.push_back(channel);
    }
  }

  if (*channels == 0 ||
      *channels != static_cast<int>(channels_to_match.size())) {
    return true;
  }

  for (int i = 0; i <= ChannelLayout::CHANNEL_LAYOUT_MAX; i++) {
    ChannelLayout layout = static_cast<ChannelLayout>(i);
    if (ChannelLayoutToChannelCount(layout) != *channels) {
      continue;
    }

    bool matched = true;
    for (const auto& channel : channels_to_match) {
      auto channel_order = ChannelOrder(layout, channel);
      if (channel_order == -1) {
        matched = false;
        break;
      }
    }

    if (matched) {
      *channel_layout = layout;
      return true;
    }
  }

  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)
    : AudioManagerApple(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.
  std::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()) {
    std::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());
  std::optional<uint32_t> transport_type = GetDeviceTransportType(device_id);
  if (transport_type && *transport_type == kAudioDeviceTransportTypeBluetooth) {
    return GetRelatedBluetoothDeviceIDs(device_id);
  }
  return GetRelatedNonBluetoothDeviceIDs(device_id);
}

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

std::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
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());
  if (AudioDeviceDescription::IsLoopbackDevice(device_id)) {
    return AudioParameters(AudioParameters::AUDIO_PCM_LOW_LATENCY,
                           ChannelLayoutConfig::Stereo(), kLoopbackSampleRate,
                           ChooseBufferSize(true, kLoopbackSampleRate));
  }

  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 (GetInputDeviceChannels(device, &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) {
    std::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_.insert(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_.insert(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());

  if (AudioDeviceDescription::IsLoopbackDevice(device_id)) {
    screen_capture_kit_swizzler_ = SwizzleScreenCaptureKit();

    return CreateSCKAudioInputStream(
        params, device_id, log_callback,
        base::BindRepeating(&AudioManagerBase::ReleaseInputStream,
                            base::Unretained(this)));
  }

  // 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_.insert(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;
  ChannelLayout hardware_channel_layout;
  if (!GetOutputDeviceChannelsAndLayout(device, &hardware_channels,
                                        &hardware_channel_layout)) {
    hardware_channels = 2;
    hardware_channel_layout = CHANNEL_LAYOUT_STEREO;
  }

  // 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 output_channel_layout = input_params.channel_layout();
  if (!has_valid_input_params || output_channels > hardware_channels) {
    output_channels = hardware_channels;
    output_channel_layout = hardware_channel_layout;
  }

  AudioParameters params(
      AudioParameters::AUDIO_PCM_LOW_LATENCY,
      {output_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());
  AudioDeviceID new_output_device;
  GetDefaultOutputDevice(&new_output_device);
  const int new_sample_rate = HardwareSampleRateForDevice(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();
}

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

double AudioManagerMac::GetMaxInputVolume(AudioDeviceID device_id) {
  // Verify that we have a valid device.
  if (device_id == kAudioObjectUnknown) {
    LOG(ERROR) << "Device ID is unknown";
    return 0.0;
  }

  // The master channel is 0, Left and right are channels 1 and 2.
  // Query if any of the master, left or right channels has volume control.
  for (int channel = 0; channel <= GetNumberOfChannelsForDevice(device_id);
       ++channel) {
    // If the volume is settable, the  valid volume range is [0.0, 1.0].
    if (IsVolumeSettableOnChannel(device_id, channel)) {
      return 1.0;
    }
  }

  // Volume control is not available for the audio stream.
  return 0.0;
}

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,
      AUElement::OUTPUT, &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;
      }
    }
  }
}

void AudioManagerMac::ReleaseOutputStream(AudioOutputStream* stream) {
  DCHECK(GetTaskRunner()->BelongsToCurrentThread());
  CHECK(stream);

  auto it = output_streams_.find(static_cast<AUHALStream*>(stream));
  if (it != output_streams_.end()) {
    output_streams_.erase(it);
  }

  AudioManagerBase::ReleaseOutputStream(stream);
}

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

  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);
}

// static
bool AudioManagerMac::IsVolumeSettableOnChannel(AudioDeviceID device_id,
                                                int channel) {
  Boolean is_settable = false;
  AudioObjectPropertyAddress property_address = {
      kAudioDevicePropertyVolumeScalar, kAudioDevicePropertyScopeInput,
      static_cast<UInt32>(channel)};
  OSStatus result =
      AudioObjectIsPropertySettable(device_id, &property_address, &is_settable);
  return (result == noErr) ? is_settable : false;
}

void AudioManagerMac::SetInputVolume(AudioDeviceID device_id, double volume) {
  CHECK_GE(volume, 0.0);
  CHECK_LE(volume, 1.0);

  // Verify that we have a valid device.
  if (device_id == kAudioObjectUnknown) {
    LOG(ERROR) << "Device ID is unknown";
    return;
  }

  Float32 volume_float32 = static_cast<Float32>(volume);
  AudioObjectPropertyAddress property_address = {
      kAudioDevicePropertyVolumeScalar, kAudioDevicePropertyScopeInput,
      kAudioObjectPropertyElementMain};

  // Try to set the volume for master volume channel.
  if (IsVolumeSettableOnChannel(device_id, kAudioObjectPropertyElementMain)) {
    OSStatus result =
        AudioObjectSetPropertyData(device_id, &property_address, 0, nullptr,
                                   sizeof(volume_float32), &volume_float32);
    if (result != noErr) {
      DLOG(WARNING) << "Failed to set volume to " << volume_float32;
    }
    return;
  }

  // The master channel is 0, Left and right are channels 1 and 2.
  // There is no master volume control, try to set volume for each channel.
  [[maybe_unused]] int successful_channels = 0;
  for (int channel = 1; channel <= GetNumberOfChannelsForDevice(device_id);
       ++channel) {
    property_address.mElement = static_cast<UInt32>(channel);
    if (IsVolumeSettableOnChannel(device_id, channel)) {
      OSStatus result =
          AudioObjectSetPropertyData(device_id, &property_address, 0, NULL,
                                     sizeof(volume_float32), &volume_float32);
      if (result == noErr) {
        ++successful_channels;
      }
    }
  }

  DLOG_IF(WARNING, successful_channels == 0)
      << "Failed to set volume to " << volume_float32;
}

double AudioManagerMac::GetInputVolume(AudioDeviceID device_id) {
  // Verify that we have a valid device.
  if (device_id == kAudioObjectUnknown) {
    LOG(ERROR) << "Device ID is unknown";
    return 0.0;
  }

  AudioObjectPropertyAddress property_address = {
      kAudioDevicePropertyVolumeScalar, kAudioDevicePropertyScopeInput,
      kAudioObjectPropertyElementMain};

  if (AudioObjectHasProperty(device_id, &property_address)) {
    // The device supports master volume control, get the volume from the
    // master channel.
    Float32 volume_float32 = 0.0;
    UInt32 size = sizeof(volume_float32);
    OSStatus result = AudioObjectGetPropertyData(
        device_id, &property_address, 0, nullptr, &size, &volume_float32);
    if (result == noErr) {
      return static_cast<double>(volume_float32);
    }
    return 0.0;
  } else {
    // There is no master volume control, try to get the average volume of
    // all the channels.
    Float32 volume_float32 = 0.0;
    int successful_channels = 0;
    for (int i = 1; i <= GetNumberOfChannelsForDevice(device_id); ++i) {
      property_address.mElement = static_cast<UInt32>(i);
      if (AudioObjectHasProperty(device_id, &property_address)) {
        Float32 channel_volume = 0;
        UInt32 size = sizeof(channel_volume);
        OSStatus result = AudioObjectGetPropertyData(
            device_id, &property_address, 0, nullptr, &size, &channel_volume);
        if (result == noErr) {
          volume_float32 += channel_volume;
          ++successful_channels;
        }
      }
    }

    // Get the average volume of the channels.
    if (successful_channels != 0) {
      return static_cast<double>(volume_float32 / successful_channels);
    }
  }

  DLOG(WARNING) << "Failed to get volume";
  return 0.0;
}

bool AudioManagerMac::IsInputMuted(AudioDeviceID device_id) {
  // Verify that we have a valid device.
  DCHECK_NE(device_id, kAudioObjectUnknown) << "Device ID is unknown";

  AudioObjectPropertyAddress property_address = {
      kAudioDevicePropertyMute, kAudioDevicePropertyScopeInput,
      kAudioObjectPropertyElementMain};

  if (!AudioObjectHasProperty(device_id, &property_address)) {
    DLOG(ERROR) << "Device does not support checking master mute state";
    return false;
  }

  UInt32 muted = 0;
  UInt32 size = sizeof(muted);
  OSStatus result = AudioObjectGetPropertyData(device_id, &property_address, 0,
                                               nullptr, &size, &muted);
  DLOG_IF(WARNING, result != noErr) << "Failed to get mute state";
  return result == noErr && muted != 0;
}

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
        << ", returing fallback sample rate " << kFallbackSampleRate;
    return kFallbackSampleRate;
  }

  return static_cast<int>(nominal_sample_rate);
}

// static
AudioDeviceID AudioManagerMac::FindFirstOutputSubdevice(
    AudioDeviceID aggregate_device_id) {
  const AudioObjectPropertyAddress property_address = {
      kAudioAggregateDevicePropertyFullSubDeviceList,
      kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMain};
  base::apple::ScopedCFTypeRef<CFArrayRef> subdevices;
  UInt32 size = sizeof(subdevices);
  OSStatus result = AudioObjectGetPropertyData(
      aggregate_device_id, &property_address, 0 /* inQualifierDataSize */,
      nullptr /* inQualifierData */, &size, subdevices.InitializeInto());

  if (result != noErr) {
    OSSTATUS_LOG(WARNING, result)
        << "Failed to read property "
        << kAudioAggregateDevicePropertyFullSubDeviceList << " for device "
        << aggregate_device_id;
    return kAudioObjectUnknown;
  }

  AudioDeviceID output_subdevice_id = kAudioObjectUnknown;
  DCHECK_EQ(CFGetTypeID(subdevices.get()), CFArrayGetTypeID());
  const CFIndex count = CFArrayGetCount(subdevices.get());
  for (CFIndex i = 0; i < count; ++i) {
    CFStringRef value = base::apple::CFCast<CFStringRef>(
        CFArrayGetValueAtIndex(subdevices.get(), i));
    if (value) {
      std::string uid = base::SysCFStringRefToUTF8(value);
      output_subdevice_id = AudioManagerMac::GetAudioDeviceIdByUId(false, uid);
      if (output_subdevice_id != kAudioObjectUnknown &&
          core_audio_mac::GetNumStreams(output_subdevice_id, false) > 0) {
        return output_subdevice_id;
      }
    }
  }

  return kAudioObjectUnknown;
}

OSStatus AudioManagerMac::GetInputDeviceStreamFormat(
    AudioUnit audio_unit,
    AudioStreamBasicDescription* input_format) {
  DCHECK(audio_unit);
  UInt32 property_size = sizeof(*input_format);
  // Get the audio stream data format on the input scope of the input element
  // since it is connected to the current input device.
  return AudioUnitGetProperty(audio_unit, kAudioUnitProperty_StreamFormat,
                              kAudioUnitScope_Input, AUElement::INPUT,
                              input_format, &property_size);
}

// static
int AudioManagerMac::GetNumberOfChannelsForDevice(AudioDeviceID device_id) {
  // The master channel is 0, Left and right are channels 1 and 2. And the
  // master channel is not counted.

  // Get the stream format, to be able to read the number of channels.
  AudioObjectPropertyAddress property_address = {
      kAudioDevicePropertyStreamFormat, kAudioDevicePropertyScopeInput,
      kAudioObjectPropertyElementMain};
  AudioStreamBasicDescription stream_format;
  UInt32 size = sizeof(stream_format);
  OSStatus result = AudioObjectGetPropertyData(device_id, &property_address, 0,
                                               nullptr, &size, &stream_format);
  if (result != noErr) {
    DLOG(WARNING) << "Could not get stream format";
    return 0;
  }

  return static_cast<int>(stream_format.mChannelsPerFrame);
}

}  // namespace media
