audio_manager_chromeos.cc 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643
  1. // Copyright 2020 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 "media/audio/cras/audio_manager_chromeos.h"
  5. #include <stddef.h>
  6. #include <algorithm>
  7. #include <map>
  8. #include <utility>
  9. #include "base/bind.h"
  10. #include "base/check_op.h"
  11. #include "base/command_line.h"
  12. #include "base/environment.h"
  13. #include "base/metrics/field_trial_params.h"
  14. #include "base/nix/xdg_util.h"
  15. #include "base/strings/string_number_conversions.h"
  16. #include "base/synchronization/waitable_event.h"
  17. #include "base/system/sys_info.h"
  18. #include "base/threading/thread_task_runner_handle.h"
  19. #include "chromeos/ash/components/audio/audio_device.h"
  20. #include "chromeos/ash/components/audio/cras_audio_handler.h"
  21. #include "media/audio/audio_device_description.h"
  22. #include "media/audio/audio_features.h"
  23. #include "media/audio/cras/cras_input.h"
  24. #include "media/audio/cras/cras_unified.h"
  25. #include "media/base/channel_layout.h"
  26. #include "media/base/limits.h"
  27. #include "media/base/localized_strings.h"
  28. namespace media {
  29. namespace {
  30. using ::ash::AudioDevice;
  31. using ::ash::AudioDeviceList;
  32. using ::ash::CrasAudioHandler;
  33. // Default sample rate for input and output streams.
  34. const int kDefaultSampleRate = 48000;
  35. // Default input buffer size.
  36. const int kDefaultInputBufferSize = 1024;
  37. const char kInternalInputVirtualDevice[] = "Built-in mic";
  38. const char kInternalOutputVirtualDevice[] = "Built-in speaker";
  39. const char kHeadphoneLineOutVirtualDevice[] = "Headphone/Line Out";
  40. // Used for the Media.CrosBeamformingDeviceState histogram, currently not used
  41. // since beamforming is disabled.
  42. enum CrosBeamformingDeviceState {
  43. BEAMFORMING_DEFAULT_ENABLED = 0,
  44. BEAMFORMING_USER_ENABLED,
  45. BEAMFORMING_DEFAULT_DISABLED,
  46. BEAMFORMING_USER_DISABLED,
  47. BEAMFORMING_STATE_MAX = BEAMFORMING_USER_DISABLED
  48. };
  49. const AudioDevice* GetDeviceFromId(const AudioDeviceList& devices,
  50. uint64_t id) {
  51. for (const auto& device : devices) {
  52. if (device.id == id) {
  53. return &device;
  54. }
  55. }
  56. return nullptr;
  57. }
  58. // Process |device_list| that two shares the same dev_index by creating a
  59. // virtual device name for them.
  60. void ProcessVirtualDeviceName(AudioDeviceNames* device_names,
  61. const AudioDeviceList& device_list) {
  62. DCHECK_EQ(2U, device_list.size());
  63. if (device_list[0].type == chromeos::AudioDeviceType::kLineout ||
  64. device_list[1].type == chromeos::AudioDeviceType::kLineout) {
  65. device_names->emplace_back(kHeadphoneLineOutVirtualDevice,
  66. base::NumberToString(device_list[0].id));
  67. } else if (device_list[0].type ==
  68. chromeos::AudioDeviceType::kInternalSpeaker ||
  69. device_list[1].type ==
  70. chromeos::AudioDeviceType::kInternalSpeaker) {
  71. device_names->emplace_back(kInternalOutputVirtualDevice,
  72. base::NumberToString(device_list[0].id));
  73. } else {
  74. DCHECK(device_list[0].IsInternalMic() || device_list[1].IsInternalMic());
  75. device_names->emplace_back(kInternalInputVirtualDevice,
  76. base::NumberToString(device_list[0].id));
  77. }
  78. }
  79. // Collects flags values for whether, and in what way, the AEC, NS or AGC
  80. // effects should be enforced in spite of them not being flagged as supported by
  81. // the board.
  82. void RetrieveSystemEffectFeatures(bool& enforce_system_aec,
  83. bool& enforce_system_ns,
  84. bool& enforce_system_agc,
  85. bool& tuned_system_aec_allowed) {
  86. const bool enforce_system_aec_ns_agc_feature =
  87. base::FeatureList::IsEnabled(features::kCrOSEnforceSystemAecNsAgc);
  88. const bool enforce_system_aec_ns_feature =
  89. base::FeatureList::IsEnabled(features::kCrOSEnforceSystemAecNs);
  90. const bool enforce_system_aec_agc_feature =
  91. base::FeatureList::IsEnabled(features::kCrOSEnforceSystemAecAgc);
  92. const bool enforce_system_aec_feature =
  93. base::FeatureList::IsEnabled(features::kCrOSEnforceSystemAec);
  94. enforce_system_aec =
  95. enforce_system_aec_feature || enforce_system_aec_ns_agc_feature ||
  96. enforce_system_aec_ns_feature || enforce_system_aec_agc_feature;
  97. enforce_system_ns =
  98. enforce_system_aec_ns_agc_feature || enforce_system_aec_ns_feature;
  99. enforce_system_agc =
  100. enforce_system_aec_ns_agc_feature || enforce_system_aec_agc_feature;
  101. tuned_system_aec_allowed =
  102. base::FeatureList::IsEnabled(features::kCrOSSystemAEC);
  103. }
  104. // Checks if a system AEC with a specific group ID is flagged to be deactivated
  105. // by the field trial.
  106. bool IsSystemAecDeactivated(int aec_group_id) {
  107. return base::GetFieldTrialParamByFeatureAsBool(
  108. features::kCrOSSystemAECDeactivatedGroups, std::to_string(aec_group_id),
  109. false);
  110. }
  111. // Checks if the board with `aec_group_id` is flagged by the field trial to not
  112. // allow using DSP-based AEC effect.
  113. bool IsDspBasedAecDeactivated(int aec_group_id) {
  114. return base::GetFieldTrialParamByFeatureAsBool(
  115. features::kCrOSDspBasedAecDeactivatedGroups,
  116. std::to_string(aec_group_id), false) ||
  117. !base::FeatureList::IsEnabled(features::kCrOSDspBasedAecAllowed);
  118. }
  119. // Checks if the board with `aec_group_id` is flagged by the field trial to not
  120. // allow using DSP-based NS effect.
  121. bool IsDspBasedNsDeactivated(int aec_group_id) {
  122. return base::GetFieldTrialParamByFeatureAsBool(
  123. features::kCrOSDspBasedNsDeactivatedGroups,
  124. std::to_string(aec_group_id), false) ||
  125. !base::FeatureList::IsEnabled(features::kCrOSDspBasedNsAllowed);
  126. }
  127. // Checks if the board with `aec_group_id` is flagged by the field trial to not
  128. // allow using DSP-based AGC effect.
  129. bool IsDspBasedAgcDeactivated(int aec_group_id) {
  130. return base::GetFieldTrialParamByFeatureAsBool(
  131. features::kCrOSDspBasedAgcDeactivatedGroups,
  132. std::to_string(aec_group_id), false) ||
  133. !base::FeatureList::IsEnabled(features::kCrOSDspBasedAgcAllowed);
  134. }
  135. // Specifies which DSP-based effects are allowed based on media constraints and
  136. // any finch field trials.
  137. void SetAllowedDspBasedEffects(int aec_group_id, AudioParameters& params) {
  138. int effects = params.effects();
  139. // Allow AEC to be applied by CRAS on DSP if the AEC is active in CRAS and if
  140. // using the AEC on DSP has not been deactivated by any field trials.
  141. if ((effects & AudioParameters::ECHO_CANCELLER) &&
  142. !IsDspBasedAecDeactivated(aec_group_id)) {
  143. effects = effects | AudioParameters::ALLOW_DSP_ECHO_CANCELLER;
  144. } else {
  145. effects = effects & ~AudioParameters::ALLOW_DSP_ECHO_CANCELLER;
  146. }
  147. // Allow NS to be applied by CRAS on DSP if the NS is active in CRAS and if
  148. // using the NS on DSP has not been deactivated by any field trials.
  149. if ((effects & AudioParameters::NOISE_SUPPRESSION) &&
  150. !IsDspBasedNsDeactivated(aec_group_id)) {
  151. effects = effects | AudioParameters::ALLOW_DSP_NOISE_SUPPRESSION;
  152. } else {
  153. effects = effects & ~AudioParameters::ALLOW_DSP_NOISE_SUPPRESSION;
  154. }
  155. // Allow AGC to be applied by CRAS on DSP if the AGC is active in CRAS and if
  156. // using the AGC on DSP has not been deactivated by any field trials.
  157. if ((effects & AudioParameters::AUTOMATIC_GAIN_CONTROL) &&
  158. !IsDspBasedAgcDeactivated(aec_group_id)) {
  159. effects = effects | AudioParameters::ALLOW_DSP_AUTOMATIC_GAIN_CONTROL;
  160. } else {
  161. effects = effects & ~AudioParameters::ALLOW_DSP_AUTOMATIC_GAIN_CONTROL;
  162. }
  163. params.set_effects(effects);
  164. }
  165. } // namespace
  166. bool AudioManagerChromeOS::HasAudioOutputDevices() {
  167. return true;
  168. }
  169. bool AudioManagerChromeOS::HasAudioInputDevices() {
  170. AudioDeviceList devices;
  171. GetAudioDevices(&devices);
  172. for (size_t i = 0; i < devices.size(); ++i) {
  173. if (devices[i].is_input && devices[i].is_for_simple_usage())
  174. return true;
  175. }
  176. return false;
  177. }
  178. AudioManagerChromeOS::AudioManagerChromeOS(
  179. std::unique_ptr<AudioThread> audio_thread,
  180. AudioLogFactory* audio_log_factory)
  181. : AudioManagerCrasBase(std::move(audio_thread), audio_log_factory),
  182. on_shutdown_(base::WaitableEvent::ResetPolicy::MANUAL,
  183. base::WaitableEvent::InitialState::NOT_SIGNALED),
  184. main_task_runner_(base::ThreadTaskRunnerHandle::Get()),
  185. weak_ptr_factory_(this) {
  186. weak_this_ = weak_ptr_factory_.GetWeakPtr();
  187. }
  188. AudioManagerChromeOS::~AudioManagerChromeOS() = default;
  189. void AudioManagerChromeOS::GetAudioDeviceNamesImpl(
  190. bool is_input,
  191. AudioDeviceNames* device_names) {
  192. DCHECK(device_names->empty());
  193. AudioDeviceList devices;
  194. GetAudioDevices(&devices);
  195. // |dev_idx_map| is a map of dev_index and their audio devices.
  196. std::map<int, AudioDeviceList> dev_idx_map;
  197. for (const auto& device : devices) {
  198. if (device.is_input != is_input || !device.is_for_simple_usage())
  199. continue;
  200. dev_idx_map[dev_index_of(device.id)].push_back(device);
  201. }
  202. for (const auto& [dev_idx, device_list] : dev_idx_map) {
  203. if (1 == device_list.size()) {
  204. const AudioDevice& device = device_list.front();
  205. device_names->emplace_back(device.display_name,
  206. base::NumberToString(device.id));
  207. } else {
  208. // Create virtual device name for audio nodes that share the same device
  209. // index.
  210. ProcessVirtualDeviceName(device_names, device_list);
  211. }
  212. }
  213. if (!device_names->empty())
  214. device_names->push_front(AudioDeviceName::CreateDefault());
  215. }
  216. void AudioManagerChromeOS::GetAudioInputDeviceNames(
  217. AudioDeviceNames* device_names) {
  218. GetAudioDeviceNamesImpl(true, device_names);
  219. }
  220. void AudioManagerChromeOS::GetAudioOutputDeviceNames(
  221. AudioDeviceNames* device_names) {
  222. GetAudioDeviceNamesImpl(false, device_names);
  223. }
  224. AudioParameters AudioManagerChromeOS::GetInputStreamParameters(
  225. const std::string& device_id) {
  226. DCHECK(GetTaskRunner()->BelongsToCurrentThread());
  227. // Retrieve buffer size.
  228. int user_buffer_size = GetUserBufferSize();
  229. user_buffer_size =
  230. user_buffer_size != 0 ? user_buffer_size : kDefaultInputBufferSize;
  231. // Retrieve the board support in terms of APM effects and properties.
  232. const SystemAudioProcessingInfo system_apm_info =
  233. GetSystemApmEffectsSupportedPerBoard();
  234. // TODO(hshi): Fine-tune audio parameters based on |device_id|. The optimal
  235. // parameters for the loopback stream may differ from the default.
  236. return GetStreamParametersForSystem(user_buffer_size, system_apm_info);
  237. }
  238. std::string AudioManagerChromeOS::GetAssociatedOutputDeviceID(
  239. const std::string& input_device_id) {
  240. AudioDeviceList devices;
  241. GetAudioDevices(&devices);
  242. if (input_device_id == AudioDeviceDescription::kDefaultDeviceId) {
  243. // Note: the default input should not be associated to any output, as this
  244. // may lead to accidental uses of a pinned stream.
  245. return "";
  246. }
  247. const std::string device_name =
  248. GetHardwareDeviceFromDeviceId(devices, true, input_device_id);
  249. if (device_name.empty())
  250. return "";
  251. // Now search for an output device with the same device name.
  252. auto output_device_it = std::find_if(
  253. devices.begin(), devices.end(), [device_name](const AudioDevice& device) {
  254. return !device.is_input && device.device_name == device_name;
  255. });
  256. return output_device_it == devices.end()
  257. ? ""
  258. : base::NumberToString(output_device_it->id);
  259. }
  260. std::string AudioManagerChromeOS::GetDefaultInputDeviceID() {
  261. DCHECK(GetTaskRunner()->BelongsToCurrentThread());
  262. return base::NumberToString(GetPrimaryActiveInputNode());
  263. }
  264. std::string AudioManagerChromeOS::GetDefaultOutputDeviceID() {
  265. DCHECK(GetTaskRunner()->BelongsToCurrentThread());
  266. return base::NumberToString(GetPrimaryActiveOutputNode());
  267. }
  268. std::string AudioManagerChromeOS::GetGroupIDOutput(
  269. const std::string& output_device_id) {
  270. AudioDeviceList devices;
  271. GetAudioDevices(&devices);
  272. return GetHardwareDeviceFromDeviceId(devices, false, output_device_id);
  273. }
  274. std::string AudioManagerChromeOS::GetGroupIDInput(
  275. const std::string& input_device_id) {
  276. AudioDeviceList devices;
  277. GetAudioDevices(&devices);
  278. return GetHardwareDeviceFromDeviceId(devices, true, input_device_id);
  279. }
  280. bool AudioManagerChromeOS::Shutdown() {
  281. DCHECK(main_task_runner_->BelongsToCurrentThread());
  282. weak_ptr_factory_.InvalidateWeakPtrs();
  283. on_shutdown_.Signal();
  284. return AudioManager::Shutdown();
  285. }
  286. int AudioManagerChromeOS::GetDefaultOutputBufferSizePerBoard() {
  287. DCHECK(GetTaskRunner()->BelongsToCurrentThread());
  288. int32_t buffer_size = 512;
  289. base::WaitableEvent event(base::WaitableEvent::ResetPolicy::MANUAL,
  290. base::WaitableEvent::InitialState::NOT_SIGNALED);
  291. if (main_task_runner_->BelongsToCurrentThread()) {
  292. // Unittest may use the same thread for audio thread.
  293. GetDefaultOutputBufferSizeOnMainThread(&buffer_size, &event);
  294. } else {
  295. main_task_runner_->PostTask(
  296. FROM_HERE,
  297. base::BindOnce(
  298. &AudioManagerChromeOS::GetDefaultOutputBufferSizeOnMainThread,
  299. weak_this_, base::Unretained(&buffer_size),
  300. base::Unretained(&event)));
  301. }
  302. WaitEventOrShutdown(&event);
  303. return static_cast<int>(buffer_size);
  304. }
  305. AudioManagerChromeOS::SystemAudioProcessingInfo
  306. AudioManagerChromeOS::GetSystemApmEffectsSupportedPerBoard() {
  307. DCHECK(GetTaskRunner()->BelongsToCurrentThread());
  308. base::WaitableEvent event(base::WaitableEvent::ResetPolicy::MANUAL,
  309. base::WaitableEvent::InitialState::NOT_SIGNALED);
  310. SystemAudioProcessingInfo system_apm_info;
  311. if (main_task_runner_->BelongsToCurrentThread()) {
  312. // Unittest may use the same thread for audio thread.
  313. GetSystemApmEffectsSupportedOnMainThread(&system_apm_info, &event);
  314. } else {
  315. // Using base::Unretained is safe here because we wait for callback be
  316. // executed in main thread before local variables are destructed.
  317. main_task_runner_->PostTask(
  318. FROM_HERE,
  319. base::BindOnce(
  320. &AudioManagerChromeOS::GetSystemApmEffectsSupportedOnMainThread,
  321. weak_this_, base::Unretained(&system_apm_info),
  322. base::Unretained(&event)));
  323. }
  324. WaitEventOrShutdown(&event);
  325. return system_apm_info;
  326. }
  327. AudioParameters AudioManagerChromeOS::GetPreferredOutputStreamParameters(
  328. const std::string& output_device_id,
  329. const AudioParameters& input_params) {
  330. DCHECK(GetTaskRunner()->BelongsToCurrentThread());
  331. ChannelLayout channel_layout = CHANNEL_LAYOUT_STEREO;
  332. int sample_rate = kDefaultSampleRate;
  333. int buffer_size = GetUserBufferSize();
  334. if (input_params.IsValid()) {
  335. channel_layout = input_params.channel_layout();
  336. sample_rate = input_params.sample_rate();
  337. if (!buffer_size) // Not user-provided.
  338. buffer_size =
  339. std::min(static_cast<int>(limits::kMaxAudioBufferSize),
  340. std::max(static_cast<int>(limits::kMinAudioBufferSize),
  341. input_params.frames_per_buffer()));
  342. return AudioParameters(
  343. AudioParameters::AUDIO_PCM_LOW_LATENCY, channel_layout, sample_rate,
  344. buffer_size,
  345. AudioParameters::HardwareCapabilities(limits::kMinAudioBufferSize,
  346. limits::kMaxAudioBufferSize));
  347. }
  348. // Get max supported channels from |output_device_id| or the primary active
  349. // one if |output_device_id| is the default device.
  350. uint64_t preferred_device_id;
  351. if (AudioDeviceDescription::IsDefaultDevice(output_device_id)) {
  352. preferred_device_id = GetPrimaryActiveOutputNode();
  353. } else {
  354. if (!base::StringToUint64(output_device_id, &preferred_device_id))
  355. preferred_device_id = 0; // 0 represents invalid |output_device_id|.
  356. }
  357. if (preferred_device_id) {
  358. AudioDeviceList devices;
  359. GetAudioDevices(&devices);
  360. const AudioDevice* device = GetDeviceFromId(devices, preferred_device_id);
  361. if (device && device->is_input == false) {
  362. channel_layout =
  363. GuessChannelLayout(static_cast<int>(device->max_supported_channels));
  364. // Fall-back to old fashion: always fixed to STEREO layout.
  365. if (channel_layout == CHANNEL_LAYOUT_UNSUPPORTED) {
  366. channel_layout = CHANNEL_LAYOUT_STEREO;
  367. }
  368. }
  369. }
  370. if (!buffer_size) // Not user-provided.
  371. buffer_size = GetDefaultOutputBufferSizePerBoard();
  372. return AudioParameters(
  373. AudioParameters::AUDIO_PCM_LOW_LATENCY, channel_layout, sample_rate,
  374. buffer_size,
  375. AudioParameters::HardwareCapabilities(limits::kMinAudioBufferSize,
  376. limits::kMaxAudioBufferSize));
  377. }
  378. bool AudioManagerChromeOS::IsDefault(const std::string& device_id,
  379. bool is_input) {
  380. return AudioDeviceDescription::IsDefaultDevice(device_id);
  381. }
  382. std::string AudioManagerChromeOS::GetHardwareDeviceFromDeviceId(
  383. const AudioDeviceList& devices,
  384. bool is_input,
  385. const std::string& device_id) {
  386. uint64_t u64_device_id = 0;
  387. if (AudioDeviceDescription::IsDefaultDevice(device_id)) {
  388. u64_device_id =
  389. is_input ? GetPrimaryActiveInputNode() : GetPrimaryActiveOutputNode();
  390. } else {
  391. if (!base::StringToUint64(device_id, &u64_device_id))
  392. return "";
  393. }
  394. const AudioDevice* device = GetDeviceFromId(devices, u64_device_id);
  395. return device ? device->device_name : "";
  396. }
  397. void AudioManagerChromeOS::GetAudioDevices(AudioDeviceList* devices) {
  398. DCHECK(GetTaskRunner()->BelongsToCurrentThread());
  399. base::WaitableEvent event(base::WaitableEvent::ResetPolicy::MANUAL,
  400. base::WaitableEvent::InitialState::NOT_SIGNALED);
  401. if (main_task_runner_->BelongsToCurrentThread()) {
  402. GetAudioDevicesOnMainThread(devices, &event);
  403. } else {
  404. main_task_runner_->PostTask(
  405. FROM_HERE,
  406. base::BindOnce(&AudioManagerChromeOS::GetAudioDevicesOnMainThread,
  407. weak_this_, base::Unretained(devices),
  408. base::Unretained(&event)));
  409. }
  410. WaitEventOrShutdown(&event);
  411. }
  412. void AudioManagerChromeOS::GetAudioDevicesOnMainThread(
  413. AudioDeviceList* devices,
  414. base::WaitableEvent* event) {
  415. DCHECK(main_task_runner_->BelongsToCurrentThread());
  416. // CrasAudioHandler is shut down before AudioManagerChromeOS.
  417. if (CrasAudioHandler::Get())
  418. CrasAudioHandler::Get()->GetAudioDevices(devices);
  419. event->Signal();
  420. }
  421. uint64_t AudioManagerChromeOS::GetPrimaryActiveInputNode() {
  422. DCHECK(GetTaskRunner()->BelongsToCurrentThread());
  423. uint64_t device_id = 0;
  424. base::WaitableEvent event(base::WaitableEvent::ResetPolicy::MANUAL,
  425. base::WaitableEvent::InitialState::NOT_SIGNALED);
  426. if (main_task_runner_->BelongsToCurrentThread()) {
  427. GetPrimaryActiveInputNodeOnMainThread(&device_id, &event);
  428. } else {
  429. main_task_runner_->PostTask(
  430. FROM_HERE,
  431. base::BindOnce(
  432. &AudioManagerChromeOS::GetPrimaryActiveInputNodeOnMainThread,
  433. weak_this_, &device_id, &event));
  434. }
  435. WaitEventOrShutdown(&event);
  436. return device_id;
  437. }
  438. uint64_t AudioManagerChromeOS::GetPrimaryActiveOutputNode() {
  439. DCHECK(GetTaskRunner()->BelongsToCurrentThread());
  440. base::WaitableEvent event(base::WaitableEvent::ResetPolicy::MANUAL,
  441. base::WaitableEvent::InitialState::NOT_SIGNALED);
  442. uint64_t device_id = 0;
  443. if (main_task_runner_->BelongsToCurrentThread()) {
  444. // Unittest may use the same thread for audio thread.
  445. GetPrimaryActiveOutputNodeOnMainThread(&device_id, &event);
  446. } else {
  447. main_task_runner_->PostTask(
  448. FROM_HERE,
  449. base::BindOnce(
  450. &AudioManagerChromeOS::GetPrimaryActiveOutputNodeOnMainThread,
  451. weak_this_, base::Unretained(&device_id),
  452. base::Unretained(&event)));
  453. }
  454. WaitEventOrShutdown(&event);
  455. return device_id;
  456. }
  457. void AudioManagerChromeOS::GetPrimaryActiveInputNodeOnMainThread(
  458. uint64_t* active_input_node_id,
  459. base::WaitableEvent* event) {
  460. DCHECK(main_task_runner_->BelongsToCurrentThread());
  461. if (CrasAudioHandler::Get()) {
  462. *active_input_node_id =
  463. CrasAudioHandler::Get()->GetPrimaryActiveInputNode();
  464. }
  465. event->Signal();
  466. }
  467. void AudioManagerChromeOS::GetPrimaryActiveOutputNodeOnMainThread(
  468. uint64_t* active_output_node_id,
  469. base::WaitableEvent* event) {
  470. DCHECK(main_task_runner_->BelongsToCurrentThread());
  471. if (CrasAudioHandler::Get()) {
  472. *active_output_node_id =
  473. CrasAudioHandler::Get()->GetPrimaryActiveOutputNode();
  474. }
  475. event->Signal();
  476. }
  477. void AudioManagerChromeOS::GetDefaultOutputBufferSizeOnMainThread(
  478. int32_t* buffer_size,
  479. base::WaitableEvent* event) {
  480. DCHECK(main_task_runner_->BelongsToCurrentThread());
  481. if (CrasAudioHandler::Get())
  482. CrasAudioHandler::Get()->GetDefaultOutputBufferSize(buffer_size);
  483. event->Signal();
  484. }
  485. void AudioManagerChromeOS::GetSystemApmEffectsSupportedOnMainThread(
  486. SystemAudioProcessingInfo* system_apm_info,
  487. base::WaitableEvent* event) {
  488. DCHECK(main_task_runner_->BelongsToCurrentThread());
  489. if (CrasAudioHandler::Get()) {
  490. system_apm_info->aec_supported =
  491. CrasAudioHandler::Get()->system_aec_supported();
  492. system_apm_info->aec_group_id =
  493. CrasAudioHandler::Get()->system_aec_group_id();
  494. system_apm_info->ns_supported =
  495. CrasAudioHandler::Get()->system_ns_supported();
  496. system_apm_info->agc_supported =
  497. CrasAudioHandler::Get()->system_agc_supported();
  498. }
  499. event->Signal();
  500. }
  501. void AudioManagerChromeOS::WaitEventOrShutdown(base::WaitableEvent* event) {
  502. base::WaitableEvent* waitables[] = {event, &on_shutdown_};
  503. base::WaitableEvent::WaitMany(waitables, std::size(waitables));
  504. }
  505. enum CRAS_CLIENT_TYPE AudioManagerChromeOS::GetClientType() {
  506. return CRAS_CLIENT_TYPE_CHROME;
  507. }
  508. AudioParameters AudioManagerChromeOS::GetStreamParametersForSystem(
  509. int user_buffer_size,
  510. const AudioManagerChromeOS::SystemAudioProcessingInfo& system_apm_info) {
  511. AudioParameters params(
  512. AudioParameters::AUDIO_PCM_LOW_LATENCY, CHANNEL_LAYOUT_STEREO,
  513. kDefaultSampleRate, user_buffer_size,
  514. AudioParameters::HardwareCapabilities(limits::kMinAudioBufferSize,
  515. limits::kMaxAudioBufferSize));
  516. bool enforce_system_aec;
  517. bool enforce_system_ns;
  518. bool enforce_system_agc;
  519. bool tuned_system_aec_allowed;
  520. RetrieveSystemEffectFeatures(enforce_system_aec, enforce_system_ns,
  521. enforce_system_agc, tuned_system_aec_allowed);
  522. // Activation of the system AEC. Allow experimentation with system AEC with
  523. // all devices, but enable it by default on devices that actually support it.
  524. params.set_effects(params.effects() |
  525. AudioParameters::EXPERIMENTAL_ECHO_CANCELLER);
  526. // Rephrase the field aec_supported to properly reflect its meaning in this
  527. // context (since it currently signals whether an CrAS APM with tuned settings
  528. // is available).
  529. const bool tuned_system_apm_available = system_apm_info.aec_supported;
  530. // Don't use the system AEC if it is deactivated for this group ID. Also never
  531. // activate NS nor AGC for this board if the AEC is not activated, since this
  532. // will cause issues for the Browser AEC.
  533. bool use_system_aec =
  534. (tuned_system_apm_available && tuned_system_aec_allowed) ||
  535. enforce_system_aec;
  536. if (!use_system_aec || IsSystemAecDeactivated(system_apm_info.aec_group_id)) {
  537. SetAllowedDspBasedEffects(system_apm_info.aec_group_id, params);
  538. return params;
  539. }
  540. // Activation of the system AEC.
  541. params.set_effects(params.effects() | AudioParameters::ECHO_CANCELLER);
  542. // Don't use system NS or AGC if the AEC has board-specific tunings.
  543. if (!tuned_system_apm_available) {
  544. // Activation of the system NS.
  545. if (system_apm_info.ns_supported || enforce_system_ns) {
  546. params.set_effects(params.effects() | AudioParameters::NOISE_SUPPRESSION);
  547. }
  548. // Activation of the system AGC.
  549. if (system_apm_info.agc_supported || enforce_system_agc) {
  550. params.set_effects(params.effects() |
  551. AudioParameters::AUTOMATIC_GAIN_CONTROL);
  552. }
  553. }
  554. SetAllowedDspBasedEffects(system_apm_info.aec_group_id, params);
  555. return params;
  556. }
  557. } // namespace media