output_controller.cc 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602
  1. // Copyright (c) 2012 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/output_controller.h"
  5. #include <inttypes.h>
  6. #include <stdio.h>
  7. #include <algorithm>
  8. #include <string>
  9. #include <utility>
  10. #include "base/bind.h"
  11. #include "base/callback_helpers.h"
  12. #include "base/compiler_specific.h"
  13. #include "base/containers/contains.h"
  14. #include "base/logging.h"
  15. #include "base/metrics/histogram_macros.h"
  16. #include "base/numerics/safe_conversions.h"
  17. #include "base/strings/stringprintf.h"
  18. #include "base/task/task_runner_util.h"
  19. #include "base/threading/platform_thread.h"
  20. #include "base/trace_event/trace_event.h"
  21. #include "media/base/audio_timestamp_helper.h"
  22. #include "services/audio/concurrent_stream_metric_reporter.h"
  23. #include "services/audio/device_listener_output_stream.h"
  24. #include "services/audio/stream_monitor.h"
  25. namespace audio {
  26. namespace {
  27. // Time in seconds between two successive measurements of audio power levels.
  28. constexpr base::TimeDelta kPowerMonitorLogInterval = base::Seconds(15);
  29. const char* StateToString(OutputController::State state) {
  30. switch (state) {
  31. case OutputController::kEmpty:
  32. return "empty";
  33. case OutputController::kCreated:
  34. return "created";
  35. case OutputController::kPlaying:
  36. return "playing";
  37. case OutputController::kPaused:
  38. return "paused";
  39. case OutputController::kClosed:
  40. return "closed";
  41. case OutputController::kError:
  42. return "error";
  43. }
  44. return "unknown";
  45. }
  46. const char* ErrorTypeToString(
  47. media::AudioOutputStream::AudioSourceCallback::ErrorType type) {
  48. switch (type) {
  49. case media::AudioOutputStream::AudioSourceCallback::ErrorType::kUnknown:
  50. return "Unknown";
  51. case media::AudioOutputStream::AudioSourceCallback::ErrorType::
  52. kDeviceChange:
  53. return "DeviceChange";
  54. }
  55. return "Invalid";
  56. }
  57. } // namespace
  58. OutputController::ErrorStatisticsTracker::ErrorStatisticsTracker(
  59. OutputController* controller)
  60. : controller_(controller),
  61. start_time_(base::TimeTicks::Now()),
  62. on_more_io_data_called_(0) {
  63. // WedgeCheck() will look to see if |on_more_io_data_called_| is true after
  64. // the timeout expires and log this as a UMA stat. If the stream is
  65. // paused/closed before the timer fires, nothing is logged.
  66. wedge_timer_.Start(FROM_HERE, base::Seconds(5), this,
  67. &ErrorStatisticsTracker::WedgeCheck);
  68. }
  69. OutputController::ErrorStatisticsTracker::~ErrorStatisticsTracker() {
  70. const base::TimeDelta duration = base::TimeTicks::Now() - start_time_;
  71. UMA_HISTOGRAM_LONG_TIMES("Media.OutputStreamDuration", duration);
  72. UMA_HISTOGRAM_BOOLEAN("Media.AudioOutputController.CallbackError",
  73. error_during_callback_);
  74. if (controller_) {
  75. controller_->SendLogMessage("StopStream => (duration=%" PRId64 " sec)",
  76. duration.InSeconds());
  77. controller_->SendLogMessage("StopStream => (error_during_callback=%s)",
  78. error_during_callback_ ? "true" : "false");
  79. }
  80. }
  81. void OutputController::ErrorStatisticsTracker::RegisterError() {
  82. error_during_callback_ = true;
  83. }
  84. void OutputController::ErrorStatisticsTracker::OnMoreDataCalled() {
  85. // Indicate that we haven't wedged (at least not indefinitely, WedgeCheck()
  86. // may have already fired if OnMoreData() took an abnormal amount of time).
  87. // Since this thread is the only writer of |on_more_io_data_called_| once the
  88. // thread starts, it's safe to compare and then increment.
  89. if (on_more_io_data_called_.IsZero())
  90. on_more_io_data_called_.Increment();
  91. }
  92. void OutputController::ErrorStatisticsTracker::WedgeCheck() {
  93. UMA_HISTOGRAM_BOOLEAN("Media.AudioOutputControllerPlaybackStartupSuccess",
  94. on_more_io_data_called_.IsOne());
  95. if (on_more_io_data_called_.IsOne()) {
  96. if (controller_)
  97. controller_->SendLogMessage("WedgeCheck => (stream is alive)");
  98. }
  99. }
  100. OutputController::OutputController(
  101. media::AudioManager* audio_manager,
  102. EventHandler* handler,
  103. OutputStreamActivityMonitor* activity_monitor,
  104. const media::AudioParameters& params,
  105. const std::string& output_device_id,
  106. SyncReader* sync_reader,
  107. ManagedDeviceOutputStreamCreateCallback
  108. managed_device_output_stream_create_callback)
  109. : audio_manager_(audio_manager),
  110. params_(params),
  111. managed_device_output_stream_create_callback_(
  112. std::move(managed_device_output_stream_create_callback)),
  113. handler_(handler),
  114. activity_monitor_(activity_monitor),
  115. task_runner_(audio_manager->GetTaskRunner()),
  116. construction_time_(base::TimeTicks::Now()),
  117. output_device_id_(output_device_id),
  118. stream_(nullptr),
  119. disable_local_output_(false),
  120. volume_(1.0),
  121. state_(kEmpty),
  122. sync_reader_(sync_reader),
  123. power_monitor_(params.sample_rate(),
  124. base::Milliseconds(kPowerMeasurementTimeConstantMillis)) {
  125. DCHECK(audio_manager);
  126. DCHECK(handler_);
  127. DCHECK(activity_monitor_);
  128. DCHECK(sync_reader_);
  129. DCHECK(task_runner_.get());
  130. }
  131. OutputController::~OutputController() {
  132. DCHECK(task_runner_->BelongsToCurrentThread());
  133. DCHECK_EQ(kClosed, state_);
  134. DCHECK_EQ(nullptr, stream_);
  135. DCHECK(snoopers_.empty());
  136. UMA_HISTOGRAM_LONG_TIMES("Media.AudioOutputController.LifeTime",
  137. base::TimeTicks::Now() - construction_time_);
  138. }
  139. bool OutputController::CreateStream() {
  140. DCHECK(task_runner_->BelongsToCurrentThread());
  141. SendLogMessage("%s([state=%s])", __func__, StateToString(state_));
  142. RecreateStream(RecreateReason::INITIAL_STREAM);
  143. SendLogMessage("%s => (state=%s)", __func__, StateToString(state_));
  144. return state_ == kCreated;
  145. }
  146. // static
  147. void OutputController::ReportStreamCreationUma(
  148. OutputController::RecreateReason reason,
  149. StreamCreationResult result) {
  150. switch (reason) {
  151. case RecreateReason::INITIAL_STREAM:
  152. UMA_HISTOGRAM_ENUMERATION(
  153. "Media.AudioOutputController."
  154. "ProxyStreamCreationResultForDeviceChange",
  155. result);
  156. return;
  157. case RecreateReason::DEVICE_CHANGE:
  158. UMA_HISTOGRAM_ENUMERATION(
  159. "Media.AudioOutputController.ProxyStreamCreationResult", result);
  160. return;
  161. case RecreateReason::LOCAL_OUTPUT_TOGGLE:
  162. return; // Not counted in UMAs.
  163. }
  164. return;
  165. }
  166. // static
  167. const char* OutputController::RecreateReasonToString(
  168. OutputController::RecreateReason reason) {
  169. switch (reason) {
  170. case RecreateReason::INITIAL_STREAM:
  171. return "INITIAL_STREAM";
  172. case RecreateReason::DEVICE_CHANGE:
  173. return "DEVICE_CHANGE";
  174. case RecreateReason::LOCAL_OUTPUT_TOGGLE:
  175. return "LOCAL_OUTPUT_TOGGLE";
  176. }
  177. return "Invalid";
  178. }
  179. void OutputController::RecreateStream(OutputController::RecreateReason reason) {
  180. DCHECK(task_runner_->BelongsToCurrentThread());
  181. TRACE_EVENT1("audio", "OutputController::RecreateStream", "reason",
  182. RecreateReasonToString(reason));
  183. SendLogMessage("RecreateStream({reason = %s}, {params = [%s]}, [state = %s])",
  184. RecreateReasonToString(reason),
  185. params_.AsHumanReadableString().c_str(),
  186. StateToString(state_));
  187. // Close() can be called before Create() is executed.
  188. if (state_ == kClosed)
  189. return;
  190. StopCloseAndClearStream();
  191. DCHECK_EQ(kEmpty, state_);
  192. if (disable_local_output_) {
  193. SendLogMessage("%s => (WARNING: local output disabed, using a fake stream)",
  194. __func__);
  195. // Create a fake AudioOutputStream that will continue pumping the audio
  196. // data, but does not play it out anywhere. Pumping the audio data is
  197. // necessary because video playback is synchronized to the audio stream and
  198. // will freeze otherwise.
  199. media::AudioParameters mute_params = params_;
  200. mute_params.set_format(media::AudioParameters::AUDIO_FAKE);
  201. stream_ = audio_manager_->MakeAudioOutputStream(
  202. mute_params, std::string(),
  203. /*log_callback, not used*/ base::DoNothing());
  204. } else if (managed_device_output_stream_create_callback_) {
  205. stream_ = managed_device_output_stream_create_callback_.Run(
  206. output_device_id_, params_,
  207. base::BindRepeating(&OutputController::ProcessDeviceChange,
  208. base::Unretained(this)));
  209. } else {
  210. media::AudioOutputStream* stream =
  211. audio_manager_->MakeAudioOutputStreamProxy(params_, output_device_id_);
  212. if (stream) {
  213. // ProcessDeviceChange must close |stream_|.
  214. stream_ = new DeviceListenerOutputStream(
  215. audio_manager_, stream,
  216. base::BindRepeating(&OutputController::ProcessDeviceChange,
  217. base::Unretained(this)));
  218. }
  219. }
  220. if (!stream_) {
  221. SendLogMessage("%s => (ERROR: failed to create output stream)", __func__);
  222. state_ = kError;
  223. ReportStreamCreationUma(reason, StreamCreationResult::kCreateFailed);
  224. handler_->OnControllerError();
  225. return;
  226. }
  227. if (!stream_->Open()) {
  228. SendLogMessage("%s => (ERROR: failed to open the created output stream)",
  229. __func__);
  230. StopCloseAndClearStream();
  231. state_ = kError;
  232. ReportStreamCreationUma(reason, StreamCreationResult::kOpenFailed);
  233. handler_->OnControllerError();
  234. return;
  235. }
  236. // Finally set the state to kCreated. Note that, it is possible that the
  237. // stream is fake in this state due to the fallback mechanism in the audio
  238. // output dispatcher which falls back to a fake stream if audio parameters
  239. // are invalid or if a physical stream can't be opened for some reason.
  240. state_ = kCreated;
  241. ReportStreamCreationUma(reason, StreamCreationResult::kOk);
  242. // We have successfully opened the stream. Set the initial volume.
  243. stream_->SetVolume(volume_);
  244. }
  245. void OutputController::Play() {
  246. DCHECK(task_runner_->BelongsToCurrentThread());
  247. TRACE_EVENT0("audio", "OutputController::Play");
  248. SendLogMessage("%s([state=%s])", __func__, StateToString(state_));
  249. // We can start from created or paused state.
  250. if (state_ != kCreated && state_ != kPaused)
  251. return;
  252. StartStream();
  253. if (StreamIsActive())
  254. activity_monitor_->OnOutputStreamActive();
  255. }
  256. void OutputController::StartStream() {
  257. DCHECK(task_runner_->BelongsToCurrentThread());
  258. DCHECK(state_ == kCreated || state_ == kPaused);
  259. // Ask for first packet.
  260. sync_reader_->RequestMoreData(base::TimeDelta(), base::TimeTicks(), 0);
  261. state_ = kPlaying;
  262. SendLogMessage("%s => (state=%s)", __func__, StateToString(state_));
  263. if (will_monitor_audio_levels()) {
  264. last_audio_level_log_time_ = base::TimeTicks::Now();
  265. }
  266. stats_tracker_.emplace(this);
  267. stream_->Start(this);
  268. handler_->OnControllerPlaying();
  269. }
  270. void OutputController::StopStream() {
  271. DCHECK(task_runner_->BelongsToCurrentThread());
  272. if (state_ == kPlaying) {
  273. stream_->Stop();
  274. // Destructor of ErrorStatisticsTracker also adds a log message.
  275. stats_tracker_.reset();
  276. if (will_monitor_audio_levels()) {
  277. LogAudioPowerLevel(__func__);
  278. }
  279. // A stopped stream is silent, and power_montior_.Scan() is no longer being
  280. // called; so we must reset the power monitor.
  281. power_monitor_.Reset();
  282. state_ = kPaused;
  283. }
  284. }
  285. void OutputController::Pause() {
  286. DCHECK(task_runner_->BelongsToCurrentThread());
  287. TRACE_EVENT0("audio", "OutputController::Pause");
  288. SendLogMessage("%s([state=%s])", __func__, StateToString(state_));
  289. if (StreamIsActive())
  290. activity_monitor_->OnOutputStreamInactive();
  291. StopStream();
  292. if (state_ != kPaused)
  293. return;
  294. // Let the renderer know we've stopped. Necessary to let PPAPI clients know
  295. // audio has been shutdown. TODO(dalecurtis): This stinks. PPAPI should have
  296. // a better way to know when it should exit PPB_Audio_Shared::Run().
  297. sync_reader_->RequestMoreData(base::TimeDelta::Max(), base::TimeTicks(), 0);
  298. handler_->OnControllerPaused();
  299. SendLogMessage("%s => (state=%s)", __func__, StateToString(state_));
  300. }
  301. void OutputController::Flush() {
  302. DCHECK(task_runner_->BelongsToCurrentThread());
  303. TRACE_EVENT0("audio", "OutputController::Flush");
  304. SendLogMessage("%s([state=%s])", __func__, StateToString(state_));
  305. if (state_ == kPlaying) {
  306. handler_->OnControllerError();
  307. return;
  308. }
  309. if (stream_) {
  310. stream_->Flush();
  311. }
  312. SendLogMessage("%s => (state=%s)", __func__, StateToString(state_));
  313. }
  314. void OutputController::Close() {
  315. DCHECK(task_runner_->BelongsToCurrentThread());
  316. TRACE_EVENT0("audio", "OutputController::Close");
  317. SendLogMessage("%s([state=%s])", __func__, StateToString(state_));
  318. if (state_ != kClosed) {
  319. if (StreamIsActive())
  320. activity_monitor_->OnOutputStreamInactive();
  321. StopCloseAndClearStream();
  322. sync_reader_->Close();
  323. state_ = kClosed;
  324. }
  325. SendLogMessage("%s => (state=%s)", __func__, StateToString(state_));
  326. }
  327. void OutputController::SetVolume(double volume) {
  328. DCHECK(task_runner_->BelongsToCurrentThread());
  329. SendLogMessage("%s({volume=%.2f} [state=%s])", __func__, volume,
  330. StateToString(state_));
  331. // Saves the volume to a member first. We may not be able to set the volume
  332. // right away but when the stream is created we'll set the volume.
  333. volume_ = volume;
  334. switch (state_) {
  335. case kCreated:
  336. case kPlaying:
  337. case kPaused:
  338. stream_->SetVolume(volume_);
  339. break;
  340. default:
  341. break;
  342. }
  343. }
  344. int OutputController::OnMoreData(base::TimeDelta delay,
  345. base::TimeTicks delay_timestamp,
  346. int prior_frames_skipped,
  347. media::AudioBus* dest) {
  348. return OnMoreData(delay, delay_timestamp, prior_frames_skipped, dest, false);
  349. }
  350. int OutputController::OnMoreData(base::TimeDelta delay,
  351. base::TimeTicks delay_timestamp,
  352. int prior_frames_skipped,
  353. media::AudioBus* dest,
  354. bool is_mixing) {
  355. TRACE_EVENT_BEGIN1("audio", "OutputController::OnMoreData", "frames skipped",
  356. prior_frames_skipped);
  357. stats_tracker_->OnMoreDataCalled();
  358. sync_reader_->Read(dest, is_mixing);
  359. const base::TimeTicks reference_time = delay_timestamp + delay;
  360. if (!dest->is_bitstream_format()) {
  361. base::AutoLock lock(snooper_lock_);
  362. if (!snoopers_.empty()) {
  363. TRACE_EVENT1("audio", "OutputController::BroadcastDataToSnoopers",
  364. "reference_time (ms)",
  365. (reference_time - base::TimeTicks()).InMillisecondsF());
  366. for (Snooper* snooper : snoopers_) {
  367. snooper->OnData(*dest, reference_time, volume_);
  368. }
  369. }
  370. }
  371. const int frames =
  372. dest->is_bitstream_format() ? dest->GetBitstreamFrames() : dest->frames();
  373. delay +=
  374. media::AudioTimestampHelper::FramesToTime(frames, params_.sample_rate());
  375. sync_reader_->RequestMoreData(delay, delay_timestamp, prior_frames_skipped);
  376. if (will_monitor_audio_levels()) {
  377. // Note: this code path should never be hit when using bitstream streams.
  378. // Scan doesn't expect compressed audio, so it may go out of bounds trying
  379. // to read |frames| frames of PCM data.
  380. CHECK(!params_.IsBitstreamFormat());
  381. power_monitor_.Scan(*dest, frames);
  382. const auto now = base::TimeTicks::Now();
  383. if ((now - last_audio_level_log_time_) > kPowerMonitorLogInterval) {
  384. LogAudioPowerLevel(__func__);
  385. last_audio_level_log_time_ = now;
  386. }
  387. }
  388. TRACE_EVENT_END2("audio", "OutputController::OnMoreData", "timestamp (ms)",
  389. (delay_timestamp - base::TimeTicks()).InMillisecondsF(),
  390. "delay (ms)", delay.InMillisecondsF());
  391. return frames;
  392. }
  393. void OutputController::SendLogMessage(const char* format, ...) {
  394. if (!handler_)
  395. return;
  396. va_list args;
  397. va_start(args, format);
  398. handler_->OnLog("AOC::" + base::StringPrintV(format, args) +
  399. base::StringPrintf(" [this=0x%" PRIXPTR "]",
  400. reinterpret_cast<uintptr_t>(this)));
  401. va_end(args);
  402. }
  403. void OutputController::LogAudioPowerLevel(const char* call_name) {
  404. std::pair<float, bool> power_and_clip =
  405. power_monitor_.ReadCurrentPowerAndClip();
  406. SendLogMessage("%s => (average audio level=%.2f dBFS)", call_name,
  407. power_and_clip.first);
  408. }
  409. bool OutputController::StreamIsActive() {
  410. DCHECK(task_runner_->BelongsToCurrentThread());
  411. return (state_ == kPlaying) && !disable_local_output_;
  412. }
  413. void OutputController::OnError(ErrorType type) {
  414. DCHECK(task_runner_->BelongsToCurrentThread());
  415. SendLogMessage("%s({type=%s} [state=%s])", __func__, ErrorTypeToString(type),
  416. StateToString(state_));
  417. TRACE_EVENT0("audio", "OutputController::OnError");
  418. DLOG(ERROR) << "OutputController::OnError";
  419. if (state_ != kClosed) {
  420. if (stats_tracker_)
  421. stats_tracker_->RegisterError();
  422. handler_->OnControllerError();
  423. }
  424. }
  425. void OutputController::StopCloseAndClearStream() {
  426. DCHECK(task_runner_->BelongsToCurrentThread());
  427. // Allow calling unconditionally and bail if we don't have a stream_ to close.
  428. if (stream_) {
  429. StopStream();
  430. stream_->Close();
  431. stream_ = nullptr;
  432. }
  433. state_ = kEmpty;
  434. }
  435. const media::AudioParameters& OutputController::GetAudioParameters() const {
  436. return params_;
  437. }
  438. void OutputController::StartSnooping(Snooper* snooper) {
  439. DCHECK(task_runner_->BelongsToCurrentThread());
  440. DCHECK(snooper);
  441. // The list will only update on this thread, and only be read on the realtime
  442. // audio thread.
  443. DCHECK(!base::Contains(snoopers_, snooper));
  444. base::AutoLock lock(snooper_lock_);
  445. snoopers_.push_back(snooper);
  446. }
  447. void OutputController::StopSnooping(Snooper* snooper) {
  448. DCHECK(task_runner_->BelongsToCurrentThread());
  449. // The list will only update on this thread, and only be read on the realtime
  450. // audio thread.
  451. const auto it = std::find(snoopers_.begin(), snoopers_.end(), snooper);
  452. DCHECK(it != snoopers_.end());
  453. // We also don't care about ordering, so swap and pop rather than erase.
  454. base::AutoLock lock(snooper_lock_);
  455. *it = snoopers_.back();
  456. snoopers_.pop_back();
  457. }
  458. void OutputController::StartMuting() {
  459. DCHECK(task_runner_->BelongsToCurrentThread());
  460. SendLogMessage("%s([state=%s])", __func__, StateToString(state_));
  461. if (!disable_local_output_) {
  462. if (StreamIsActive())
  463. activity_monitor_->OnOutputStreamInactive();
  464. ToggleLocalOutput();
  465. }
  466. }
  467. void OutputController::StopMuting() {
  468. DCHECK(task_runner_->BelongsToCurrentThread());
  469. SendLogMessage("%s([state=%s])", __func__, StateToString(state_));
  470. if (disable_local_output_) {
  471. ToggleLocalOutput();
  472. if (StreamIsActive())
  473. activity_monitor_->OnOutputStreamActive();
  474. }
  475. }
  476. void OutputController::ToggleLocalOutput() {
  477. DCHECK(task_runner_->BelongsToCurrentThread());
  478. disable_local_output_ = !disable_local_output_;
  479. SendLogMessage("%s({disable_local_output=%s} [state=%s])", __func__,
  480. disable_local_output_ ? "true" : "false",
  481. StateToString(state_));
  482. // If there is an active |stream_|, close it and re-create either: 1) a fake
  483. // stream to prevent local audio output, or 2) a normal AudioOutputStream.
  484. if (stream_) {
  485. const bool restore_playback = (state_ == kPlaying);
  486. RecreateStream(RecreateReason::LOCAL_OUTPUT_TOGGLE);
  487. if (state_ == kCreated && restore_playback)
  488. StartStream();
  489. }
  490. }
  491. void OutputController::ProcessDeviceChange() {
  492. DCHECK(task_runner_->BelongsToCurrentThread());
  493. SendLogMessage("%s([state=%s])", __func__, StateToString(state_));
  494. TRACE_EVENT0("audio", "OutputController::ProcessDeviceChange");
  495. DCHECK(!disable_local_output_);
  496. // TODO(dalecurtis): Notify the renderer side that a device change has
  497. // occurred. Currently querying the hardware information here will lead to
  498. // crashes on OSX. See http://crbug.com/158170.
  499. const bool restore_playback = (state_ == kPlaying);
  500. RecreateStream(RecreateReason::DEVICE_CHANGE);
  501. if (state_ == kCreated && restore_playback)
  502. StartStream();
  503. }
  504. std::pair<float, bool> OutputController::ReadCurrentPowerAndClip() {
  505. DCHECK(will_monitor_audio_levels());
  506. return power_monitor_.ReadCurrentPowerAndClip();
  507. }
  508. } // namespace audio