// Copyright 2019 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/android/aaudio_output.h"

#include "base/android/build_info.h"
#include "base/logging.h"
#include "base/thread_annotations.h"
#include "base/threading/sequenced_task_runner_handle.h"
#include "base/trace_event/trace_event.h"
#include "media/audio/android/aaudio_stubs.h"
#include "media/audio/android/audio_manager_android.h"
#include "media/base/audio_bus.h"

namespace media {

// Used to circumvent issues where the AAudio thread callbacks continue
// after AAudioStream_requestStop() completes. See crbug.com/1183255.
class LOCKABLE AAudioDestructionHelper {
 public:
  explicit AAudioDestructionHelper(AAudioOutputStream* stream)
      : output_stream_(stream) {}

  ~AAudioDestructionHelper() {
    DCHECK(is_closing_);
    if (aaudio_stream_)
      AAudioStream_close(aaudio_stream_);
  }

  AAudioOutputStream* GetAndLockStream() EXCLUSIVE_LOCK_FUNCTION() {
    lock_.Acquire();
    return is_closing_ ? nullptr : output_stream_;
  }

  void UnlockStream() UNLOCK_FUNCTION() { lock_.Release(); }

  void DeferStreamClosure(AAudioStream* stream) {
    base::AutoLock al(lock_);
    DCHECK(!is_closing_);

    is_closing_ = true;
    aaudio_stream_ = stream;
  }

 private:
  base::Lock lock_;
  AAudioOutputStream* output_stream_ GUARDED_BY(lock_) = nullptr;
  AAudioStream* aaudio_stream_ GUARDED_BY(lock_) = nullptr;
  bool is_closing_ GUARDED_BY(lock_) = false;
};

static aaudio_data_callback_result_t OnAudioDataRequestedCallback(
    AAudioStream* stream,
    void* user_data,
    void* audio_data,
    int32_t num_frames) {
  AAudioDestructionHelper* destruction_helper =
      reinterpret_cast<AAudioDestructionHelper*>(user_data);

  AAudioOutputStream* output_stream = destruction_helper->GetAndLockStream();

  aaudio_data_callback_result_t result = AAUDIO_CALLBACK_RESULT_STOP;
  if (output_stream)
    result = output_stream->OnAudioDataRequested(audio_data, num_frames);

  destruction_helper->UnlockStream();

  return result;
}

static void OnStreamErrorCallback(AAudioStream* stream,
                                  void* user_data,
                                  aaudio_result_t error) {
  AAudioDestructionHelper* destruction_helper =
      reinterpret_cast<AAudioDestructionHelper*>(user_data);

  AAudioOutputStream* output_stream = destruction_helper->GetAndLockStream();

  if (output_stream)
    output_stream->OnStreamError(error);

  destruction_helper->UnlockStream();
}

AAudioOutputStream::AAudioOutputStream(AudioManagerAndroid* manager,
                                       const AudioParameters& params,
                                       aaudio_usage_t usage)
    : audio_manager_(manager),
      params_(params),
      usage_(usage),
      performance_mode_(AAUDIO_PERFORMANCE_MODE_NONE),
      ns_per_frame_(base::Time::kNanosecondsPerSecond /
                    static_cast<double>(params.sample_rate())),
      destruction_helper_(std::make_unique<AAudioDestructionHelper>(this)) {
  DCHECK(manager);
  DCHECK(params.IsValid());

  if (AudioManagerAndroid::SupportsPerformanceModeForOutput()) {
    switch (params.latency_tag()) {
      case AudioLatency::LATENCY_EXACT_MS:
      case AudioLatency::LATENCY_INTERACTIVE:
      case AudioLatency::LATENCY_RTC:
        performance_mode_ = AAUDIO_PERFORMANCE_MODE_LOW_LATENCY;
        break;
      case AudioLatency::LATENCY_PLAYBACK:
        performance_mode_ = AAUDIO_PERFORMANCE_MODE_POWER_SAVING;
        break;
      default:
        performance_mode_ = AAUDIO_PERFORMANCE_MODE_NONE;
    }
  }

  TRACE_EVENT2("audio", "AAudioOutputStream::AAudioOutputStream",
               "AAUDIO_PERFORMANCE_MODE_LOW_LATENCY",
               performance_mode_ == AAUDIO_PERFORMANCE_MODE_LOW_LATENCY
                   ? "true" : "false",
               "frames_per_buffer", params.frames_per_buffer());
}

AAudioOutputStream::~AAudioOutputStream() {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);

