Do not assume that the orientation is PORTRAIT by default.
[chromium-blink-merge.git] / chromeos / audio / cras_audio_handler.cc
blobfd2d92e519457e8970001a1b9aca256f83d036cd
1 // Copyright (c) 2013 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.
5 #include "chromeos/audio/cras_audio_handler.h"
7 #include <algorithm>
8 #include <cmath>
10 #include "base/bind.h"
11 #include "base/bind_helpers.h"
12 #include "base/logging.h"
13 #include "chromeos/audio/audio_devices_pref_handler.h"
14 #include "chromeos/audio/audio_devices_pref_handler_stub.h"
15 #include "chromeos/dbus/dbus_thread_manager.h"
17 using std::max;
18 using std::min;
20 namespace chromeos {
22 namespace {
24 // Default value for unmuting, as a percent in the range [0, 100].
25 // Used when sound is unmuted, but volume was less than kMuteThresholdPercent.
26 const int kDefaultUnmuteVolumePercent = 4;
28 // Volume value which should be considered as muted in range [0, 100].
29 const int kMuteThresholdPercent = 1;
31 static CrasAudioHandler* g_cras_audio_handler = NULL;
33 bool IsSameAudioDevice(const AudioDevice& a, const AudioDevice& b) {
34 return a.id == b.id && a.is_input == b.is_input && a.type == b.type
35 && a.device_name == b.device_name;
38 } // namespace
40 CrasAudioHandler::AudioObserver::AudioObserver() {
43 CrasAudioHandler::AudioObserver::~AudioObserver() {
46 void CrasAudioHandler::AudioObserver::OnOutputVolumeChanged() {
49 void CrasAudioHandler::AudioObserver::OnInputGainChanged() {
52 void CrasAudioHandler::AudioObserver::OnOutputMuteChanged() {
55 void CrasAudioHandler::AudioObserver::OnInputMuteChanged() {
58 void CrasAudioHandler::AudioObserver::OnAudioNodesChanged() {
61 void CrasAudioHandler::AudioObserver::OnActiveOutputNodeChanged() {
64 void CrasAudioHandler::AudioObserver::OnActiveInputNodeChanged() {
67 // static
68 void CrasAudioHandler::Initialize(
69 scoped_refptr<AudioDevicesPrefHandler> audio_pref_handler) {
70 CHECK(!g_cras_audio_handler);
71 g_cras_audio_handler = new CrasAudioHandler(audio_pref_handler);
74 // static
75 void CrasAudioHandler::InitializeForTesting() {
76 CHECK(!g_cras_audio_handler);
77 CrasAudioHandler::Initialize(new AudioDevicesPrefHandlerStub());
80 // static
81 void CrasAudioHandler::Shutdown() {
82 CHECK(g_cras_audio_handler);
83 delete g_cras_audio_handler;
84 g_cras_audio_handler = NULL;
87 // static
88 bool CrasAudioHandler::IsInitialized() {
89 return g_cras_audio_handler != NULL;
92 // static
93 CrasAudioHandler* CrasAudioHandler::Get() {
94 CHECK(g_cras_audio_handler)
95 << "CrasAudioHandler::Get() called before Initialize().";
96 return g_cras_audio_handler;
99 void CrasAudioHandler::AddAudioObserver(AudioObserver* observer) {
100 observers_.AddObserver(observer);
103 void CrasAudioHandler::RemoveAudioObserver(AudioObserver* observer) {
104 observers_.RemoveObserver(observer);
107 bool CrasAudioHandler::IsOutputMuted() {
108 return output_mute_on_;
111 bool CrasAudioHandler::IsOutputMutedForDevice(uint64 device_id) {
112 const AudioDevice* device = GetDeviceFromId(device_id);
113 if (!device)
114 return false;
115 return audio_pref_handler_->GetMuteValue(*device);
118 bool CrasAudioHandler::IsOutputVolumeBelowDefaultMuteLvel() {
119 return output_volume_ <= kMuteThresholdPercent;
122 bool CrasAudioHandler::IsInputMuted() {
123 return input_mute_on_;
126 bool CrasAudioHandler::IsInputMutedForDevice(uint64 device_id) {
127 const AudioDevice* device = GetDeviceFromId(device_id);
128 if (!device)
129 return false;
130 return audio_pref_handler_->GetMuteValue(*device);
133 int CrasAudioHandler::GetOutputDefaultVolumeMuteThreshold() {
134 return kMuteThresholdPercent;
137 int CrasAudioHandler::GetOutputVolumePercent() {
138 return output_volume_;
141 int CrasAudioHandler::GetOutputVolumePercentForDevice(uint64 device_id) {
142 if (device_id == active_output_node_id_) {
143 return output_volume_;
144 } else {
145 const AudioDevice* device = GetDeviceFromId(device_id);
146 return static_cast<int>(audio_pref_handler_->GetOutputVolumeValue(device));
150 int CrasAudioHandler::GetInputGainPercent() {
151 return input_gain_;
154 int CrasAudioHandler::GetInputGainPercentForDevice(uint64 device_id) {
155 if (device_id == active_input_node_id_) {
156 return input_gain_;
157 } else {
158 const AudioDevice* device = GetDeviceFromId(device_id);
159 return static_cast<int>(audio_pref_handler_->GetInputGainValue(device));
163 uint64 CrasAudioHandler::GetActiveOutputNode() const {
164 return active_output_node_id_;
167 uint64 CrasAudioHandler::GetActiveInputNode() const {
168 return active_input_node_id_;
171 void CrasAudioHandler::GetAudioDevices(AudioDeviceList* device_list) const {
172 device_list->clear();
173 for (AudioDeviceMap::const_iterator it = audio_devices_.begin();
174 it != audio_devices_.end(); ++it)
175 device_list->push_back(it->second);
178 bool CrasAudioHandler::GetActiveOutputDevice(AudioDevice* device) const {
179 const AudioDevice* active_device = GetDeviceFromId(active_output_node_id_);
180 if (!active_device || !device)
181 return false;
182 *device = *active_device;
183 return true;
186 bool CrasAudioHandler::has_alternative_input() const {
187 return has_alternative_input_;
190 bool CrasAudioHandler::has_alternative_output() const {
191 return has_alternative_output_;
194 void CrasAudioHandler::SetOutputVolumePercent(int volume_percent) {
195 volume_percent = min(max(volume_percent, 0), 100);
196 if (volume_percent <= kMuteThresholdPercent)
197 volume_percent = 0;
198 output_volume_ = volume_percent;
200 if (const AudioDevice* device = GetDeviceFromId(active_output_node_id_))
201 audio_pref_handler_->SetVolumeGainValue(*device, output_volume_);
203 SetOutputNodeVolume(active_output_node_id_, output_volume_);
204 FOR_EACH_OBSERVER(AudioObserver, observers_, OnOutputVolumeChanged());
207 // TODO: Rename the 'Percent' to something more meaningful.
208 void CrasAudioHandler::SetInputGainPercent(int gain_percent) {
209 // NOTE: We do not sanitize input gain values since the range is completely
210 // dependent on the device.
211 input_gain_ = gain_percent;
213 if (const AudioDevice* device = GetDeviceFromId(active_input_node_id_))
214 audio_pref_handler_->SetVolumeGainValue(*device, input_gain_);
216 SetInputNodeGain(active_input_node_id_, input_gain_);
217 FOR_EACH_OBSERVER(AudioObserver, observers_, OnInputGainChanged());
220 void CrasAudioHandler::AdjustOutputVolumeByPercent(int adjust_by_percent) {
221 SetOutputVolumePercent(output_volume_ + adjust_by_percent);
224 void CrasAudioHandler::SetOutputMute(bool mute_on) {
225 if (!SetOutputMuteInternal(mute_on))
226 return;
228 if (const AudioDevice* device = GetDeviceFromId(active_output_node_id_))
229 audio_pref_handler_->SetMuteValue(*device, output_mute_on_);
231 FOR_EACH_OBSERVER(AudioObserver, observers_, OnOutputMuteChanged());
234 void CrasAudioHandler::AdjustOutputVolumeToAudibleLevel() {
235 if (output_volume_ <= kMuteThresholdPercent) {
236 // Avoid the situation when sound has been unmuted, but the volume
237 // is set to a very low value, so user still can't hear any sound.
238 SetOutputVolumePercent(kDefaultUnmuteVolumePercent);
242 void CrasAudioHandler::SetInputMute(bool mute_on) {
243 if (!SetInputMuteInternal(mute_on))
244 return;
246 AudioDevice device;
247 if (const AudioDevice* device = GetDeviceFromId(active_input_node_id_))
248 audio_pref_handler_->SetMuteValue(*device, input_mute_on_);
251 FOR_EACH_OBSERVER(AudioObserver, observers_, OnInputMuteChanged());
254 void CrasAudioHandler::SetActiveOutputNode(uint64 node_id) {
255 chromeos::DBusThreadManager::Get()->GetCrasAudioClient()->
256 SetActiveOutputNode(node_id);
257 FOR_EACH_OBSERVER(AudioObserver, observers_, OnActiveOutputNodeChanged());
260 void CrasAudioHandler::SetActiveInputNode(uint64 node_id) {
261 chromeos::DBusThreadManager::Get()->GetCrasAudioClient()->
262 SetActiveInputNode(node_id);
263 FOR_EACH_OBSERVER(AudioObserver, observers_, OnActiveInputNodeChanged());
266 void CrasAudioHandler::SetVolumeGainPercentForDevice(uint64 device_id,
267 int value) {
268 if (device_id == active_output_node_id_) {
269 SetOutputVolumePercent(value);
270 return;
271 } else if (device_id == active_input_node_id_) {
272 SetInputGainPercent(value);
273 return;
276 if (const AudioDevice* device = GetDeviceFromId(device_id)) {
277 if (!device->is_input) {
278 value = min(max(value, 0), 100);
279 if (value <= kMuteThresholdPercent)
280 value = 0;
282 audio_pref_handler_->SetVolumeGainValue(*device, value);
286 void CrasAudioHandler::SetMuteForDevice(uint64 device_id, bool mute_on) {
287 if (device_id == active_output_node_id_) {
288 SetOutputMute(mute_on);
289 return;
290 } else if (device_id == active_input_node_id_) {
291 SetInputMute(mute_on);
292 return;
295 AudioDevice device;
296 if (const AudioDevice* device = GetDeviceFromId(device_id))
297 audio_pref_handler_->SetMuteValue(*device, mute_on);
300 void CrasAudioHandler::LogErrors() {
301 log_errors_ = true;
304 CrasAudioHandler::CrasAudioHandler(
305 scoped_refptr<AudioDevicesPrefHandler> audio_pref_handler)
306 : audio_pref_handler_(audio_pref_handler),
307 weak_ptr_factory_(this),
308 output_mute_on_(false),
309 input_mute_on_(false),
310 output_volume_(0),
311 input_gain_(0),
312 active_output_node_id_(0),
313 active_input_node_id_(0),
314 has_alternative_input_(false),
315 has_alternative_output_(false),
316 output_mute_locked_(false),
317 input_mute_locked_(false),
318 log_errors_(false) {
319 if (!audio_pref_handler.get())
320 return;
321 // If the DBusThreadManager or the CrasAudioClient aren't available, there
322 // isn't much we can do. This should only happen when running tests.
323 if (!chromeos::DBusThreadManager::IsInitialized() ||
324 !chromeos::DBusThreadManager::Get() ||
325 !chromeos::DBusThreadManager::Get()->GetCrasAudioClient())
326 return;
327 chromeos::DBusThreadManager::Get()->GetCrasAudioClient()->AddObserver(this);
328 audio_pref_handler_->AddAudioPrefObserver(this);
329 if (chromeos::DBusThreadManager::Get()->GetSessionManagerClient()) {
330 chromeos::DBusThreadManager::Get()->GetSessionManagerClient()->
331 AddObserver(this);
333 InitializeAudioState();
336 CrasAudioHandler::~CrasAudioHandler() {
337 if (!chromeos::DBusThreadManager::IsInitialized() ||
338 !chromeos::DBusThreadManager::Get() ||
339 !chromeos::DBusThreadManager::Get()->GetCrasAudioClient())
340 return;
341 chromeos::DBusThreadManager::Get()->GetCrasAudioClient()->
342 RemoveObserver(this);
343 chromeos::DBusThreadManager::Get()->GetSessionManagerClient()->
344 RemoveObserver(this);
345 if (audio_pref_handler_.get())
346 audio_pref_handler_->RemoveAudioPrefObserver(this);
347 audio_pref_handler_ = NULL;
350 void CrasAudioHandler::AudioClientRestarted() {
351 // Make sure the logging is enabled in case cras server
352 // restarts after crashing.
353 LogErrors();
354 InitializeAudioState();
357 void CrasAudioHandler::NodesChanged() {
358 // Refresh audio nodes data.
359 GetNodes();
362 void CrasAudioHandler::ActiveOutputNodeChanged(uint64 node_id) {
363 if (active_output_node_id_ == node_id)
364 return;
366 // Active audio output device should always be changed by chrome.
367 // During system boot, cras may change active input to unknown device 0x1,
368 // we don't need to log it, since it is not an valid device.
369 if (GetDeviceFromId(node_id)) {
370 LOG_IF(WARNING, log_errors_)
371 << "Active output node changed unexpectedly by system node_id="
372 << "0x" << std::hex << node_id;
376 void CrasAudioHandler::ActiveInputNodeChanged(uint64 node_id) {
377 if (active_input_node_id_ == node_id)
378 return;
380 // Active audio input device should always be changed by chrome.
381 // During system boot, cras may change active input to unknown device 0x2,
382 // we don't need to log it, since it is not an valid device.
383 if (GetDeviceFromId(node_id)) {
384 LOG_IF(WARNING, log_errors_)
385 << "Active input node changed unexpectedly by system node_id="
386 << "0x" << std::hex << node_id;
390 void CrasAudioHandler::OnAudioPolicyPrefChanged() {
391 ApplyAudioPolicy();
394 void CrasAudioHandler::EmitLoginPromptVisibleCalled() {
395 // Enable logging after cras server is started, which will be after
396 // EmitLoginPromptVisible.
397 LogErrors();
400 const AudioDevice* CrasAudioHandler::GetDeviceFromId(uint64 device_id) const {
401 AudioDeviceMap::const_iterator it = audio_devices_.find(device_id);
402 if (it == audio_devices_.end())
403 return NULL;
405 return &(it->second);
408 void CrasAudioHandler::SetupAudioInputState() {
409 // Set the initial audio state to the ones read from audio prefs.
410 const AudioDevice* device = GetDeviceFromId(active_input_node_id_);
411 if (!device) {
412 LOG_IF(ERROR, log_errors_)
413 << "Can't set up audio state for unknown input device id ="
414 << "0x" << std::hex << active_input_node_id_;
415 return;
417 input_mute_on_ = audio_pref_handler_->GetMuteValue(*device);
418 input_gain_ = audio_pref_handler_->GetInputGainValue(device);
419 SetInputMuteInternal(input_mute_on_);
420 // TODO(rkc,jennyz): Set input gain once we decide on how to store
421 // the gain values since the range and step are both device specific.
424 void CrasAudioHandler::SetupAudioOutputState() {
425 const AudioDevice* device = GetDeviceFromId(active_output_node_id_);
426 if (!device) {
427 LOG_IF(ERROR, log_errors_)
428 << "Can't set up audio state for unknown output device id ="
429 << "0x" << std::hex << active_output_node_id_;
430 return;
432 output_mute_on_ = audio_pref_handler_->GetMuteValue(*device);
433 output_volume_ = audio_pref_handler_->GetOutputVolumeValue(device);
435 SetOutputMuteInternal(output_mute_on_);
436 SetOutputNodeVolume(active_output_node_id_, output_volume_);
439 void CrasAudioHandler::InitializeAudioState() {
440 ApplyAudioPolicy();
441 GetNodes();
444 void CrasAudioHandler::ApplyAudioPolicy() {
445 output_mute_locked_ = false;
446 if (!audio_pref_handler_->GetAudioOutputAllowedValue()) {
447 // Mute the device, but do not update the preference.
448 SetOutputMuteInternal(true);
449 output_mute_locked_ = true;
450 } else {
451 // Restore the mute state.
452 const AudioDevice* device = GetDeviceFromId(active_output_node_id_);
453 if (device)
454 SetOutputMuteInternal(audio_pref_handler_->GetMuteValue(*device));
457 input_mute_locked_ = false;
458 if (audio_pref_handler_->GetAudioCaptureAllowedValue()) {
459 // Set input mute if we have discovered active input device.
460 const AudioDevice* device = GetDeviceFromId(active_input_node_id_);
461 if (device)
462 SetInputMuteInternal(false);
463 } else {
464 SetInputMute(true);
465 input_mute_locked_ = true;
469 void CrasAudioHandler::SetOutputNodeVolume(uint64 node_id, int volume) {
470 chromeos::DBusThreadManager::Get()->GetCrasAudioClient()->
471 SetOutputNodeVolume(node_id, volume);
474 bool CrasAudioHandler::SetOutputMuteInternal(bool mute_on) {
475 if (output_mute_locked_)
476 return false;
478 output_mute_on_ = mute_on;
479 chromeos::DBusThreadManager::Get()->GetCrasAudioClient()->
480 SetOutputUserMute(mute_on);
481 return true;
484 void CrasAudioHandler::SetInputNodeGain(uint64 node_id, int gain) {
485 chromeos::DBusThreadManager::Get()->GetCrasAudioClient()->
486 SetInputNodeGain(node_id, gain);
489 bool CrasAudioHandler::SetInputMuteInternal(bool mute_on) {
490 if (input_mute_locked_)
491 return false;
493 input_mute_on_ = mute_on;
494 chromeos::DBusThreadManager::Get()->GetCrasAudioClient()->
495 SetInputMute(mute_on);
496 return true;
499 void CrasAudioHandler::GetNodes() {
500 chromeos::DBusThreadManager::Get()->GetCrasAudioClient()->GetNodes(
501 base::Bind(&CrasAudioHandler::HandleGetNodes,
502 weak_ptr_factory_.GetWeakPtr()),
503 base::Bind(&CrasAudioHandler::HandleGetNodesError,
504 weak_ptr_factory_.GetWeakPtr()));
507 bool CrasAudioHandler::ChangeActiveDevice(const AudioDevice& new_active_device,
508 uint64* current_active_node_id) {
509 // If the device we want to switch to is already the current active device,
510 // do nothing.
511 if (new_active_device.active &&
512 new_active_device.id == *current_active_node_id) {
513 return false;
516 // Reset all other input or output devices' active status. The active audio
517 // device from the previous user session can be remembered by cras, but not
518 // in chrome. see crbug.com/273271.
519 for (AudioDeviceMap::iterator it = audio_devices_.begin();
520 it != audio_devices_.end(); ++it) {
521 if (it->second.is_input == new_active_device.is_input &&
522 it->second.id != new_active_device.id)
523 it->second.active = false;
526 // Set the current active input/output device to the new_active_device.
527 *current_active_node_id = new_active_device.id;
528 audio_devices_[*current_active_node_id].active = true;
529 return true;
532 bool CrasAudioHandler::NonActiveDeviceUnplugged(
533 size_t old_devices_size,
534 size_t new_devices_size,
535 uint64 current_active_node) {
536 return (new_devices_size < old_devices_size &&
537 GetDeviceFromId(current_active_node));
540 void CrasAudioHandler::SwitchToDevice(const AudioDevice& device) {
541 if (device.is_input) {
542 if (!ChangeActiveDevice(device, &active_input_node_id_))
543 return;
544 SetupAudioInputState();
545 SetActiveInputNode(active_input_node_id_);
546 } else {
547 if (!ChangeActiveDevice(device, &active_output_node_id_))
548 return;
549 SetupAudioOutputState();
550 SetActiveOutputNode(active_output_node_id_);
554 bool CrasAudioHandler::HasDeviceChange(const AudioNodeList& new_nodes,
555 bool is_input) {
556 size_t num_old_devices = 0;
557 size_t num_new_devices = 0;
558 for (AudioDeviceMap::const_iterator it = audio_devices_.begin();
559 it != audio_devices_.end(); ++it) {
560 if (is_input == it->second.is_input)
561 ++num_old_devices;
564 for (AudioNodeList::const_iterator it = new_nodes.begin();
565 it != new_nodes.end(); ++it) {
566 if (is_input == it->is_input) {
567 ++num_new_devices;
568 // Look to see if the new device not in the old device list.
569 AudioDevice device(*it);
570 if (FoundNewDevice(device))
571 return true;
574 return num_old_devices != num_new_devices;
577 bool CrasAudioHandler::FoundNewDevice(const AudioDevice& device) {
578 const AudioDevice* device_found = GetDeviceFromId(device.id);
579 if (!device_found)
580 return true;
582 if (!IsSameAudioDevice(device, *device_found)) {
583 LOG(WARNING) << "Different Audio devices with same id:"
584 << " new device: " << device.ToString()
585 << " old device: " << device_found->ToString();
586 return true;
588 return false;
591 // Sanitize the audio node data. When a device is plugged in or unplugged, there
592 // should be only one NodesChanged signal from cras. However, we've observed
593 // the case that multiple NodesChanged signals being sent from cras. After the
594 // first NodesChanged being processed, chrome sets the active node properly.
595 // However, the NodesChanged received after the first one, can return stale
596 // nodes data in GetNodes call, the staled nodes data does not reflect the
597 // latest active node state. Since active audio node should only be set by
598 // chrome, the inconsistent data from cras could be the result of stale data
599 // described above and sanitized.
600 AudioDevice CrasAudioHandler::GetSanitizedAudioDevice(const AudioNode& node) {
601 AudioDevice device(node);
602 if (device.is_input) {
603 if (device.active && device.id != active_input_node_id_) {
604 LOG(WARNING) << "Stale audio device data, should not be active: "
605 << " device = " << device.ToString()
606 << " current active input node id = 0x" << std::hex
607 << active_input_node_id_;
608 device.active = false;
609 } else if (device.id == active_input_node_id_ && !device.active) {
610 LOG(WARNING) << "Stale audio device data, should be active:"
611 << " device = " << device.ToString()
612 << " current active input node id = 0x" << std::hex
613 << active_input_node_id_;
614 device.active = true;
616 } else {
617 if (device.active && device.id != active_output_node_id_) {
618 LOG(WARNING) << "Stale audio device data, should not be active: "
619 << " device = " << device.ToString()
620 << " current active output node id = 0x" << std::hex
621 << active_output_node_id_;
622 device.active = false;
623 } else if (device.id == active_output_node_id_ && !device.active) {
624 LOG(WARNING) << "Stale audio device data, should be active:"
625 << " device = " << device.ToString()
626 << " current active output node id = 0x" << std::hex
627 << active_output_node_id_;
628 device.active = true;
631 return device;
634 void CrasAudioHandler::UpdateDevicesAndSwitchActive(
635 const AudioNodeList& nodes) {
636 size_t old_audio_devices_size = audio_devices_.size();
637 bool output_devices_changed = HasDeviceChange(nodes, false);
638 bool input_devices_changed = HasDeviceChange(nodes, true);
639 audio_devices_.clear();
640 has_alternative_input_ = false;
641 has_alternative_output_ = false;
643 while (!input_devices_pq_.empty())
644 input_devices_pq_.pop();
645 while (!output_devices_pq_.empty())
646 output_devices_pq_.pop();
648 for (size_t i = 0; i < nodes.size(); ++i) {
649 AudioDevice device = GetSanitizedAudioDevice(nodes[i]);
650 audio_devices_[device.id] = device;
652 if (!has_alternative_input_ &&
653 device.is_input &&
654 device.type != AUDIO_TYPE_INTERNAL_MIC) {
655 has_alternative_input_ = true;
656 } else if (!has_alternative_output_ &&
657 !device.is_input &&
658 device.type != AUDIO_TYPE_INTERNAL_SPEAKER) {
659 has_alternative_output_ = true;
662 if (device.is_input)
663 input_devices_pq_.push(device);
664 else
665 output_devices_pq_.push(device);
668 // If audio nodes change is caused by unplugging some non-active audio
669 // devices, the previously set active audio device will stay active.
670 // Otherwise, switch to a new active audio device according to their priority.
671 if (input_devices_changed &&
672 !NonActiveDeviceUnplugged(old_audio_devices_size,
673 audio_devices_.size(),
674 active_input_node_id_) &&
675 !input_devices_pq_.empty())
676 SwitchToDevice(input_devices_pq_.top());
677 if (output_devices_changed &&
678 !NonActiveDeviceUnplugged(old_audio_devices_size,
679 audio_devices_.size(),
680 active_output_node_id_) &&
681 !output_devices_pq_.empty()) {
682 SwitchToDevice(output_devices_pq_.top());
686 void CrasAudioHandler::HandleGetNodes(const chromeos::AudioNodeList& node_list,
687 bool success) {
688 if (!success) {
689 LOG_IF(ERROR, log_errors_) << "Failed to retrieve audio nodes data";
690 return;
693 UpdateDevicesAndSwitchActive(node_list);
694 FOR_EACH_OBSERVER(AudioObserver, observers_, OnAudioNodesChanged());
697 void CrasAudioHandler::HandleGetNodesError(const std::string& error_name,
698 const std::string& error_msg) {
699 LOG_IF(ERROR, log_errors_) << "Failed to call GetNodes: "
700 << error_name << ": " << error_msg;
702 } // namespace chromeos