Commit babc24b7 authored by jennyz@chromium.org's avatar jennyz@chromium.org

Fix the wrong output device switching caused by an input device being plugged in.

BUG=286029

Review URL: https://chromiumcodereview.appspot.com/23819034

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@222133 0039d316-1c4b-4281-b951-d872f2087c98
parent e11fceee
...@@ -513,9 +513,29 @@ void CrasAudioHandler::SwitchToDevice(const AudioDevice& device) { ...@@ -513,9 +513,29 @@ void CrasAudioHandler::SwitchToDevice(const AudioDevice& device) {
} }
} }
bool CrasAudioHandler::HasDeviceChange(const AudioNodeList& new_nodes,
bool is_input) {
size_t num_old_devices = 0;
size_t num_new_devices = 0;
for (AudioDeviceMap::const_iterator it = audio_devices_.begin();
it != audio_devices_.end(); ++it) {
if (is_input == it->second.is_input)
++num_old_devices;
}
for (AudioNodeList::const_iterator it = new_nodes.begin();
it != new_nodes.end(); ++it) {
if (is_input == it->is_input)
++num_new_devices;
}
return num_old_devices != num_new_devices;
}
void CrasAudioHandler::UpdateDevicesAndSwitchActive( void CrasAudioHandler::UpdateDevicesAndSwitchActive(
const AudioNodeList& nodes) { const AudioNodeList& nodes) {
size_t old_audio_devices_size = audio_devices_.size(); size_t old_audio_devices_size = audio_devices_.size();
bool output_devices_changed = HasDeviceChange(nodes, false);
bool input_devices_changed = HasDeviceChange(nodes, true);
audio_devices_.clear(); audio_devices_.clear();
has_alternative_input_ = false; has_alternative_input_ = false;
has_alternative_output_ = false; has_alternative_output_ = false;
...@@ -548,12 +568,14 @@ void CrasAudioHandler::UpdateDevicesAndSwitchActive( ...@@ -548,12 +568,14 @@ void CrasAudioHandler::UpdateDevicesAndSwitchActive(
// If audio nodes change is caused by unplugging some non-active audio // If audio nodes change is caused by unplugging some non-active audio
// devices, the previously set active audio device will stay active. // devices, the previously set active audio device will stay active.
// Otherwise, switch to a new active audio device according to their priority. // Otherwise, switch to a new active audio device according to their priority.
if (!NonActiveDeviceUnplugged(old_audio_devices_size, if (input_devices_changed &&
!NonActiveDeviceUnplugged(old_audio_devices_size,
audio_devices_.size(), audio_devices_.size(),
active_input_node_id_) && active_input_node_id_) &&
!input_devices_pq_.empty()) !input_devices_pq_.empty())
SwitchToDevice(input_devices_pq_.top()); SwitchToDevice(input_devices_pq_.top());
if (!NonActiveDeviceUnplugged(old_audio_devices_size, if (output_devices_changed &&
!NonActiveDeviceUnplugged(old_audio_devices_size,
audio_devices_.size(), audio_devices_.size(),
active_output_node_id_) && active_output_node_id_) &&
!output_devices_pq_.empty()) { !output_devices_pq_.empty()) {
......
...@@ -219,6 +219,10 @@ class CHROMEOS_EXPORT CrasAudioHandler : public CrasAudioClient::Observer, ...@@ -219,6 +219,10 @@ class CHROMEOS_EXPORT CrasAudioHandler : public CrasAudioClient::Observer,
size_t new_device_size, size_t new_device_size,
uint64 current_active_node); uint64 current_active_node);
// Returns true if there is any device change for for input or output,
// specified by |is_input|.
bool HasDeviceChange(const AudioNodeList& new_nodes, bool is_input);
// Handles dbus callback for GetNodes. // Handles dbus callback for GetNodes.
void HandleGetNodes(const chromeos::AudioNodeList& node_list, bool success); void HandleGetNodes(const chromeos::AudioNodeList& node_list, bool success);
......
...@@ -948,7 +948,7 @@ TEST_F(CrasAudioHandlerTest, PlugUSBMic) { ...@@ -948,7 +948,7 @@ TEST_F(CrasAudioHandlerTest, PlugUSBMic) {
EXPECT_EQ(init_nodes_size, audio_devices.size()); EXPECT_EQ(init_nodes_size, audio_devices.size());
EXPECT_EQ(0, test_observer_->audio_nodes_changed_count()); EXPECT_EQ(0, test_observer_->audio_nodes_changed_count());
// Verify the internal mic is selected as the active output. // Verify the internal mic is selected as the active input.
EXPECT_EQ(0, test_observer_->active_input_node_changed_count()); EXPECT_EQ(0, test_observer_->active_input_node_changed_count());
EXPECT_EQ(kInternalMic.id, cras_audio_handler_->GetActiveInputNode()); EXPECT_EQ(kInternalMic.id, cras_audio_handler_->GetActiveInputNode());
EXPECT_FALSE(cras_audio_handler_->has_alternative_input()); EXPECT_FALSE(cras_audio_handler_->has_alternative_input());
...@@ -1006,6 +1006,65 @@ TEST_F(CrasAudioHandlerTest, UnplugUSBMic) { ...@@ -1006,6 +1006,65 @@ TEST_F(CrasAudioHandlerTest, UnplugUSBMic) {
EXPECT_FALSE(cras_audio_handler_->has_alternative_input()); EXPECT_FALSE(cras_audio_handler_->has_alternative_input());
} }
TEST_F(CrasAudioHandlerTest, PlugUSBMicNotAffectActiveOutput) {
// Set up initial audio devices.
AudioNodeList audio_nodes;
audio_nodes.push_back(kInternalSpeaker);
audio_nodes.push_back(kHeadphone);
audio_nodes.push_back(kInternalMic);
SetUpCrasAudioHandler(audio_nodes);
const size_t init_nodes_size = audio_nodes.size();
// Verify the audio devices size.
EXPECT_EQ(0, test_observer_->audio_nodes_changed_count());
AudioDeviceList audio_devices;
cras_audio_handler_->GetAudioDevices(&audio_devices);
EXPECT_EQ(init_nodes_size, audio_devices.size());
// Verify the internal mic is selected as the active input.
EXPECT_EQ(0, test_observer_->active_input_node_changed_count());
EXPECT_EQ(kInternalMicId, cras_audio_handler_->GetActiveInputNode());
EXPECT_FALSE(cras_audio_handler_->has_alternative_input());
// Verify the headphone is selected as the active output.
EXPECT_EQ(0, test_observer_->active_output_node_changed_count());
EXPECT_EQ(kHeadphoneId, cras_audio_handler_->GetActiveOutputNode());
EXPECT_TRUE(cras_audio_handler_->has_alternative_output());
// Switch the active output to internal speaker.
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(1, test_observer_->active_output_node_changed_count());
AudioDevice active_output;
EXPECT_TRUE(cras_audio_handler_->GetActiveOutputDevice(&active_output));
EXPECT_EQ(kInternalSpeaker.id, active_output.id);
EXPECT_EQ(kInternalSpeaker.id, cras_audio_handler_->GetActiveOutputNode());
// Plug the USB Mic.
audio_nodes.push_back(kUSBMic);
ChangeAudioNodes(audio_nodes);
// Verify the AudioNodesChanged event is fired, one new 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 input device is switched to USB mic, and
// and ActiveInputChanged event is fired.
EXPECT_EQ(1, test_observer_->active_input_node_changed_count());
EXPECT_EQ(kUSBMic.id, cras_audio_handler_->GetActiveInputNode());
EXPECT_TRUE(cras_audio_handler_->has_alternative_input());
// Verify the active output device is not changed.
EXPECT_EQ(1, 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());
}
TEST_F(CrasAudioHandlerTest, SetOutputMute) { TEST_F(CrasAudioHandlerTest, SetOutputMute) {
AudioNodeList audio_nodes; AudioNodeList audio_nodes;
audio_nodes.push_back(kInternalSpeaker); audio_nodes.push_back(kInternalSpeaker);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment