aecdump_recording_manager.cc 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. // Copyright 2022 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/aecdump_recording_manager.h"
  5. #include "base/bind.h"
  6. #include "base/task/single_thread_task_runner.h"
  7. #include "base/task/thread_pool.h"
  8. namespace audio {
  9. namespace {
  10. void CloseFileWithoutBlocking(base::File file) {
  11. // Post as a low-priority task to a thread pool to avoid blocking the
  12. // current thread.
  13. base::ThreadPool::PostTask(
  14. FROM_HERE, {base::TaskPriority::LOWEST, base::MayBlock()},
  15. base::BindOnce([](base::File) {}, std::move(file)));
  16. }
  17. } // namespace
  18. AecdumpRecordingManager::AecdumpRecordingManager(
  19. scoped_refptr<base::SingleThreadTaskRunner> task_runner)
  20. : task_runner_(std::move(task_runner)) {
  21. DCHECK(task_runner_->BelongsToCurrentThread());
  22. }
  23. AecdumpRecordingManager::~AecdumpRecordingManager() {
  24. DCHECK(task_runner_->BelongsToCurrentThread());
  25. DCHECK_EQ(aecdump_recording_sources_.size(), 0u);
  26. DCHECK(!IsDebugRecordingEnabled());
  27. }
  28. void AecdumpRecordingManager::EnableDebugRecording(
  29. CreateFileCallback create_file_callback) {
  30. DCHECK(task_runner_->BelongsToCurrentThread());
  31. DCHECK(create_file_callback);
  32. DCHECK(!create_file_callback_);
  33. create_file_callback_ = std::move(create_file_callback);
  34. for (const auto& it : aecdump_recording_sources_) {
  35. AecdumpRecordingSource* source = it.first;
  36. uint32_t id = it.second;
  37. create_file_callback_.Run(
  38. id, /*reply_callback=*/base::BindOnce(
  39. &StartRecordingIfValidPointer, weak_factory_.GetWeakPtr(), source));
  40. }
  41. }
  42. void AecdumpRecordingManager::StartRecording(AecdumpRecordingSource* source,
  43. base::File file) {
  44. DCHECK(task_runner_->BelongsToCurrentThread());
  45. DCHECK(IsDebugRecordingEnabled());
  46. if (aecdump_recording_sources_.find(source) !=
  47. aecdump_recording_sources_.end()) {
  48. source->StartAecdump(std::move(file));
  49. return;
  50. }
  51. // The source is deregistered and we are responsible for closing the file.
  52. CloseFileWithoutBlocking(std::move(file));
  53. }
  54. void AecdumpRecordingManager::DisableDebugRecording() {
  55. DCHECK(task_runner_->BelongsToCurrentThread());
  56. DCHECK(create_file_callback_);
  57. for (const auto& it : aecdump_recording_sources_) {
  58. AecdumpRecordingSource* source = it.first;
  59. source->StopAecdump();
  60. }
  61. create_file_callback_.Reset();
  62. // By invalidating weak pointers, we cancel any recordings in the process of
  63. // being started (file creation).
  64. weak_factory_.InvalidateWeakPtrs();
  65. }
  66. void AecdumpRecordingManager::RegisterAecdumpSource(
  67. AecdumpRecordingSource* source) {
  68. DCHECK(task_runner_->BelongsToCurrentThread());
  69. DCHECK(aecdump_recording_sources_.find(source) ==
  70. aecdump_recording_sources_.end());
  71. const uint32_t id = recording_id_counter_++;
  72. if (IsDebugRecordingEnabled()) {
  73. create_file_callback_.Run(id, /*reply_callback=*/base::BindOnce(
  74. &AecdumpRecordingManager::StartRecording,
  75. weak_factory_.GetWeakPtr(), source));
  76. }
  77. aecdump_recording_sources_[source] = id;
  78. }
  79. void AecdumpRecordingManager::DeregisterAecdumpSource(
  80. AecdumpRecordingSource* source) {
  81. DCHECK(task_runner_->BelongsToCurrentThread());
  82. DCHECK(aecdump_recording_sources_.find(source) !=
  83. aecdump_recording_sources_.end());
  84. if (IsDebugRecordingEnabled()) {
  85. source->StopAecdump();
  86. }
  87. aecdump_recording_sources_.erase(source);
  88. }
  89. bool AecdumpRecordingManager::IsDebugRecordingEnabled() const {
  90. DCHECK(task_runner_->BelongsToCurrentThread());
  91. return !create_file_callback_.is_null();
  92. }
  93. // static
  94. void AecdumpRecordingManager::StartRecordingIfValidPointer(
  95. base::WeakPtr<AecdumpRecordingManager> manager,
  96. AecdumpRecordingSource* source,
  97. base::File file) {
  98. if (manager) {
  99. manager->StartRecording(source, std::move(file));
  100. return;
  101. }
  102. // Recording has been stopped and we are responsible for closing the file.
  103. CloseFileWithoutBlocking(std::move(file));
  104. }
  105. } // namespace audio