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 
5 #include "media/audio/audio_manager_base.h"
6 
7 #include <memory>
8 
9 #include "base/bind.h"
10 #include "base/callback_helpers.h"
11 #include "base/command_line.h"
12 #include "base/macros.h"
13 #include "base/metrics/histogram_macros.h"
14 #include "base/optional.h"
15 #include "base/single_thread_task_runner.h"
16 #include "base/strings/string_number_conversions.h"
17 #include "base/strings/stringprintf.h"
18 #include "base/threading/thread_task_runner_handle.h"
19 #include "build/build_config.h"
20 #include "build/buildflag.h"
21 #include "media/audio/audio_device_description.h"
22 #include "media/audio/audio_output_dispatcher_impl.h"
23 #include "media/audio/audio_output_proxy.h"
24 #include "media/audio/audio_output_resampler.h"
25 #include "media/audio/fake_audio_input_stream.h"
26 #include "media/audio/fake_audio_output_stream.h"
27 #include "media/base/media_switches.h"
28 
29 #include "base/logging.h"
30 #include "build/chromeos_buildflags.h"
31 #include "media/audio/audio_input_stream_data_interceptor.h"
32 
33 namespace media {
34 
35 namespace {
36 
37 const int kStreamCloseDelaySeconds = 5;
38 
39 // Default maximum number of output streams that can be open simultaneously
40 // for all platforms.
41 const int kDefaultMaxOutputStreams = 16;
42 
43 // Default maximum number of input streams that can be open simultaneously
44 // for all platforms.
45 const int kMaxInputStreams = 16;
46 
47 const int kMaxInputChannels = 3;
48 
49 // Helper function to pass as callback when the audio debug recording is not
50 // enabled.
GetNullptrAudioDebugRecorder(const AudioParameters & params)51 std::unique_ptr<AudioDebugRecorder> GetNullptrAudioDebugRecorder(
52     const AudioParameters& params) {
53   return nullptr;
54 }
55 
56 // This enum must match the numbering for AudioOutputProxyStreamFormat in
57 // enums.xml. Do not reorder or remove items, only add new items before
58 // STREAM_FORMAT_MAX.
59 enum StreamFormat {
60   STREAM_FORMAT_BITSTREAM = 0,
61   STREAM_FORMAT_PCM_LINEAR = 1,
62   STREAM_FORMAT_PCM_LOW_LATENCY = 2,
63   STREAM_FORMAT_PCM_LOW_LATENCY_FALLBACK_TO_FAKE = 3,
64   STREAM_FORMAT_FAKE = 4,
65   STREAM_FORMAT_MAX = 4,
66 };
67 
68 PRINTF_FORMAT(2, 3)
SendLogMessage(const AudioManagerBase::LogCallback & callback,const char * format,...)69 void SendLogMessage(const AudioManagerBase::LogCallback& callback,
70                     const char* format,
71                     ...) {
72   if (callback.is_null())
73     return;
74   va_list args;
75   va_start(args, format);
76   callback.Run("AMB::" + base::StringPrintV(format, args));
77   va_end(args);
78 }
79 
80 }  // namespace
81 
82 struct AudioManagerBase::DispatcherParams {
DispatcherParamsmedia::AudioManagerBase::DispatcherParams83   DispatcherParams(const AudioParameters& input,
84                    const AudioParameters& output,
85                    const std::string& output_device_id)
86       : input_params(input),
87         output_params(output),
88         output_device_id(output_device_id) {}
89   ~DispatcherParams() = default;
90 
91   const AudioParameters input_params;
92   const AudioParameters output_params;
93   const std::string output_device_id;
94   std::unique_ptr<AudioOutputDispatcher> dispatcher;
95 
96  private:
97   DISALLOW_COPY_AND_ASSIGN(DispatcherParams);
98 };
99 
100 class AudioManagerBase::CompareByParams {
101  public:
CompareByParams(const DispatcherParams * dispatcher)102   explicit CompareByParams(const DispatcherParams* dispatcher)
103       : dispatcher_(dispatcher) {}
operator ()(const std::unique_ptr<DispatcherParams> & dispatcher_in) const104   bool operator()(
105       const std::unique_ptr<DispatcherParams>& dispatcher_in) const {
106     // We will reuse the existing dispatcher when:
107     // 1) Unified IO is not used, input_params and output_params of the
108     //    existing dispatcher are the same as the requested dispatcher.
109     // 2) Unified IO is used, input_params and output_params of the existing
110     //    dispatcher are the same as the request dispatcher.
111     return (dispatcher_->input_params.Equals(dispatcher_in->input_params) &&
112             dispatcher_->output_params.Equals(dispatcher_in->output_params) &&
113             dispatcher_->output_device_id == dispatcher_in->output_device_id);
114   }
115 
116  private:
117   const DispatcherParams* dispatcher_;
118 };
119 
AudioManagerBase(std::unique_ptr<AudioThread> audio_thread,AudioLogFactory * audio_log_factory)120 AudioManagerBase::AudioManagerBase(std::unique_ptr<AudioThread> audio_thread,
121                                    AudioLogFactory* audio_log_factory)
122     : AudioManager(std::move(audio_thread)),
123       max_num_output_streams_(kDefaultMaxOutputStreams),
124       num_output_streams_(0),
125       // TODO(dalecurtis): Switch this to an base::ObserverListThreadSafe, so we
126       // don't block the UI thread when swapping devices.
127       output_listeners_(base::ObserverListPolicy::EXISTING_ONLY),
128       audio_log_factory_(audio_log_factory) {}
129 
~AudioManagerBase()130 AudioManagerBase::~AudioManagerBase() {
131   // All the output streams should have been deleted.
132   CHECK_EQ(0, num_output_streams_);
133   // All the input streams should have been deleted.
134   CHECK(input_streams_.empty());
135 }
136 
GetAudioInputDeviceDescriptions(AudioDeviceDescriptions * device_descriptions)137 void AudioManagerBase::GetAudioInputDeviceDescriptions(
138     AudioDeviceDescriptions* device_descriptions) {
139   CHECK(GetTaskRunner()->BelongsToCurrentThread());
140   GetAudioDeviceDescriptions(device_descriptions,
141                              &AudioManagerBase::GetAudioInputDeviceNames,
142                              &AudioManagerBase::GetDefaultInputDeviceID,
143                              &AudioManagerBase::GetCommunicationsInputDeviceID,
144                              &AudioManagerBase::GetGroupIDInput);
145 }
146 
GetAudioOutputDeviceDescriptions(AudioDeviceDescriptions * device_descriptions)147 void AudioManagerBase::GetAudioOutputDeviceDescriptions(
148     AudioDeviceDescriptions* device_descriptions) {
149   CHECK(GetTaskRunner()->BelongsToCurrentThread());
150   GetAudioDeviceDescriptions(device_descriptions,
151                              &AudioManagerBase::GetAudioOutputDeviceNames,
152                              &AudioManagerBase::GetDefaultOutputDeviceID,
153                              &AudioManagerBase::GetCommunicationsOutputDeviceID,
154                              &AudioManagerBase::GetGroupIDOutput);
155 }
156 
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 &))157 void AudioManagerBase::GetAudioDeviceDescriptions(
158     AudioDeviceDescriptions* device_descriptions,
159     void (AudioManagerBase::*get_device_names)(AudioDeviceNames*),
160     std::string (AudioManagerBase::*get_default_device_id)(),
161     std::string (AudioManagerBase::*get_communications_device_id)(),
162     std::string (AudioManagerBase::*get_group_id)(const std::string&)) {
163   CHECK(GetTaskRunner()->BelongsToCurrentThread());
164   AudioDeviceNames device_names;
165   (this->*get_device_names)(&device_names);
166   std::string real_default_device_id = (this->*get_default_device_id)();
167   std::string real_communications_device_id =
168       (this->*get_communications_device_id)();
169   std::string real_default_name;
170   std::string real_communications_name;
171 
172   // Find the names for the real devices that are mapped to the default and
173   // communications devices.
174   for (const auto& name : device_names) {
175     if (name.unique_id == real_default_device_id)
176       real_default_name = name.device_name;
177     if (name.unique_id == real_communications_device_id)
178       real_communications_name = name.device_name;
179   }
180 
181   for (auto& name : device_names) {
182     if (AudioDeviceDescription::IsDefaultDevice(name.unique_id))
183       name.device_name = real_default_name;
184     else if (AudioDeviceDescription::IsCommunicationsDevice(name.unique_id))
185       name.device_name = real_communications_name;
186     std::string group_id = (this->*get_group_id)(name.unique_id);
187     device_descriptions->emplace_back(std::move(name.device_name),
188                                       std::move(name.unique_id),
189                                       std::move(group_id));
190   }
191 }
192 
MakeAudioOutputStream(const AudioParameters & params,const std::string & device_id,const LogCallback & log_callback)193 AudioOutputStream* AudioManagerBase::MakeAudioOutputStream(
194     const AudioParameters& params,
195     const std::string& device_id,
196     const LogCallback& log_callback) {
197   CHECK(GetTaskRunner()->BelongsToCurrentThread());
198   DCHECK(params.IsValid());
199 
200   if (base::CommandLine::ForCurrentProcess()->HasSwitch(
201           switches::kFailAudioStreamCreation)) {
202     return nullptr;
203   }
204 
205   SendLogMessage(log_callback, "%s({device_id=%s}, {params=[%s]})", __func__,
206                  device_id.c_str(), params.AsHumanReadableString().c_str());
207 
208   // Limit the number of audio streams opened. This is to prevent using
209   // excessive resources for a large number of audio streams. More
210   // importantly it prevents instability on certain systems.
211   // See bug: http://crbug.com/30242.
212   if (num_output_streams_ >= max_num_output_streams_) {
213     LOG(ERROR) << "Number of opened output audio streams "
214                << num_output_streams_ << " exceed the max allowed number "
215                << max_num_output_streams_;
216     return nullptr;
217   }
218 
219   AudioOutputStream* stream;
220   switch (params.format()) {
221     case AudioParameters::AUDIO_PCM_LINEAR:
222       DCHECK(AudioDeviceDescription::IsDefaultDevice(device_id))
223           << "AUDIO_PCM_LINEAR supports only the default device.";
224       stream = MakeLinearOutputStream(params, log_callback);
225       break;
226     case AudioParameters::AUDIO_PCM_LOW_LATENCY:
227       stream = MakeLowLatencyOutputStream(params, device_id, log_callback);
228       break;
229     case AudioParameters::AUDIO_BITSTREAM_AC3:
230     case AudioParameters::AUDIO_BITSTREAM_EAC3:
231       stream = MakeBitstreamOutputStream(params, device_id, log_callback);
232       break;
233     case AudioParameters::AUDIO_FAKE:
234       stream = FakeAudioOutputStream::MakeFakeStream(this, params);
235       break;
236     default:
237       stream = nullptr;
238       break;
239   }
240 
241   if (stream) {
242     ++num_output_streams_;
243     SendLogMessage(log_callback, "%s => (number of streams=%d)", __func__,
244                    output_stream_count());
245   }
246 
247   return stream;
248 }
249 
MakeBitstreamOutputStream(const AudioParameters & params,const std::string & device_id,const LogCallback & log_callback)250 AudioOutputStream* AudioManagerBase::MakeBitstreamOutputStream(
251     const AudioParameters& params,
252     const std::string& device_id,
253     const LogCallback& log_callback) {
254   return nullptr;
255 }
256 
MakeAudioInputStream(const AudioParameters & params,const std::string & device_id,const LogCallback & log_callback)257 AudioInputStream* AudioManagerBase::MakeAudioInputStream(
258     const AudioParameters& params,
259     const std::string& device_id,
260     const LogCallback& log_callback) {
261   CHECK(GetTaskRunner()->BelongsToCurrentThread());
262 
263   if (base::CommandLine::ForCurrentProcess()->HasSwitch(
264           switches::kFailAudioStreamCreation)) {
265     return nullptr;
266   }
267 
268   SendLogMessage(log_callback, "%s({device_id=%s}, {params=[%s]})", __func__,
269                  device_id.c_str(), params.AsHumanReadableString().c_str());
270 
271   if (!params.IsValid() || (params.channels() > kMaxInputChannels) ||
272       device_id.empty()) {
273     DLOG(ERROR) << "Audio parameters are invalid for device " << device_id
274                 << ", params: " << params.AsHumanReadableString();
275     return nullptr;
276   }
277 
278   if (input_stream_count() >= kMaxInputStreams) {
279     LOG(ERROR) << "Number of opened input audio streams "
280                << input_stream_count() << " exceed the max allowed number "
281                << kMaxInputStreams;
282     return nullptr;
283   }
284 
285   DVLOG(2) << "Creating a new AudioInputStream with buffer size = "
286            << params.frames_per_buffer();
287 
288   AudioInputStream* stream;
289   switch (params.format()) {
290     case AudioParameters::AUDIO_PCM_LINEAR:
291       stream = MakeLinearInputStream(params, device_id, log_callback);
292       break;
293     case AudioParameters::AUDIO_PCM_LOW_LATENCY:
294       stream = MakeLowLatencyInputStream(params, device_id, log_callback);
295       break;
296     case AudioParameters::AUDIO_FAKE:
297       stream = FakeAudioInputStream::MakeFakeStream(this, params);
298       break;
299     default:
300       stream = nullptr;
301       break;
302   }
303 
304   if (stream) {
305     input_streams_.insert(stream);
306     if (!log_callback.is_null()) {
307       SendLogMessage(log_callback, "%s => (number of streams=%d)", __func__,
308                      input_stream_count());
309     }
310 
311     if (!params.IsBitstreamFormat() && debug_recording_manager_) {
312       // Using unretained for |debug_recording_manager_| is safe since it
313       // outlives the audio thread, on which streams are operated.
314       // Note: The AudioInputStreamDataInterceptor takes ownership of the
315       // created stream and cleans it up when it is Close()d, transparently to
316       // the user of the stream. I the case where the audio manager closes the
317       // stream (Mac), this will result in a dangling pointer.
318       stream = new AudioInputStreamDataInterceptor(
319           base::BindRepeating(
320               &AudioDebugRecordingManager::RegisterDebugRecordingSource,
321               base::Unretained(debug_recording_manager_.get()),
322               AudioDebugRecordingStreamType::kInput, params),
323           stream);
324     }
325   }
326 
327   return stream;
328 }
329 
MakeAudioOutputStreamProxy(const AudioParameters & params,const std::string & device_id)330 AudioOutputStream* AudioManagerBase::MakeAudioOutputStreamProxy(
331     const AudioParameters& params,
332     const std::string& device_id) {
333   CHECK(GetTaskRunner()->BelongsToCurrentThread());
334   DCHECK(params.IsValid());
335   base::Optional<StreamFormat> uma_stream_format;
336 
337   // If the caller supplied an empty device id to select the default device,
338   // we fetch the actual device id of the default device so that the lookup
339   // will find the correct device regardless of whether it was opened as
340   // "default" or via the specific id.
341   // NOTE: Implementations that don't yet support opening non-default output
342   // devices may return an empty string from GetDefaultOutputDeviceID().
343   std::string output_device_id =
344       AudioDeviceDescription::IsDefaultDevice(device_id)
345           ?
346 #if BUILDFLAG(IS_ASH)
347           // On ChromeOS, it is expected that, if the default device is given,
348           // no specific device ID should be used since the actual output device
349           // should change dynamically if the system default device changes.
350           // See http://crbug.com/750614.
351           std::string()
352 #else
353           GetDefaultOutputDeviceID()
354 #endif
355           : device_id;
356 
357   // If we're not using AudioOutputResampler our output parameters are the same
358   // as our input parameters.
359   AudioParameters output_params = params;
360 
361   // If audio has been disabled force usage of a fake audio stream.
362   if (base::CommandLine::ForCurrentProcess()->HasSwitch(
363           switches::kDisableAudioOutput)) {
364     output_params.set_format(AudioParameters::AUDIO_FAKE);
365   }
366 
367   if (params.format() == AudioParameters::AUDIO_PCM_LOW_LATENCY &&
368       output_params.format() != AudioParameters::AUDIO_FAKE) {
369     output_params =
370         GetPreferredOutputStreamParameters(output_device_id, params);
371 
372     // Ensure we only pass on valid output parameters.
373     if (output_params.IsValid()) {
374       if (params.effects() & AudioParameters::MULTIZONE) {
375         // Never turn off the multizone effect even if it is not preferred.
376         output_params.set_effects(output_params.effects() |
377                                   AudioParameters::MULTIZONE);
378       }
379       if (params.effects() != output_params.effects()) {
380         // Turn off effects that weren't requested.
381         output_params.set_effects(params.effects() & output_params.effects());
382       }
383 
384       uma_stream_format = STREAM_FORMAT_PCM_LOW_LATENCY;
385     } else {
386       // We've received invalid audio output parameters, so switch to a mock
387       // output device based on the input parameters.  This may happen if the OS
388       // provided us junk values for the hardware configuration.
389       LOG(ERROR) << "Invalid audio output parameters received; using fake "
390                  << "audio path: " << output_params.AsHumanReadableString();
391 
392       // Tell the AudioManager to create a fake output device.
393       output_params = params;
394       output_params.set_format(AudioParameters::AUDIO_FAKE);
395       uma_stream_format = STREAM_FORMAT_PCM_LOW_LATENCY_FALLBACK_TO_FAKE;
396     }
397 
398     output_params.set_latency_tag(params.latency_tag());
399   } else {
400     switch (output_params.format()) {
401       case AudioParameters::AUDIO_PCM_LINEAR:
402         uma_stream_format = STREAM_FORMAT_PCM_LINEAR;
403         break;
404       case AudioParameters::AUDIO_FAKE:
405         uma_stream_format = STREAM_FORMAT_FAKE;
406         break;
407       default:
408         if (output_params.IsBitstreamFormat())
409           uma_stream_format = STREAM_FORMAT_BITSTREAM;
410         else
411           NOTREACHED();
412     }
413   }
414 
415   if (uma_stream_format) {
416     UMA_HISTOGRAM_ENUMERATION("Media.AudioOutputStreamProxy.StreamFormat",
417                               *uma_stream_format, STREAM_FORMAT_MAX + 1);
418   } else {
419     NOTREACHED();
420   }
421 
422   std::unique_ptr<DispatcherParams> dispatcher_params =
423       std::make_unique<DispatcherParams>(params, output_params,
424                                          output_device_id);
425 
426   auto it = std::find_if(output_dispatchers_.begin(), output_dispatchers_.end(),
427                          CompareByParams(dispatcher_params.get()));
428   if (it != output_dispatchers_.end())
429     return (*it)->dispatcher->CreateStreamProxy();
430 
431   const base::TimeDelta kCloseDelay =
432       base::TimeDelta::FromSeconds(kStreamCloseDelaySeconds);
433   std::unique_ptr<AudioOutputDispatcher> dispatcher;
434   if (output_params.format() != AudioParameters::AUDIO_FAKE &&
435       !output_params.IsBitstreamFormat()) {
436     // Using unretained for |debug_recording_manager_| is safe since it
437     // outlives the dispatchers (cleared in ShutdownOnAudioThread()).
438     dispatcher = std::make_unique<AudioOutputResampler>(
439         this, params, output_params, output_device_id, kCloseDelay,
440         debug_recording_manager_
441             ? base::BindRepeating(
442                   &AudioDebugRecordingManager::RegisterDebugRecordingSource,
443                   base::Unretained(debug_recording_manager_.get()),
444                   AudioDebugRecordingStreamType::kOutput)
445             : base::BindRepeating(&GetNullptrAudioDebugRecorder));
446   } else {
447     dispatcher = std::make_unique<AudioOutputDispatcherImpl>(
448         this, output_params, output_device_id, kCloseDelay);
449   }
450 
451   dispatcher_params->dispatcher = std::move(dispatcher);
452   output_dispatchers_.push_back(std::move(dispatcher_params));
453   return output_dispatchers_.back()->dispatcher->CreateStreamProxy();
454 }
455 
GetAudioInputDeviceNames(AudioDeviceNames * device_names)456 void AudioManagerBase::GetAudioInputDeviceNames(
457     AudioDeviceNames* device_names) {
458 }
459 
GetAudioOutputDeviceNames(AudioDeviceNames * device_names)460 void AudioManagerBase::GetAudioOutputDeviceNames(
461     AudioDeviceNames* device_names) {
462 }
463 
ReleaseOutputStream(AudioOutputStream * stream)464 void AudioManagerBase::ReleaseOutputStream(AudioOutputStream* stream) {
465   CHECK(GetTaskRunner()->BelongsToCurrentThread());
466   DCHECK(stream);
467   CHECK_GT(num_output_streams_, 0);
468   // TODO(xians) : Have a clearer destruction path for the AudioOutputStream.
469   // For example, pass the ownership to AudioManager so it can delete the
470   // streams.
471   --num_output_streams_;
472   delete stream;
473 }
474 
ReleaseInputStream(AudioInputStream * stream)475 void AudioManagerBase::ReleaseInputStream(AudioInputStream* stream) {
476   CHECK(GetTaskRunner()->BelongsToCurrentThread());
477   DCHECK(stream);
478   // TODO(xians) : Have a clearer destruction path for the AudioInputStream.
479   CHECK_EQ(1u, input_streams_.erase(stream));
480   delete stream;
481 }
482 
ShutdownOnAudioThread()483 void AudioManagerBase::ShutdownOnAudioThread() {
484   DCHECK(GetTaskRunner()->BelongsToCurrentThread());
485 
486   // Close all output streams.
487   output_dispatchers_.clear();
488 }
489 
AddOutputDeviceChangeListener(AudioDeviceListener * listener)490 void AudioManagerBase::AddOutputDeviceChangeListener(
491     AudioDeviceListener* listener) {
492   DCHECK(GetTaskRunner()->BelongsToCurrentThread());
493   output_listeners_.AddObserver(listener);
494 }
495 
RemoveOutputDeviceChangeListener(AudioDeviceListener * listener)496 void AudioManagerBase::RemoveOutputDeviceChangeListener(
497     AudioDeviceListener* listener) {
498   DCHECK(GetTaskRunner()->BelongsToCurrentThread());
499   output_listeners_.RemoveObserver(listener);
500 }
501 
NotifyAllOutputDeviceChangeListeners()502 void AudioManagerBase::NotifyAllOutputDeviceChangeListeners() {
503   DCHECK(GetTaskRunner()->BelongsToCurrentThread());
504   DVLOG(1) << "Firing OnDeviceChange() notifications.";
505   for (auto& observer : output_listeners_)
506     observer.OnDeviceChange();
507 }
508 
GetDefaultOutputStreamParameters()509 AudioParameters AudioManagerBase::GetDefaultOutputStreamParameters() {
510   return GetPreferredOutputStreamParameters(GetDefaultOutputDeviceID(),
511       AudioParameters());
512 }
513 
GetOutputStreamParameters(const std::string & device_id)514 AudioParameters AudioManagerBase::GetOutputStreamParameters(
515     const std::string& device_id) {
516   return GetPreferredOutputStreamParameters(device_id,
517       AudioParameters());
518 }
519 
GetInputStreamParameters(const std::string & device_id)520 AudioParameters AudioManagerBase::GetInputStreamParameters(
521     const std::string& device_id) {
522   NOTREACHED();
523   return AudioParameters();
524 }
525 
GetAssociatedOutputDeviceID(const std::string & input_device_id)526 std::string AudioManagerBase::GetAssociatedOutputDeviceID(
527     const std::string& input_device_id) {
528   return std::string();
529 }
530 
GetGroupIDOutput(const std::string & output_device_id)531 std::string AudioManagerBase::GetGroupIDOutput(
532     const std::string& output_device_id) {
533   if (output_device_id == AudioDeviceDescription::kDefaultDeviceId) {
534     std::string real_device_id = GetDefaultOutputDeviceID();
535     if (!real_device_id.empty())
536       return real_device_id;
537   } else if (output_device_id ==
538              AudioDeviceDescription::kCommunicationsDeviceId) {
539     std::string real_device_id = GetCommunicationsOutputDeviceID();
540     if (!real_device_id.empty())
541       return real_device_id;
542   }
543   return output_device_id;
544 }
545 
GetGroupIDInput(const std::string & input_device_id)546 std::string AudioManagerBase::GetGroupIDInput(
547     const std::string& input_device_id) {
548   const std::string& real_input_device_id =
549       input_device_id == AudioDeviceDescription::kDefaultDeviceId
550           ? GetDefaultInputDeviceID()
551           : input_device_id == AudioDeviceDescription::kCommunicationsDeviceId
552                 ? GetCommunicationsInputDeviceID()
553                 : input_device_id;
554   std::string output_device_id =
555       GetAssociatedOutputDeviceID(real_input_device_id);
556   if (output_device_id.empty()) {
557     // Some characters are added to avoid accidentally
558     // giving the input the same group id as an output.
559     return real_input_device_id + "input";
560   }
561   return GetGroupIDOutput(output_device_id);
562 }
563 
CloseAllInputStreams()564 void AudioManagerBase::CloseAllInputStreams() {
565   for (auto iter = input_streams_.begin(); iter != input_streams_.end();) {
566     // Note: Closing the stream will invalidate the iterator.
567     // Increment the iterator before closing the stream.
568     AudioInputStream* stream = *iter++;
569     stream->Close();
570   }
571   CHECK(input_streams_.empty());
572 }
573 
GetDefaultInputDeviceID()574 std::string AudioManagerBase::GetDefaultInputDeviceID() {
575   return std::string();
576 }
577 
GetDefaultOutputDeviceID()578 std::string AudioManagerBase::GetDefaultOutputDeviceID() {
579   return std::string();
580 }
581 
GetCommunicationsInputDeviceID()582 std::string AudioManagerBase::GetCommunicationsInputDeviceID() {
583   return std::string();
584 }
585 
GetCommunicationsOutputDeviceID()586 std::string AudioManagerBase::GetCommunicationsOutputDeviceID() {
587   return std::string();
588 }
589 
590 // static
GetUserBufferSize()591 int AudioManagerBase::GetUserBufferSize() {
592   const base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess();
593   int buffer_size = 0;
594   std::string buffer_size_str(cmd_line->GetSwitchValueASCII(
595       switches::kAudioBufferSize));
596   if (base::StringToInt(buffer_size_str, &buffer_size) && buffer_size > 0)
597     return buffer_size;
598 
599   return 0;
600 }
601 
CreateAudioLog(AudioLogFactory::AudioComponent component,int component_id)602 std::unique_ptr<AudioLog> AudioManagerBase::CreateAudioLog(
603     AudioLogFactory::AudioComponent component,
604     int component_id) {
605   return audio_log_factory_->CreateAudioLog(component, component_id);
606 }
607 
InitializeDebugRecording()608 void AudioManagerBase::InitializeDebugRecording() {
609   if (!GetTaskRunner()->BelongsToCurrentThread()) {
610     // AudioManager is deleted on the audio thread, so it's safe to post
611     // unretained.
612     GetTaskRunner()->PostTask(
613         FROM_HERE, base::BindOnce(&AudioManagerBase::InitializeDebugRecording,
614                                   base::Unretained(this)));
615     return;
616   }
617 
618   DCHECK(!debug_recording_manager_);
619   debug_recording_manager_ = CreateAudioDebugRecordingManager(GetTaskRunner());
620 }
621 
622 std::unique_ptr<AudioDebugRecordingManager>
CreateAudioDebugRecordingManager(scoped_refptr<base::SingleThreadTaskRunner> task_runner)623 AudioManagerBase::CreateAudioDebugRecordingManager(
624     scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
625   return std::make_unique<AudioDebugRecordingManager>(std::move(task_runner));
626 }
627 
GetAudioDebugRecordingManager()628 AudioDebugRecordingManager* AudioManagerBase::GetAudioDebugRecordingManager() {
629   DCHECK(GetTaskRunner()->BelongsToCurrentThread());
630   return debug_recording_manager_.get();
631 }
632 
633 }  // namespace media
634