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

#include "media/audio/audio_manager_base.h"

#include <memory>

#include "base/bind.h"
#include "base/callback_helpers.h"
#include "base/command_line.h"
#include "base/macros.h"
#include "base/metrics/histogram_macros.h"
#include "base/single_thread_task_runner.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/stringprintf.h"
#include "base/threading/thread_task_runner_handle.h"
#include "build/build_config.h"
#include "build/buildflag.h"
#include "media/audio/audio_device_description.h"
#include "media/audio/audio_output_dispatcher_impl.h"
#include "media/audio/audio_output_proxy.h"
#include "media/audio/audio_output_resampler.h"
#include "media/audio/fake_audio_input_stream.h"
#include "media/audio/fake_audio_output_stream.h"
#include "media/base/media_switches.h"
#include "third_party/abseil-cpp/absl/types/optional.h"

#include "base/logging.h"
#include "build/chromeos_buildflags.h"
#include "media/audio/audio_input_stream_data_interceptor.h"

namespace media {

namespace {

const int kStreamCloseDelaySeconds = 5;

// Default maximum number of output streams that can be open simultaneously
// for all platforms.
const int kDefaultMaxOutputStreams = 16;

// Default maximum number of input streams that can be open simultaneously
// for all platforms.
const int kMaxInputStreams = 16;

const int kMaxInputChannels = 3;

// Helper function to pass as callback when the audio debug recording is not
// enabled.
std::unique_ptr<AudioDebugRecorder> GetNullptrAudioDebugRecorder(
    const AudioParameters& params) {
  return nullptr;
}

// This enum must match the numbering for AudioOutputProxyStreamFormat in
// enums.xml. Do not reorder or remove items, only add new items before
// STREAM_FORMAT_MAX.
enum StreamFormat {
  STREAM_FORMAT_BITSTREAM = 0,
  STREAM_FORMAT_PCM_LINEAR = 1,
  STREAM_FORMAT_PCM_LOW_LATENCY = 2,
  STREAM_FORMAT_PCM_LOW_LATENCY_FALLBACK_TO_FAKE = 3,
  STREAM_FORMAT_FAKE = 4,
  STREAM_FORMAT_MAX = 4,
};

PRINTF_FORMAT(2, 3)
void SendLogMessage(const AudioManagerBase::LogCallback& callback,
                    const char* format,
                    ...) {
  if (callback.is_null())
    return;
  va_list args;
  va_start(args, format);
  callback.Run("AMB::" + base::StringPrintV(format, args));
  va_end(args);
}

}  // namespace

struct AudioManagerBase::DispatcherParams {
  DispatcherParams(const AudioParameters& input,
                   const AudioParameters& output,
                   const std::string& output_device_id)
      : input_params(input),
        output_params(output),
        output_device_id(output_device_id) {}
  ~DispatcherParams() = default;

  const AudioParameters input_params;
  const AudioParameters output_params;
  const std::string output_device_id;
  std::unique_ptr<AudioOutputDispatcher> dispatcher;

 private:
  DISALLOW_COPY_AND_ASSIGN(DispatcherParams);
};

class AudioManagerBase::CompareByParams {
 public:
  explicit CompareByParams(const DispatcherParams* dispatcher)
      : dispatcher_(dispatcher) {}
  bool operator()(
      const std::unique_ptr<DispatcherParams>& dispatcher_in) const {
    // We will reuse the existing dispatcher when:
    // 1) Unified IO is not used, input_params and output_params of the
    //    existing dispatcher are the same as the requested dispatcher.
    // 2) Unified IO is used, input_params and output_params of the existing
    //    dispatcher are the same as the request dispatcher.
    return (dispatcher_->input_params.Equals(dispatcher_in->input_params) &&
            dispatcher_->output_params.Equals(dispatcher_in->output_params) &&
            dispatcher_->output_device_id == dispatcher_in->output_device_id);
  }

