summaryrefslogtreecommitdiffstats
path: root/chromeos/audio
diff options
context:
space:
mode:
authorjennyz@chromium.org <jennyz@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-08-15 11:48:39 +0000
committerjennyz@chromium.org <jennyz@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-08-15 11:48:39 +0000
commitca473256dedea4afbe106f86fdc2591dd135f1a9 (patch)
treec369f1dbc3a446e0bee0e3861ed8e1a28d089e95 /chromeos/audio
parentf6b2aa4c7fa10f07cb3b1945a24d900486fa3e52 (diff)
downloadchromium_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.cc24
-rw-r--r--chromeos/audio/cras_audio_handler.h6
-rw-r--r--chromeos/audio/cras_audio_handler_unittest.cc82
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;