diff options
author | jennyz@chromium.org <jennyz@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-08-15 11:48:39 +0000 |
---|---|---|
committer | jennyz@chromium.org <jennyz@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-08-15 11:48:39 +0000 |
commit | ca473256dedea4afbe106f86fdc2591dd135f1a9 (patch) | |
tree | c369f1dbc3a446e0bee0e3861ed8e1a28d089e95 /chromeos/audio | |
parent | f6b2aa4c7fa10f07cb3b1945a24d900486fa3e52 (diff) | |
download | chromium_src-ca473256dedea4afbe106f86fdc2591dd135f1a9.zip chromium_src-ca473256dedea4afbe106f86fdc2591dd135f1a9.tar.gz chromium_src-ca473256dedea4afbe106f86fdc2591dd135f1a9.tar.bz2 |
Don't switch to the high priority audio device if user has set a lower priority device to be the active device and unplugged some other audio devices.
Add a test case to cover this case.
BUG=272479
Review URL: https://chromiumcodereview.appspot.com/23166004
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@217790 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chromeos/audio')
-rw-r--r-- | chromeos/audio/cras_audio_handler.cc | 24 | ||||
-rw-r--r-- | chromeos/audio/cras_audio_handler.h | 6 | ||||
-rw-r--r-- | chromeos/audio/cras_audio_handler_unittest.cc | 82 |
3 files changed, 109 insertions, 3 deletions
diff --git a/chromeos/audio/cras_audio_handler.cc b/chromeos/audio/cras_audio_handler.cc index ae206f9..736af14 100644 --- a/chromeos/audio/cras_audio_handler.cc +++ b/chromeos/audio/cras_audio_handler.cc @@ -473,6 +473,14 @@ bool CrasAudioHandler::ChangeActiveDevice(const AudioDevice& new_active_device, return true; } +bool CrasAudioHandler::NonActiveDeviceUnplugged( + size_t old_devices_size, + size_t new_devices_size, + uint64 current_active_node) { + return (new_devices_size <= old_devices_size && + GetDeviceFromId(current_active_node)); +} + void CrasAudioHandler::SwitchToDevice(const AudioDevice& device) { if (device.is_input) { if (!ChangeActiveDevice(device, &active_input_node_id_)) @@ -489,6 +497,7 @@ void CrasAudioHandler::SwitchToDevice(const AudioDevice& device) { void CrasAudioHandler::UpdateDevicesAndSwitchActive( const AudioNodeList& nodes) { + size_t old_audio_devices_size = audio_devices_.size(); audio_devices_.clear(); has_alternative_input_ = false; has_alternative_output_ = false; @@ -518,11 +527,20 @@ void CrasAudioHandler::UpdateDevicesAndSwitchActive( output_devices_pq_.push(device); } - if (!input_devices_pq_.empty()) + // If audio nodes change is caused by unplugging some non-active audio + // devices, the previously set active audio device will stay active. + // Otherwise, switch to a new active audio device according to their priority. + if (!NonActiveDeviceUnplugged(old_audio_devices_size, + audio_devices_.size(), + active_input_node_id_) && + !input_devices_pq_.empty()) SwitchToDevice(input_devices_pq_.top()); - - if (!output_devices_pq_.empty()) + if (!NonActiveDeviceUnplugged(old_audio_devices_size, + audio_devices_.size(), + active_output_node_id_) && + !output_devices_pq_.empty()) { SwitchToDevice(output_devices_pq_.top()); + } } void CrasAudioHandler::HandleGetNodes(const chromeos::AudioNodeList& node_list, diff --git a/chromeos/audio/cras_audio_handler.h b/chromeos/audio/cras_audio_handler.h index 5df456e..b95f123 100644 --- a/chromeos/audio/cras_audio_handler.h +++ b/chromeos/audio/cras_audio_handler.h @@ -224,6 +224,12 @@ class CHROMEOS_EXPORT CrasAudioHandler : public CrasAudioClient::Observer, bool ChangeActiveDevice(const AudioDevice& new_active_device, uint64* current_active_node_id); + // Returns true if the audio nodes change is caused by some non-active + // audio nodes unplugged. + bool NonActiveDeviceUnplugged(size_t old_devices_size, + size_t new_device_size, + uint64 current_active_node); + // Handles dbus callback for GetNodes. void HandleGetNodes(const chromeos::AudioNodeList& node_list, bool success); diff --git a/chromeos/audio/cras_audio_handler_unittest.cc b/chromeos/audio/cras_audio_handler_unittest.cc index 1fe67e9..d18488a 100644 --- a/chromeos/audio/cras_audio_handler_unittest.cc +++ b/chromeos/audio/cras_audio_handler_unittest.cc @@ -814,6 +814,88 @@ TEST_F(CrasAudioHandlerTest, HandleMultipleUSBHeadphones) { EXPECT_TRUE(cras_audio_handler_->has_alternative_output()); } +TEST_F(CrasAudioHandlerTest, UnplugUSBHeadphonesWithActiveSpeaker) { + // Initialize with internal speaker and one usb headphone. + AudioNodeList audio_nodes; + audio_nodes.push_back(kInternalSpeaker); + audio_nodes.push_back(kUSBHeadphone1); + SetUpCrasAudioHandler(audio_nodes); + const size_t init_nodes_size = audio_nodes.size(); + + // Verify the audio devices size. + AudioDeviceList audio_devices; + cras_audio_handler_->GetAudioDevices(&audio_devices); + EXPECT_EQ(init_nodes_size, audio_devices.size()); + EXPECT_EQ(0, test_observer_->audio_nodes_changed_count()); + + // Verify the usb headphone is selected as the active output initially. + EXPECT_EQ(0, test_observer_->active_output_node_changed_count()); + AudioDevice active_output; + EXPECT_TRUE(cras_audio_handler_->GetActiveOutputDevice(&active_output)); + EXPECT_EQ(kUSBHeadphone1.id, active_output.id); + EXPECT_EQ(kUSBHeadphone1.id, cras_audio_handler_->GetActiveOutputNode()); + EXPECT_TRUE(cras_audio_handler_->has_alternative_output()); + + // Plug in the headphone jack. + audio_nodes.clear(); + audio_nodes.push_back(kInternalSpeaker); + AudioNode usb_headphone_1(kUSBHeadphone1); + usb_headphone_1.active = true; + usb_headphone_1.plugged_time = 80000000; + audio_nodes.push_back(usb_headphone_1); + AudioNode headphone_jack(kHeadphone); + headphone_jack.plugged_time = 90000000; + audio_nodes.push_back(headphone_jack); + ChangeAudioNodes(audio_nodes); + + // Verify the AudioNodesChanged event is fired and new audio device is added. + EXPECT_EQ(1, test_observer_->audio_nodes_changed_count()); + cras_audio_handler_->GetAudioDevices(&audio_devices); + EXPECT_EQ(init_nodes_size + 1, audio_devices.size()); + + // Verify the active output device is switched to the headphone jack, which + // is plugged later, and ActiveOutputChanged event is fired. + EXPECT_EQ(1, test_observer_->active_output_node_changed_count()); + EXPECT_TRUE(cras_audio_handler_->GetActiveOutputDevice(&active_output)); + EXPECT_EQ(kHeadphone.id, active_output.id); + EXPECT_EQ(kHeadphone.id, cras_audio_handler_->GetActiveOutputNode()); + EXPECT_TRUE(cras_audio_handler_->has_alternative_output()); + + // Select the speaker to be the active output device. + AudioDevice internal_speaker(kInternalSpeaker); + cras_audio_handler_->SwitchToDevice(internal_speaker); + + // Verify the active output is switched to internal speaker, and the + // ActiveOutputNodeChanged event is fired. + EXPECT_EQ(2, test_observer_->active_output_node_changed_count()); + EXPECT_TRUE(cras_audio_handler_->GetActiveOutputDevice(&active_output)); + EXPECT_EQ(kInternalSpeaker.id, active_output.id); + EXPECT_EQ(kInternalSpeaker.id, cras_audio_handler_->GetActiveOutputNode()); + + // Unplug the usb headphone. + audio_nodes.clear(); + AudioNode internal_speaker_node(kInternalSpeaker); + internal_speaker_node.active = true; + internal_speaker_node.plugged_time = 70000000; + audio_nodes.push_back(internal_speaker_node); + headphone_jack.active = false; + audio_nodes.push_back(headphone_jack); + ChangeAudioNodes(audio_nodes); + + // Verify the AudioNodesChanged event is fired and one audio device is + // removed. + EXPECT_EQ(2, test_observer_->audio_nodes_changed_count()); + cras_audio_handler_->GetAudioDevices(&audio_devices); + EXPECT_EQ(init_nodes_size, audio_devices.size()); + + // Verify the active output device remains to be speaker. + EXPECT_EQ(2, test_observer_->active_output_node_changed_count()); + EXPECT_TRUE(cras_audio_handler_->GetActiveOutputDevice(&active_output)); + EXPECT_EQ(kInternalSpeaker.id, active_output.id); + EXPECT_EQ(kInternalSpeaker.id, cras_audio_handler_->GetActiveOutputNode()); + EXPECT_TRUE(cras_audio_handler_->has_alternative_output()); +} + TEST_F(CrasAudioHandlerTest, PlugUSBMic) { // Set up initial audio devices, only with internal mic. AudioNodeList audio_nodes; |