  if (base::android::SdkVersion::SDK_VERSION_S >=
      base::android::BuildInfo::GetInstance()->sdk_int()) {
    // On Android S+, |destruction_helper_| can be destroyed as part of the
    // normal class teardown.
    return;
  }

  // In R and earlier, it is possible for callbacks to still be running even
  // after calling AAudioStream_close(). The code below is a mitigation to work
  // around this issue. See crbug.com/1183255.

  // Keep |destruction_helper_| alive longer than |this|, so the |user_data|
  // bound to the callback stays valid, until the callbacks stop.
  base::SequencedTaskRunnerHandle::Get()->PostDelayedTask(
      FROM_HERE,
      base::BindOnce([](std::unique_ptr<AAudioDestructionHelper>) {},
                     std::move(destruction_helper_)),
      base::Seconds(1));
}

void AAudioOutputStream::Flush() {}

bool AAudioOutputStream::Open() {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);

  AAudioStreamBuilder* builder;
  auto result = AAudio_createStreamBuilder(&builder);
  if (AAUDIO_OK != result)
    return false;

  // Parameters
  AAudioStreamBuilder_setDirection(builder, AAUDIO_DIRECTION_OUTPUT);
  AAudioStreamBuilder_setSampleRate(builder, params_.sample_rate());
  AAudioStreamBuilder_setChannelCount(builder, params_.channels());
  AAudioStreamBuilder_setFormat(builder, AAUDIO_FORMAT_PCM_FLOAT);
  AAudioStreamBuilder_setUsage(builder, usage_);
  AAudioStreamBuilder_setPerformanceMode(builder, performance_mode_);
  AAudioStreamBuilder_setFramesPerDataCallback(builder,
                                               params_.frames_per_buffer());

  // Callbacks
  AAudioStreamBuilder_setDataCallback(builder, OnAudioDataRequestedCallback,
                                      destruction_helper_.get());
  AAudioStreamBuilder_setErrorCallback(builder, OnStreamErrorCallback,
                                       destruction_helper_.get());

  result = AAudioStreamBuilder_openStream(builder, &aaudio_stream_);

  AAudioStreamBuilder_delete(builder);

  if (AAUDIO_OK != result)
    return false;

  // After opening the stream, sets the effective buffer size to 3X the burst
  // size to prevent glitching if the burst is small (e.g. < 128). On some
  // devices you can get by with 1X or 2X, but 3X is safer.
  int32_t framesPerBurst = AAudioStream_getFramesPerBurst(aaudio_stream_);
  int32_t sizeRequested = framesPerBurst * (framesPerBurst < 128 ? 3 : 2);
  AAudioStream_setBufferSizeInFrames(aaudio_stream_, sizeRequested);

  audio_bus_ = AudioBus::Create(params_);

  TRACE_EVENT2("audio", "AAudioOutputStream::Open",
               "params_", params_.AsHumanReadableString(),
               "requested BufferSizeInFrames", sizeRequested);

  return true;
}

void AAudioOutputStream::Close() {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);

  Stop();

  // |destruction_helper_->GetStreamAndLock()| will return nullptr after this.
  destruction_helper_->DeferStreamClosure(aaudio_stream_);

  // We shouldn't be acessing |aaudio_stream_| after it's stopped.
  aaudio_stream_ = nullptr;

  // Note: This must be last, it will delete |this|.
  audio_manager_->ReleaseOutputStream(this);
}

void AAudioOutputStream::Start(AudioSourceCallback* callback) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  DCHECK(aaudio_stream_);

  {
    base::AutoLock al(lock_);

    // The device might have been disconnected between Open() and Start().
    if (device_changed_) {
      callback->OnError(AudioSourceCallback::ErrorType::kDeviceChange);
      return;
    }

    DCHECK(!callback_);
    callback_ = callback;
  }

  auto result = AAudioStream_requestStart(aaudio_stream_);
  if (result != AAUDIO_OK) {
    DLOG(ERROR) << "Failed to start audio stream, result: "
                << AAudio_convertResultToText(result);

    // Lock is required in case a previous asynchronous requestStop() still has
    // not completed by the time we reach this point.
    base::AutoLock al(lock_);
    callback_->OnError(AudioSourceCallback::ErrorType::kUnknown);
    callback_ = nullptr;
  }
}