 private:
  const DispatcherParams* dispatcher_;
};

AudioManagerBase::AudioManagerBase(std::unique_ptr<AudioThread> audio_thread,
                                   AudioLogFactory* audio_log_factory)
    : AudioManager(std::move(audio_thread)),
      max_num_output_streams_(kDefaultMaxOutputStreams),
      num_output_streams_(0),
      // TODO(dalecurtis): Switch this to an base::ObserverListThreadSafe, so we
      // don't block the UI thread when swapping devices.
      output_listeners_(base::ObserverListPolicy::EXISTING_ONLY),
      audio_log_factory_(audio_log_factory) {}

AudioManagerBase::~AudioManagerBase() {
  // All the output streams should have been deleted.
  CHECK_EQ(0, num_output_streams_);
  // All the input streams should have been deleted.
  CHECK(input_streams_.empty());
}

void AudioManagerBase::GetAudioInputDeviceDescriptions(
    AudioDeviceDescriptions* device_descriptions) {
  CHECK(GetTaskRunner()->BelongsToCurrentThread());
  GetAudioDeviceDescriptions(device_descriptions,
                             &AudioManagerBase::GetAudioInputDeviceNames,
                             &AudioManagerBase::GetDefaultInputDeviceID,
                             &AudioManagerBase::GetCommunicationsInputDeviceID,
                             &AudioManagerBase::GetGroupIDInput);
}

void AudioManagerBase::GetAudioOutputDeviceDescriptions(
    AudioDeviceDescriptions* device_descriptions) {
  CHECK(GetTaskRunner()->BelongsToCurrentThread());
  GetAudioDeviceDescriptions(device_descriptions,
                             &AudioManagerBase::GetAudioOutputDeviceNames,
                             &AudioManagerBase::GetDefaultOutputDeviceID,
                             &AudioManagerBase::GetCommunicationsOutputDeviceID,
                             &AudioManagerBase::GetGroupIDOutput);
}

void AudioManagerBase::GetAudioDeviceDescriptions(
    AudioDeviceDescriptions* device_descriptions,
    void (AudioManagerBase::*get_device_names)(AudioDeviceNames*),
    std::string (AudioManagerBase::*get_default_device_id)(),
    std::string (AudioManagerBase::*get_communications_device_id)(),
    std::string (AudioManagerBase::*get_group_id)(const std::string&)) {
  CHECK(GetTaskRunner()->BelongsToCurrentThread());
  AudioDeviceNames device_names;
  (this->*get_device_names)(&device_names);
  std::string real_default_device_id = (this->*get_default_device_id)();
  std::string real_communications_device_id =
      (this->*get_communications_device_id)();
  std::string real_default_name;
  std::string real_communications_name;

  // Find the names for the real devices that are mapped to the default and
  // communications devices.
  for (const auto& name : device_names) {
    if (name.unique_id == real_default_device_id)
      real_default_name = name.device_name;
    if (name.unique_id == real_communications_device_id)
      real_communications_name = name.device_name;
  }

  for (auto& name : device_names) {
    if (AudioDeviceDescription::IsDefaultDevice(name.unique_id))
      name.device_name = real_default_name;
    else if (AudioDeviceDescription::IsCommunicationsDevice(name.unique_id))
      name.device_name = real_communications_name;
    std::string group_id = (this->*get_group_id)(name.unique_id);
    device_descriptions->emplace_back(std::move(name.device_name),
                                      std::move(name.unique_id),
                                      std::move(group_id));
  }
}

AudioOutputStream* AudioManagerBase::MakeAudioOutputStream(
    const AudioParameters& params,
    const std::string& device_id,
    const LogCallback& log_callback) {
  CHECK(GetTaskRunner()->BelongsToCurrentThread());
  DCHECK(params.IsValid());

  if (base::CommandLine::ForCurrentProcess()->HasSwitch(
          switches::kFailAudioStreamCreation)) {
    return nullptr;
  }

  SendLogMessage(log_callback, "%s({device_id=%s}, {params=[%s]})", __func__,
                 device_id.c_str(), params.AsHumanReadableString().c_str());

  // Limit the number of audio streams opened. This is to prevent using
  // excessive resources for a large number of audio streams. More
  // importantly it prevents instability on certain systems.
  // See bug: http://crbug.com/30242.
  if (num_output_streams_ >= max_num_output_streams_) {
    LOG(ERROR) << "Number of opened output audio streams "
               << num_output_streams_ << " exceed the max allowed number "
               << max_num_output_streams_;
    return nullptr;
  }

  AudioOutputStream* stream;
  switch (params.format()) {
    case AudioParameters::AUDIO_PCM_LINEAR:
      DCHECK(AudioDeviceDescription::IsDefaultDevice(device_id))
          << "AUDIO_PCM_LINEAR supports only the default device.";
      stream = MakeLinearOutputStream(params, log_callback);
      break;
    case AudioParameters::AUDIO_PCM_LOW_LATENCY:
      stream = MakeLowLatencyOutputStream(params, device_id, log_callback);
      break;
    case AudioParameters::AUDIO_BITSTREAM_AC3:
    case AudioParameters::AUDIO_BITSTREAM_EAC3:
      stream = MakeBitstreamOutputStream(params, device_id, log_callback);
      break;
    case AudioParameters::AUDIO_FAKE:
      stream = FakeAudioOutputStream::MakeFakeStream(this, params);
      break;
    default:
      stream = nullptr;
      break;
  }

  if (stream) {
    ++num_output_streams_;
    SendLogMessage(log_callback, "%s => (number of streams=%d)", __func__,
                   output_stream_count());
  }

  return stream;
}

AudioOutputStream* AudioManagerBase::MakeBitstreamOutputStream(
    const AudioParameters& params,
    const std::string& device_id,
    const LogCallback& log_callback) {
  return nullptr;
}

AudioInputStream* AudioManagerBase::MakeAudioInputStream(
    const AudioParameters& params,
    const std::string& device_id,
    const LogCallback& log_callback) {
  CHECK(GetTaskRunner()->BelongsToCurrentThread());

  if (base::CommandLine::ForCurrentProcess()->HasSwitch(
          switches::kFailAudioStreamCreation)) {
    return nullptr;
  }

  SendLogMessage(log_callback, "%s({device_id=%s}, {params=[%s]})", __func__,
                 device_id.c_str(), params.AsHumanReadableString().c_str());

  if (!params.IsValid() || (params.channels() > kMaxInputChannels) ||
      device_id.empty()) {
    DLOG(ERROR) << "Audio parameters are invalid for device " << device_id
                << ", params: " << params.AsHumanReadableString();
    return nullptr;
  }

  if (input_stream_count() >= kMaxInputStreams) {
    LOG(ERROR) << "Number of opened input audio streams "
               << input_stream_count() << " exceed the max allowed number "
               << kMaxInputStreams;
    return nullptr;
  }

  DVLOG(2) << "Creating a new AudioInputStream with buffer size = "
           << params.frames_per_buffer();

  AudioInputStream* stream;
  switch (params.format()) {
    case AudioParameters::AUDIO_PCM_LINEAR:
      stream = MakeLinearInputStream(params, device_id, log_callback);
      break;
    case AudioParameters::AUDIO_PCM_LOW_LATENCY:
      stream = MakeLowLatencyInputStream(params, device_id, log_callback);
      break;
    case AudioParameters::AUDIO_FAKE:
      stream = FakeAudioInputStream::MakeFakeStream(this, params);
      break;
    default:
      stream = nullptr;
      break;
  }

  if (stream) {
    input_streams_.insert(stream);
    if (!log_callback.is_null()) {
      SendLogMessage(log_callback, "%s => (number of streams=%d)", __func__,
                     input_stream_count());
    }

    if (!params.IsBitstreamFormat() && debug_recording_manager_) {
      // Using unretained for |debug_recording_manager_| is safe since it
      // outlives the audio thread, on which streams are operated.
      // Note: The AudioInputStreamDataInterceptor takes ownership of the
      // created stream and cleans it up when it is Close()d, transparently to
      // the user of the stream. I the case where the audio manager closes the
      // stream (Mac), this will result in a dangling pointer.
      stream = new AudioInputStreamDataInterceptor(
          base::BindRepeating(
              &AudioDebugRecordingManager::RegisterDebugRecordingSource,
              base::Unretained(debug_recording_manager_.get()),
              AudioDebugRecordingStreamType::kInput, params),
          stream);
    }
  }

  return stream;
}

AudioOutputStream* AudioManagerBase::MakeAudioOutputStreamProxy(
    const AudioParameters& params,
    const std::string& device_id) {
  CHECK(GetTaskRunner()->BelongsToCurrentThread());
  DCHECK(params.IsValid());
  absl::optional<StreamFormat> uma_stream_format;

  // If the caller supplied an empty device id to select the default device,
  // we fetch the actual device id of the default device so that the lookup
  // will find the correct device regardless of whether it was opened as
  // "default" or via the specific id.
  // NOTE: Implementations that don't yet support opening non-default output
  // devices may return an empty string from GetDefaultOutputDeviceID().
  std::string output_device_id =
      AudioDeviceDescription::IsDefaultDevice(device_id)
          ?
#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS)
          // On ChromeOS, it is expected that, if the default device is given,
          // no specific device ID should be used since the actual output device
          // should change dynamically if the system default device changes.
          // See http://crbug.com/750614.
          std::string()
#else
          GetDefaultOutputDeviceID()
#endif
          : device_id;

  // If we're not using AudioOutputResampler our output parameters are the same
  // as our input parameters.
  AudioParameters output_params = params;

  // If audio has been disabled force usage of a fake audio stream.
  if (base::CommandLine::ForCurrentProcess()->HasSwitch(
          switches::kDisableAudioOutput)) {
    output_params.set_format(AudioParameters::AUDIO_FAKE);
  }

  if (params.format() == AudioParameters::AUDIO_PCM_LOW_LATENCY &&
      output_params.format() != AudioParameters::AUDIO_FAKE) {
    output_params =
        GetPreferredOutputStreamParameters(output_device_id, params);

    // Ensure we only pass on valid output parameters.
    if (output_params.IsValid()) {
      if (params.effects() & AudioParameters::MULTIZONE) {
        // Never turn off the multizone effect even if it is not preferred.
        output_params.set_effects(output_params.effects() |
                                  AudioParameters::MULTIZONE);
      }
      if (params.effects() != output_params.effects()) {
        // Turn off effects that weren't requested.
        output_params.set_effects(params.effects() & output_params.effects());
      }

      uma_stream_format = STREAM_FORMAT_PCM_LOW_LATENCY;
    } else {
      // We've received invalid audio output parameters, so switch to a mock
      // output device based on the input parameters.  This may happen if the OS
      // provided us junk values for the hardware configuration.
      LOG(ERROR) << "Invalid audio output parameters received; using fake "
                 << "audio path: " << output_params.AsHumanReadableString();

      // Tell the AudioManager to create a fake output device.
      output_params = params;
      output_params.set_format(AudioParameters::AUDIO_FAKE);
      uma_stream_format = STREAM_FORMAT_PCM_LOW_LATENCY_FALLBACK_TO_FAKE;
    }

    output_params.set_latency_tag(params.latency_tag());
  } else {
    switch (output_params.format()) {
      case AudioParameters::AUDIO_PCM_LINEAR:
        uma_stream_format = STREAM_FORMAT_PCM_LINEAR;
        break;
      case AudioParameters::AUDIO_FAKE:
        uma_stream_format = STREAM_FORMAT_FAKE;
        break;
      default:
        if (output_params.IsBitstreamFormat())
          uma_stream_format = STREAM_FORMAT_BITSTREAM;
        else
          NOTREACHED();
    }
  }

  if (uma_stream_format) {
    UMA_HISTOGRAM_ENUMERATION("Media.AudioOutputStreamProxy.StreamFormat",
                              *uma_stream_format, STREAM_FORMAT_MAX + 1);
  } else {
    NOTREACHED();
  }

  std::unique_ptr<DispatcherParams> dispatcher_params =
      std::make_unique<DispatcherParams>(params, output_params,
                                         output_device_id);

  auto it = std::find_if(output_dispatchers_.begin(), output_dispatchers_.end(),
                         CompareByParams(dispatcher_params.get()));
  if (it != output_dispatchers_.end())
    return (*it)->dispatcher->CreateStreamProxy();

  const base::TimeDelta kCloseDelay = base::Seconds(kStreamCloseDelaySeconds);
  std::unique_ptr<AudioOutputDispatcher> dispatcher;
  if (output_params.format() != AudioParameters::AUDIO_FAKE &&
      !output_params.IsBitstreamFormat()) {
    // Using unretained for |debug_recording_manager_| is safe since it
    // outlives the dispatchers (cleared in ShutdownOnAudioThread()).
    dispatcher = std::make_unique<AudioOutputResampler>(
        this, params, output_params, output_device_id, kCloseDelay,
        debug_recording_manager_
            ? base::BindRepeating(
                  &AudioDebugRecordingManager::RegisterDebugRecordingSource,
                  base::Unretained(debug_recording_manager_.get()),
                  AudioDebugRecordingStreamType::kOutput)
            : base::BindRepeating(&GetNullptrAudioDebugRecorder));
  } else {
    dispatcher = std::make_unique<AudioOutputDispatcherImpl>(
        this, output_params, output_device_id, kCloseDelay);
  }

  dispatcher_params->dispatcher = std::move(dispatcher);
  output_dispatchers_.push_back(std::move(dispatcher_params));
  return output_dispatchers_.back()->dispatcher->CreateStreamProxy();
}

void AudioManagerBase::GetAudioInputDeviceNames(
    AudioDeviceNames* device_names) {
}

void AudioManagerBase::GetAudioOutputDeviceNames(
    AudioDeviceNames* device_names) {
}

void AudioManagerBase::ReleaseOutputStream(AudioOutputStream* stream) {
  CHECK(GetTaskRunner()->BelongsToCurrentThread());
  DCHECK(stream);
  CHECK_GT(num_output_streams_, 0);
  // TODO(xians) : Have a clearer destruction path for the AudioOutputStream.
  // For example, pass the ownership to AudioManager so it can delete the
  // streams.
  --num_output_streams_;
  delete stream;
}

void AudioManagerBase::ReleaseInputStream(AudioInputStream* stream) {
  CHECK(GetTaskRunner()->BelongsToCurrentThread());
  DCHECK(stream);
  // TODO(xians) : Have a clearer destruction path for the AudioInputStream.
  CHECK_EQ(1u, input_streams_.erase(stream));
  delete stream;
}

void AudioManagerBase::ShutdownOnAudioThread() {
  DCHECK(GetTaskRunner()->BelongsToCurrentThread());

  // Close all output streams.
  output_dispatchers_.clear();
}

void AudioManagerBase::AddOutputDeviceChangeListener(
    AudioDeviceListener* listener) {
  DCHECK(GetTaskRunner()->BelongsToCurrentThread());
  output_listeners_.AddObserver(listener);
}

void AudioManagerBase::RemoveOutputDeviceChangeListener(
    AudioDeviceListener* listener) {
  DCHECK(GetTaskRunner()->BelongsToCurrentThread());
  output_listeners_.RemoveObserver(listener);
}

void AudioManagerBase::NotifyAllOutputDeviceChangeListeners() {
  DCHECK(GetTaskRunner()->BelongsToCurrentThread());
  DVLOG(1) << "Firing OnDeviceChange() notifications.";
  for (auto& observer : output_listeners_)
    observer.OnDeviceChange();
}

AudioParameters AudioManagerBase::GetDefaultOutputStreamParameters() {
  return GetPreferredOutputStreamParameters(GetDefaultOutputDeviceID(),
      AudioParameters());
}

AudioParameters AudioManagerBase::GetOutputStreamParameters(
    const std::string& device_id) {
  return GetPreferredOutputStreamParameters(device_id,
      AudioParameters());
}

AudioParameters AudioManagerBase::GetInputStreamParameters(
    const std::string& device_id) {
  NOTREACHED();
  return AudioParameters();
}

std::string AudioManagerBase::GetAssociatedOutputDeviceID(
    const std::string& input_device_id) {
  return std::string();
}

std::string AudioManagerBase::GetGroupIDOutput(
    const std::string& output_device_id) {
  if (output_device_id == AudioDeviceDescription::kDefaultDeviceId) {
    std::string real_device_id = GetDefaultOutputDeviceID();
    if (!real_device_id.empty())
      return real_device_id;
  } else if (output_device_id ==
             AudioDeviceDescription::kCommunicationsDeviceId) {
    std::string real_device_id = GetCommunicationsOutputDeviceID();
    if (!real_device_id.empty())
      return real_device_id;
  }
  return output_device_id;
}

std::string AudioManagerBase::GetGroupIDInput(
    const std::string& input_device_id) {
  const std::string& real_input_device_id =
      input_device_id == AudioDeviceDescription::kDefaultDeviceId
          ? GetDefaultInputDeviceID()
          : input_device_id == AudioDeviceDescription::kCommunicationsDeviceId
                ? GetCommunicationsInputDeviceID()
                : input_device_id;
  std::string output_device_id =
      GetAssociatedOutputDeviceID(real_input_device_id);
  if (output_device_id.empty()) {
    // Some characters are added to avoid accidentally
    // giving the input the same group id as an output.
    return real_input_device_id + "input";
  }
  return GetGroupIDOutput(output_device_id);
}

void AudioManagerBase::CloseAllInputStreams() {
  for (auto iter = input_streams_.begin(); iter != input_streams_.end();) {
    // Note: Closing the stream will invalidate the iterator.
    // Increment the iterator before closing the stream.
    AudioInputStream* stream = *iter++;
    stream->Close();
  }
  CHECK(input_streams_.empty());
}

std::string AudioManagerBase::GetDefaultInputDeviceID() {
  return std::string();
}

std::string AudioManagerBase::GetDefaultOutputDeviceID() {
  return std::string();
}

std::string AudioManagerBase::GetCommunicationsInputDeviceID() {
  return std::string();
}

std::string AudioManagerBase::GetCommunicationsOutputDeviceID() {
  return std::string();
}

// static
int AudioManagerBase::GetUserBufferSize() {
  const base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess();
  int buffer_size = 0;
  std::string buffer_size_str(cmd_line->GetSwitchValueASCII(
      switches::kAudioBufferSize));
  if (base::StringToInt(buffer_size_str, &buffer_size) && buffer_size > 0)
    return buffer_size;

  return 0;
}

std::unique_ptr<AudioLog> AudioManagerBase::CreateAudioLog(
    AudioLogFactory::AudioComponent component,
    int component_id) {
  return audio_log_factory_->CreateAudioLog(component, component_id);
}

void AudioManagerBase::InitializeDebugRecording() {
  if (!GetTaskRunner()->BelongsToCurrentThread()) {
    // AudioManager is deleted on the audio thread, so it's safe to post
    // unretained.
    GetTaskRunner()->PostTask(
        FROM_HERE, base::BindOnce(&AudioManagerBase::InitializeDebugRecording,
                                  base::Unretained(this)));
    return;
  }

  DCHECK(!debug_recording_manager_);
  debug_recording_manager_ = CreateAudioDebugRecordingManager(GetTaskRunner());
}

std::unique_ptr<AudioDebugRecordingManager>
AudioManagerBase::CreateAudioDebugRecordingManager(
    scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
  return std::make_unique<AudioDebugRecordingManager>(std::move(task_runner));
}

AudioDebugRecordingManager* AudioManagerBase::GetAudioDebugRecordingManager() {
  DCHECK(GetTaskRunner()->BelongsToCurrentThread());
  return debug_recording_manager_.get();
}

}  // namespace media
