owning_audio_manager_accessor.cc 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. // Copyright 2018 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "services/audio/owning_audio_manager_accessor.h"
  5. #include <memory>
  6. #include <utility>
  7. #include "base/feature_list.h"
  8. #include "base/metrics/field_trial_params.h"
  9. #include "base/metrics/histogram_macros.h"
  10. #include "base/strings/string_number_conversions.h"
  11. #include "base/task/sequenced_task_runner.h"
  12. #include "base/task/single_thread_task_runner.h"
  13. #include "base/threading/thread_task_runner_handle.h"
  14. #include "base/time/default_tick_clock.h"
  15. #include "base/time/time.h"
  16. #include "media/audio/audio_features.h"
  17. #include "media/audio/audio_manager.h"
  18. #include "media/audio/audio_thread.h"
  19. #include "media/audio/audio_thread_hang_monitor.h"
  20. #include "services/audio/realtime_audio_thread.h"
  21. using HangAction = media::AudioThreadHangMonitor::HangAction;
  22. namespace audio {
  23. namespace {
  24. // Ideally, this would be based on the incoming audio's buffer durations.
  25. // However, we might deal with multiple streams, with multiple buffer durations.
  26. // Using a 10ms constant instead is acceptable (and better than the default)
  27. // since there are no super-strict realtime requirements (no system audio calls
  28. // waiting on these threads).
  29. constexpr base::TimeDelta kReatimeThreadPeriod = base::Milliseconds(10);
  30. absl::optional<base::TimeDelta> GetAudioThreadHangDeadline() {
  31. if (!base::FeatureList::IsEnabled(
  32. features::kAudioServiceOutOfProcessKillAtHang)) {
  33. return absl::nullopt;
  34. }
  35. const std::string timeout_string = base::GetFieldTrialParamValueByFeature(
  36. features::kAudioServiceOutOfProcessKillAtHang, "timeout_seconds");
  37. int timeout_int = 0;
  38. if (!base::StringToInt(timeout_string, &timeout_int) || timeout_int == 0)
  39. return absl::nullopt;
  40. return base::Seconds(timeout_int);
  41. }
  42. HangAction GetAudioThreadHangAction() {
  43. const bool dump =
  44. base::FeatureList::IsEnabled(features::kDumpOnAudioServiceHang);
  45. const bool kill = base::FeatureList::IsEnabled(
  46. features::kAudioServiceOutOfProcessKillAtHang);
  47. if (dump) {
  48. return kill ? HangAction::kDumpAndTerminateCurrentProcess
  49. : HangAction::kDump;
  50. }
  51. return kill ? HangAction::kTerminateCurrentProcess : HangAction::kDoNothing;
  52. }
  53. // Thread class for hosting owned AudioManager on the main thread of the
  54. // service, with a separate worker thread (started on-demand) for running things
  55. // that shouldn't be blocked by main-thread tasks.
  56. class MainThread final : public media::AudioThread {
  57. public:
  58. MainThread();
  59. MainThread(const MainThread&) = delete;
  60. MainThread& operator=(const MainThread&) = delete;
  61. ~MainThread() final;
  62. // AudioThread implementation.
  63. void Stop() final;
  64. bool IsHung() const final;
  65. base::SingleThreadTaskRunner* GetTaskRunner() final;
  66. base::SingleThreadTaskRunner* GetWorkerTaskRunner() final;
  67. private:
  68. scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
  69. // This is not started until the first time GetWorkerTaskRunner() is called.
  70. RealtimeAudioThread worker_thread_;
  71. scoped_refptr<base::SingleThreadTaskRunner> worker_task_runner_;
  72. media::AudioThreadHangMonitor::Ptr hang_monitor_;
  73. };
  74. MainThread::MainThread()
  75. : task_runner_(base::ThreadTaskRunnerHandle::Get()),
  76. worker_thread_("AudioWorkerThread", kReatimeThreadPeriod),
  77. hang_monitor_(media::AudioThreadHangMonitor::Create(
  78. GetAudioThreadHangAction(),
  79. GetAudioThreadHangDeadline(),
  80. base::DefaultTickClock::GetInstance(),
  81. task_runner_)) {}
  82. MainThread::~MainThread() {
  83. DCHECK(task_runner_->BelongsToCurrentThread());
  84. }
  85. void MainThread::Stop() {
  86. DCHECK(task_runner_->BelongsToCurrentThread());
  87. hang_monitor_.reset();
  88. if (worker_task_runner_) {
  89. worker_task_runner_ = nullptr;
  90. worker_thread_.Stop();
  91. }
  92. }
  93. bool MainThread::IsHung() const {
  94. return hang_monitor_->IsAudioThreadHung();
  95. }
  96. base::SingleThreadTaskRunner* MainThread::GetTaskRunner() {
  97. return task_runner_.get();
  98. }
  99. base::SingleThreadTaskRunner* MainThread::GetWorkerTaskRunner() {
  100. DCHECK(
  101. task_runner_->BelongsToCurrentThread() ||
  102. (worker_task_runner_ && worker_task_runner_->BelongsToCurrentThread()));
  103. if (!worker_task_runner_) {
  104. base::Thread::Options options;
  105. options.timer_slack = base::TIMER_SLACK_NONE;
  106. options.thread_type = base::ThreadType::kRealtimeAudio;
  107. CHECK(worker_thread_.StartWithOptions(std::move(options)));
  108. worker_task_runner_ = worker_thread_.task_runner();
  109. }
  110. return worker_task_runner_.get();
  111. }
  112. } // namespace
  113. OwningAudioManagerAccessor::OwningAudioManagerAccessor(
  114. AudioManagerFactoryCallback audio_manager_factory_cb)
  115. : audio_manager_factory_cb_(std::move(audio_manager_factory_cb)) {
  116. DCHECK(audio_manager_factory_cb_);
  117. }
  118. OwningAudioManagerAccessor::~OwningAudioManagerAccessor() {
  119. DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  120. }
  121. media::AudioManager* OwningAudioManagerAccessor::GetAudioManager() {
  122. DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  123. if (!audio_manager_) {
  124. TRACE_EVENT0("audio", "AudioManager creation");
  125. DCHECK(audio_manager_factory_cb_);
  126. DCHECK(log_factory_);
  127. base::TimeTicks creation_start_time = base::TimeTicks::Now();
  128. audio_manager_ =
  129. std::move(audio_manager_factory_cb_)
  130. .Run(std::make_unique<MainThread>(), log_factory_.get());
  131. DCHECK(audio_manager_);
  132. UMA_HISTOGRAM_TIMES("Media.AudioService.AudioManagerStartupTime",
  133. base::TimeTicks::Now() - creation_start_time);
  134. }
  135. DCHECK(audio_manager_->GetTaskRunner()->BelongsToCurrentThread());
  136. return audio_manager_.get();
  137. }
  138. void OwningAudioManagerAccessor::SetAudioLogFactory(
  139. media::AudioLogFactory* log_factory) {
  140. log_factory_ = log_factory;
  141. }
  142. void OwningAudioManagerAccessor::Shutdown() {
  143. DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  144. if (audio_manager_)
  145. audio_manager_->Shutdown();
  146. audio_manager_factory_cb_ = AudioManagerFactoryCallback();
  147. }
  148. } // namespace audio