void AAudioOutputStream::Stop() {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);

  {
    base::AutoLock al(lock_);
    if (!callback_ || !aaudio_stream_)
      return;
  }

  // Note: This call may be asynchronous, so we must clear |callback_| under
  // lock below to ensure no further calls occur after Stop(). Since it may
  // not always be asynchronous, we don't hold |lock_| while we call stop.
  auto result = AAudioStream_requestStop(aaudio_stream_);

  {
    base::AutoLock al(lock_);
    if (result != AAUDIO_OK) {
      DLOG(ERROR) << "Failed to stop audio stream, result: "
                  << AAudio_convertResultToText(result);
      callback_->OnError(AudioSourceCallback::ErrorType::kUnknown);
    }

    callback_ = nullptr;
  }

  // Wait for AAUDIO_STREAM_STATE_STOPPED, but do not explicitly check for the
  // success of this wait.
  aaudio_stream_state_t current_state = AAUDIO_STREAM_STATE_STOPPING;
  aaudio_stream_state_t next_state = AAUDIO_STREAM_STATE_UNINITIALIZED;
  static const int64_t kTimeoutNanoseconds = 1e8;
  result = AAudioStream_waitForStateChange(aaudio_stream_, current_state,
                                           &next_state, kTimeoutNanoseconds);
}

base::TimeDelta AAudioOutputStream::GetDelay(base::TimeTicks delay_timestamp) {
  // Get the time that a known audio frame was presented for playing.
  int64_t existing_frame_index;
  int64_t existing_frame_pts;
  auto result =
      AAudioStream_getTimestamp(aaudio_stream_, CLOCK_MONOTONIC,
                                &existing_frame_index, &existing_frame_pts);

  if (result != AAUDIO_OK) {
    DLOG(ERROR) << "Failed to get audio latency, result: "
                << AAudio_convertResultToText(result);
    return base::TimeDelta();
  }

  // Calculate the number of frames between our known frame and the write index.
  const int64_t frame_index_delta =
      AAudioStream_getFramesWritten(aaudio_stream_) - existing_frame_index;

  // Calculate the time which the next frame will be presented.
  const base::TimeDelta next_frame_pts =
      base::Nanoseconds(existing_frame_pts + frame_index_delta * ns_per_frame_);

  // Calculate the latency between write time and presentation time. At startup
  // we may end up with negative values here.
  return std::max(base::TimeDelta(),
                  next_frame_pts - (delay_timestamp - base::TimeTicks()));
}

aaudio_data_callback_result_t AAudioOutputStream::OnAudioDataRequested(
    void* audio_data,
    int32_t num_frames) {
  // TODO(tguilbert): This can be downgraded to a DCHECK after we've launched.
  CHECK_EQ(num_frames, audio_bus_->frames());

  base::AutoLock al(lock_);
  if (!callback_)
    return AAUDIO_CALLBACK_RESULT_STOP;

  const base::TimeTicks delay_timestamp = base::TimeTicks::Now();
  const base::TimeDelta delay = GetDelay(delay_timestamp);

  const int frames_filled =
      callback_->OnMoreData(delay, delay_timestamp, 0, audio_bus_.get());

  audio_bus_->Scale(muted_ ? 0.0 : volume_);
  audio_bus_->ToInterleaved<Float32SampleTypeTraits>(
      frames_filled, reinterpret_cast<float*>(audio_data));
  return AAUDIO_CALLBACK_RESULT_CONTINUE;
}

void AAudioOutputStream::OnStreamError(aaudio_result_t error) {
  base::AutoLock al(lock_);

  if (error == AAUDIO_ERROR_DISCONNECTED)
    device_changed_ = true;

  if (!callback_)
    return;

  if (device_changed_) {
    callback_->OnError(AudioSourceCallback::ErrorType::kDeviceChange);
    return;
  }

  // TODO(dalecurtis): Consider sending a translated |error| code.
  callback_->OnError(AudioSourceCallback::ErrorType::kUnknown);
}

void AAudioOutputStream::SetVolume(double volume) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);

  double volume_override = 0;
  if (audio_manager_->HasOutputVolumeOverride(&volume_override))
    volume = volume_override;

  if (volume < 0.0 || volume > 1.0)
    return;

  base::AutoLock al(lock_);
  volume_ = volume;
}

void AAudioOutputStream::GetVolume(double* volume) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  base::AutoLock al(lock_);
  *volume = volume_;
}

void AAudioOutputStream::SetMute(bool muted) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);

  base::AutoLock al(lock_);
  muted_ = muted;
}

}  // namespace media
