diff options
author | jennyz@chromium.org <jennyz@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-07-29 21:41:32 +0000 |
---|---|---|
committer | jennyz@chromium.org <jennyz@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-07-29 21:41:32 +0000 |
commit | ee38bc4084d0812df5fa0d9a615f8a8193e04ab2 (patch) | |
tree | c7d352edcf879b00b3f684164bcdab86f00acbe8 /chromeos/audio | |
parent | 9367d3412716696b94edb746f3162f1a57b0d37a (diff) | |
download | chromium_src-ee38bc4084d0812df5fa0d9a615f8a8193e04ab2.zip chromium_src-ee38bc4084d0812df5fa0d9a615f8a8193e04ab2.tar.gz chromium_src-ee38bc4084d0812df5fa0d9a615f8a8193e04ab2.tar.bz2 |
Add test coverage for CrasAudioHandler.
Separate CrasAudioClientStubImpl out of cras_audio_client.cc into its own files.
Remove MockCrasAudioHandler.
BUG=233266
R=stevenjb@chromium.org
Review URL: https://codereview.chromium.org/19861002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@214224 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chromeos/audio')
-rw-r--r-- | chromeos/audio/audio_devices_pref_handler.h | 2 | ||||
-rw-r--r-- | chromeos/audio/audio_devices_pref_handler_stub.cc | 54 | ||||
-rw-r--r-- | chromeos/audio/audio_devices_pref_handler_stub.h | 47 | ||||
-rw-r--r-- | chromeos/audio/cras_audio_handler.cc | 11 | ||||
-rw-r--r-- | chromeos/audio/cras_audio_handler.h | 6 | ||||
-rw-r--r-- | chromeos/audio/cras_audio_handler_unittest.cc | 1114 | ||||
-rw-r--r-- | chromeos/audio/mock_cras_audio_handler.cc | 73 | ||||
-rw-r--r-- | chromeos/audio/mock_cras_audio_handler.h | 41 |
8 files changed, 1223 insertions, 125 deletions
diff --git a/chromeos/audio/audio_devices_pref_handler.h b/chromeos/audio/audio_devices_pref_handler.h index 08080b7..d382218 100644 --- a/chromeos/audio/audio_devices_pref_handler.h +++ b/chromeos/audio/audio_devices_pref_handler.h @@ -10,7 +10,7 @@ #include "chromeos/audio/audio_pref_observer.h" #include "chromeos/chromeos_export.h" -class PrefRegistrySimple; +class PrefService; namespace chromeos { diff --git a/chromeos/audio/audio_devices_pref_handler_stub.cc b/chromeos/audio/audio_devices_pref_handler_stub.cc new file mode 100644 index 0000000..4f195ab --- /dev/null +++ b/chromeos/audio/audio_devices_pref_handler_stub.cc @@ -0,0 +1,54 @@ +// Copyright (c) 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chromeos/audio/audio_devices_pref_handler_stub.h" + +#include "chromeos/audio/audio_device.h" + +namespace chromeos { + +AudioDevicesPrefHandlerStub::AudioDevicesPrefHandlerStub() { +} + +AudioDevicesPrefHandlerStub::~AudioDevicesPrefHandlerStub() { +} + +double AudioDevicesPrefHandlerStub::GetVolumeGainValue( + const AudioDevice& device) { + return audio_device_volume_gain_map_[device.id]; +} + +void AudioDevicesPrefHandlerStub::SetVolumeGainValue(const AudioDevice& device, + double value) { + audio_device_volume_gain_map_[device.id] = value; +} + +bool AudioDevicesPrefHandlerStub::GetMuteValue( + const AudioDevice& device) { + return audio_device_mute_map_[device.id]; +} + +void AudioDevicesPrefHandlerStub::SetMuteValue(const AudioDevice& device, + bool mute_on) { + audio_device_mute_map_[device.id] = mute_on; +} + +bool AudioDevicesPrefHandlerStub::GetAudioCaptureAllowedValue() { + return true; +} + +bool AudioDevicesPrefHandlerStub::GetAudioOutputAllowedValue() { + return true; +} + +void AudioDevicesPrefHandlerStub::AddAudioPrefObserver( + AudioPrefObserver* observer) { +} + +void AudioDevicesPrefHandlerStub::RemoveAudioPrefObserver( + AudioPrefObserver* observer) { +} + +} // namespace chromeos + diff --git a/chromeos/audio/audio_devices_pref_handler_stub.h b/chromeos/audio/audio_devices_pref_handler_stub.h new file mode 100644 index 0000000..5f585ed --- /dev/null +++ b/chromeos/audio/audio_devices_pref_handler_stub.h @@ -0,0 +1,47 @@ +// Copyright (c) 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROMEOS_AUDIO_AUDIO_DEVICES_PREF_HANDLER_STUB_H_ +#define CHROMEOS_AUDIO_AUDIO_DEVICES_PREF_HANDLER_STUB_H_ + +#include "chromeos/audio/audio_devices_pref_handler.h" + +#include <map> + +namespace chromeos { + +struct AudioDevice; + +// Stub class for AudioDevicesPrefHandler, used for testing. +class CHROMEOS_EXPORT AudioDevicesPrefHandlerStub + : public AudioDevicesPrefHandler { + public: + typedef std::map<uint64, bool> AudioDeviceMute; + typedef std::map<uint64, int> AudioDeviceVolumeGain; + + AudioDevicesPrefHandlerStub(); + + virtual double GetVolumeGainValue(const AudioDevice& device) OVERRIDE; + virtual void SetVolumeGainValue(const AudioDevice& device, + double value) OVERRIDE; + virtual bool GetMuteValue(const AudioDevice& device) OVERRIDE; + virtual void SetMuteValue(const AudioDevice& device, bool mute_on) OVERRIDE; + virtual bool GetAudioCaptureAllowedValue() OVERRIDE; + virtual bool GetAudioOutputAllowedValue() OVERRIDE; + virtual void AddAudioPrefObserver(AudioPrefObserver* observer) OVERRIDE; + virtual void RemoveAudioPrefObserver(AudioPrefObserver* observer) OVERRIDE; + + protected: + virtual ~AudioDevicesPrefHandlerStub(); + + private: + AudioDeviceMute audio_device_mute_map_; + AudioDeviceVolumeGain audio_device_volume_gain_map_; + + DISALLOW_COPY_AND_ASSIGN(AudioDevicesPrefHandlerStub); +}; + +} // namespace chromeos + +#endif // CHROMEOS_AUDIO_AUDIO_DEVICES_PREF_HANDLER_STUB_H_ diff --git a/chromeos/audio/cras_audio_handler.cc b/chromeos/audio/cras_audio_handler.cc index 92e984b..f6ae05a 100644 --- a/chromeos/audio/cras_audio_handler.cc +++ b/chromeos/audio/cras_audio_handler.cc @@ -11,7 +11,7 @@ #include "base/bind_helpers.h" #include "base/logging.h" #include "chromeos/audio/audio_devices_pref_handler.h" -#include "chromeos/audio/mock_cras_audio_handler.h" +#include "chromeos/audio/audio_devices_pref_handler_stub.h" #include "chromeos/dbus/dbus_thread_manager.h" using std::max; @@ -69,7 +69,7 @@ void CrasAudioHandler::Initialize( // static void CrasAudioHandler::InitializeForTesting() { CHECK(!g_cras_audio_handler); - g_cras_audio_handler = new MockCrasAudioHandler(); + CrasAudioHandler::Initialize(new AudioDevicesPrefHandlerStub()); } // static @@ -164,6 +164,7 @@ uint64 CrasAudioHandler::GetActiveInputNode() const { } void CrasAudioHandler::GetAudioDevices(AudioDeviceList* device_list) const { + device_list->clear(); for (AudioDeviceMap::const_iterator it = audio_devices_.begin(); it != audio_devices_.end(); ++it) device_list->push_back(it->second); @@ -219,8 +220,6 @@ void CrasAudioHandler::SetOutputMute(bool mute_on) { if (!SetOutputMuteInternal(mute_on)) return; - output_mute_on_ = mute_on; - if (const AudioDevice* device = GetDeviceFromId(active_output_node_id_)) audio_pref_handler_->SetMuteValue(*device, output_mute_on_); @@ -239,8 +238,6 @@ void CrasAudioHandler::SetInputMute(bool mute_on) { if (!SetInputMuteInternal(mute_on)) return; - input_mute_on_ = mute_on; - AudioDevice device; if (const AudioDevice* device = GetDeviceFromId(active_input_node_id_)) audio_pref_handler_->SetMuteValue(*device, input_mute_on_); @@ -442,6 +439,7 @@ bool CrasAudioHandler::SetOutputMuteInternal(bool mute_on) { if (output_mute_locked_) return false; + output_mute_on_ = mute_on; chromeos::DBusThreadManager::Get()->GetCrasAudioClient()-> SetOutputUserMute(mute_on); return true; @@ -456,6 +454,7 @@ bool CrasAudioHandler::SetInputMuteInternal(bool mute_on) { if (input_mute_locked_) return false; + input_mute_on_ = mute_on; chromeos::DBusThreadManager::Get()->GetCrasAudioClient()-> SetInputMute(mute_on); return true; diff --git a/chromeos/audio/cras_audio_handler.h b/chromeos/audio/cras_audio_handler.h index 3bc504e..5a0a423 100644 --- a/chromeos/audio/cras_audio_handler.h +++ b/chromeos/audio/cras_audio_handler.h @@ -137,12 +137,10 @@ class CHROMEOS_EXPORT CrasAudioHandler : public CrasAudioClient::Observer, virtual bool has_alternative_input() const; virtual bool has_alternative_output() const; - // Sets volume level from 0-100%. If less than kMuteThresholdPercent, then - // mutes the sound. If it was muted, and |volume_percent| is larger than - // the threshold, then the sound is unmuted. + // Sets volume level to |volume_percent|, whose range is from 0-100%. virtual void SetOutputVolumePercent(int volume_percent); - // Sets gain level from 0-100%. + // Sets gain level to |gain_percent|, whose range is from 0-100%. virtual void SetInputGainPercent(int gain_percent); // Adjusts volume up (positive percentage) or down (negative percentage). diff --git a/chromeos/audio/cras_audio_handler_unittest.cc b/chromeos/audio/cras_audio_handler_unittest.cc new file mode 100644 index 0000000..1fe67e9 --- /dev/null +++ b/chromeos/audio/cras_audio_handler_unittest.cc @@ -0,0 +1,1114 @@ +// Copyright (c) 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chromeos/audio/cras_audio_handler.h" + +#include "base/memory/ref_counted.h" +#include "base/memory/scoped_ptr.h" +#include "base/message_loop/message_loop.h" +#include "base/values.h" +#include "chromeos/audio/audio_devices_pref_handler_stub.h" +#include "chromeos/dbus/audio_node.h" +#include "chromeos/dbus/cras_audio_client_stub_impl.h" +#include "chromeos/dbus/dbus_thread_manager.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace chromeos { + +const uint64 kInternalSpeakerId = 10001; +const uint64 kHeadphoneId = 10002; +const uint64 kInternalMicId = 10003; +const uint64 kUSBMicId = 10004; +const uint64 kBluetoothHeadsetId = 10005; +const uint64 kHDMIOutputId = 10006; +const uint64 kUSBHeadphoneId1 = 10007; +const uint64 kUSBHeadphoneId2 = 10008; +const uint64 kOtherTypeOutputId = 90001; +const uint64 kOtherTypeInputId = 90002; + +const AudioNode kInternalSpeaker( + false, + kInternalSpeakerId, + "Fake Speaker", + "INTERNAL_SPEAKER", + "Speaker", + false, + 0 +); + +const AudioNode kHeadphone( + false, + kHeadphoneId, + "Fake Headphone", + "HEADPHONE", + "Headphone", + false, + 0 +); + +const AudioNode kInternalMic( + true, + kInternalMicId, + "Fake Mic", + "INTERNAL_MIC", + "Internal Mic", + false, + 0 +); + +const AudioNode kUSBMic( + true, + kUSBMicId, + "Fake USB Mic", + "USB", + "USB Microphone", + false, + 0 +); + +const AudioNode kOtherTypeOutput( + false, + kOtherTypeOutputId, + "Output Device", + "SOME_OTHER_TYPE", + "Other Type Output Device", + false, + 0 +); + +const AudioNode kOtherTypeInput( + true, + kOtherTypeInputId, + "Input Device", + "SOME_OTHER_TYPE", + "Other Type Input Device", + false, + 0 +); + +const AudioNode kBluetoothHeadset ( + false, + kBluetoothHeadsetId, + "Bluetooth Headset", + "BLUETOOTH", + "Bluetooth Headset 1", + false, + 0 +); + +const AudioNode kHDMIOutput ( + false, + kHDMIOutputId, + "HDMI output", + "HDMI", + "HDMI output", + false, + 0 +); + +const AudioNode kUSBHeadphone1 ( + false, + kUSBHeadphoneId1, + "USB Headphone", + "USB", + "USB Headphone 1", + false, + 0 +); + +const AudioNode kUSBHeadphone2 ( + false, + kUSBHeadphoneId2, + "USB Headphone", + "USB", + "USB Headphone 1", + false, + 0 +); + + +class TestObserver : public chromeos::CrasAudioHandler::AudioObserver { + public: + TestObserver() : active_output_node_changed_count_(0), + active_input_node_changed_count_(0), + audio_nodes_changed_count_(0), + output_mute_changed_count_(0), + input_mute_changed_count_(0), + output_volume_changed_count_(0), + input_gain_changed_count_(0) { + } + + int active_output_node_changed_count() const { + return active_output_node_changed_count_; + } + + int active_input_node_changed_count() const { + return active_input_node_changed_count_; + } + + int audio_nodes_changed_count() const { + return audio_nodes_changed_count_; + } + + int output_mute_changed_count() const { + return output_mute_changed_count_; + } + + int input_mute_changed_count() const { + return input_mute_changed_count_; + } + + int output_volume_changed_count() const { + return output_volume_changed_count_; + } + + int input_gain_changed_count() const { + return input_gain_changed_count_; + } + + virtual ~TestObserver() {} + + protected: + // chromeos::CrasAudioHandler::AudioObserver overrides. + virtual void OnActiveOutputNodeChanged() OVERRIDE { + ++active_output_node_changed_count_; + } + + virtual void OnActiveInputNodeChanged() OVERRIDE { + ++active_input_node_changed_count_; + } + + virtual void OnAudioNodesChanged() OVERRIDE { + ++audio_nodes_changed_count_; + } + + virtual void OnOutputMuteChanged() OVERRIDE { + ++output_mute_changed_count_; + } + + virtual void OnInputMuteChanged() OVERRIDE { + ++input_mute_changed_count_; + } + + virtual void OnOutputVolumeChanged() OVERRIDE { + ++output_volume_changed_count_; + } + + virtual void OnInputGainChanged() OVERRIDE { + ++input_gain_changed_count_; + } + + private: + int active_output_node_changed_count_; + int active_input_node_changed_count_; + int audio_nodes_changed_count_; + int output_mute_changed_count_; + int input_mute_changed_count_; + int output_volume_changed_count_; + int input_gain_changed_count_; + + DISALLOW_COPY_AND_ASSIGN(TestObserver); +}; + +class CrasAudioHandlerTest : public testing::Test { + public: + CrasAudioHandlerTest() : cras_audio_handler_(NULL), + cras_audio_client_stub_(NULL) { + } + virtual ~CrasAudioHandlerTest() {} + + virtual void SetUp() OVERRIDE { + } + + virtual void TearDown() OVERRIDE { + cras_audio_handler_->RemoveAudioObserver(test_observer_.get()); + test_observer_.reset(); + CrasAudioHandler::Shutdown(); + audio_pref_handler_ = NULL; + DBusThreadManager::Shutdown(); + } + + void SetUpCrasAudioHandler(const AudioNodeList& audio_nodes) { + DBusThreadManager::InitializeWithStub(); + cras_audio_client_stub_ = static_cast<CrasAudioClientStubImpl*>( + DBusThreadManager::Get()->GetCrasAudioClient()); + cras_audio_client_stub_->SetAudioDevices(audio_nodes); + audio_pref_handler_ = new AudioDevicesPrefHandlerStub(); + CrasAudioHandler::Initialize(audio_pref_handler_); + cras_audio_handler_ = CrasAudioHandler::Get(); + test_observer_.reset(new TestObserver); + cras_audio_handler_->AddAudioObserver(test_observer_.get()); + message_loop_.RunUntilIdle(); + } + + void ChangeAudioNodes(const AudioNodeList& audio_nodes) { + cras_audio_client_stub_->ChangeAudioNodes(audio_nodes); + message_loop_.RunUntilIdle(); + } + + protected: + base::MessageLoopForUI message_loop_; + CrasAudioHandler* cras_audio_handler_; // Not owned. + CrasAudioClientStubImpl* cras_audio_client_stub_; // Not owned. + scoped_ptr<TestObserver> test_observer_; + scoped_refptr<AudioDevicesPrefHandlerStub> audio_pref_handler_; + + private: + DISALLOW_COPY_AND_ASSIGN(CrasAudioHandlerTest); +}; + +TEST_F(CrasAudioHandlerTest, InitializeWithOnlyDefaultAudioDevices) { + AudioNodeList audio_nodes; + audio_nodes.push_back(kInternalSpeaker); + audio_nodes.push_back(kInternalMic); + SetUpCrasAudioHandler(audio_nodes); + + // Verify the audio devices size. + AudioDeviceList audio_devices; + cras_audio_handler_->GetAudioDevices(&audio_devices); + EXPECT_EQ(audio_nodes.size(), audio_devices.size()); + + // Verify the internal speaker has been selected as the active output. + 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()); + EXPECT_FALSE(cras_audio_handler_->has_alternative_output()); + + // Ensure the internal microphone has been selected as the active input. + AudioDevice active_input; + EXPECT_EQ(kInternalMic.id, cras_audio_handler_->GetActiveInputNode()); + EXPECT_FALSE(cras_audio_handler_->has_alternative_input()); +} + +TEST_F(CrasAudioHandlerTest, InitializeWithAlternativeAudioDevices) { + AudioNodeList audio_nodes; + audio_nodes.push_back(kInternalSpeaker); + audio_nodes.push_back(kHeadphone); + audio_nodes.push_back(kInternalMic); + audio_nodes.push_back(kUSBMic); + SetUpCrasAudioHandler(audio_nodes); + + // Verify the audio devices size. + AudioDeviceList audio_devices; + cras_audio_handler_->GetAudioDevices(&audio_devices); + EXPECT_EQ(audio_nodes.size(), audio_devices.size()); + + // Verify the headphone has been selected as the active output. + AudioDevice active_output; + 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()); + + // Ensure the USB microphone has been selected as the active input. + AudioDevice active_input; + EXPECT_EQ(kUSBMicId, cras_audio_handler_->GetActiveInputNode()); + EXPECT_TRUE(cras_audio_handler_->has_alternative_input()); +} + +TEST_F(CrasAudioHandlerTest, SwitchActiveOutputDevice) { + AudioNodeList audio_nodes; + audio_nodes.push_back(kInternalSpeaker); + audio_nodes.push_back(kHeadphone); + SetUpCrasAudioHandler(audio_nodes); + AudioDeviceList audio_devices; + cras_audio_handler_->GetAudioDevices(&audio_devices); + EXPECT_EQ(audio_nodes.size(), audio_devices.size()); + + // Verify the initial active output device is headphone. + EXPECT_EQ(0, test_observer_->active_output_node_changed_count()); + AudioDevice active_output; + EXPECT_TRUE(cras_audio_handler_->GetActiveOutputDevice(&active_output)); + EXPECT_EQ(kHeadphone.id, active_output.id); + EXPECT_EQ(kHeadphone.id, cras_audio_handler_->GetActiveOutputNode()); + + // 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()); + 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, SwitchActiveInputDevice) { + AudioNodeList audio_nodes; + audio_nodes.push_back(kInternalMic); + audio_nodes.push_back(kUSBMic); + SetUpCrasAudioHandler(audio_nodes); + AudioDeviceList audio_devices; + cras_audio_handler_->GetAudioDevices(&audio_devices); + EXPECT_EQ(audio_nodes.size(), audio_devices.size()); + + // Verify the initial active input device is USB mic. + EXPECT_EQ(0, test_observer_->active_input_node_changed_count()); + EXPECT_EQ(kUSBMicId, cras_audio_handler_->GetActiveInputNode()); + + // Switch the active input to internal mic. + AudioDevice internal_mic(kInternalMic); + cras_audio_handler_->SwitchToDevice(internal_mic); + + // Verify the active output is switched to internal speaker, and the active + // ActiveInputNodeChanged event is fired. + EXPECT_EQ(1, test_observer_->active_input_node_changed_count()); + EXPECT_EQ(kInternalMic.id, cras_audio_handler_->GetActiveInputNode()); +} + +TEST_F(CrasAudioHandlerTest, PlugHeadphone) { + // Set up initial audio devices, only with internal speaker. + AudioNodeList audio_nodes; + audio_nodes.push_back(kInternalSpeaker); + 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 internal speaker has been selected as the active output. + EXPECT_EQ(0, 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()); + EXPECT_FALSE(cras_audio_handler_->has_alternative_output()); + + // Plug the headphone. + audio_nodes.push_back(kHeadphone); + 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 headphone 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()); +} + +TEST_F(CrasAudioHandlerTest, UnplugHeadphone) { + // Set up initial audio devices, with internal speaker and headphone. + AudioNodeList audio_nodes; + audio_nodes.push_back(kInternalSpeaker); + audio_nodes.push_back(kHeadphone); + 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 headphone has been selected as the active output. + EXPECT_EQ(0, test_observer_->active_output_node_changed_count()); + AudioDevice active_output; + 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()); + + // Unplug the headphone. + audio_nodes.clear(); + audio_nodes.push_back(kInternalSpeaker); + ChangeAudioNodes(audio_nodes); + + // Verify the AudioNodesChanged event is fired and one audio device is + // removed. + 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 internal speaker 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(kInternalSpeaker.id, active_output.id); + EXPECT_EQ(kInternalSpeaker.id, cras_audio_handler_->GetActiveOutputNode()); + EXPECT_FALSE(cras_audio_handler_->has_alternative_output()); +} + +TEST_F(CrasAudioHandlerTest, InitializeWithBluetoothHeadset) { + AudioNodeList audio_nodes; + audio_nodes.push_back(kInternalSpeaker); + audio_nodes.push_back(kBluetoothHeadset); + SetUpCrasAudioHandler(audio_nodes); + + // Verify the audio devices size. + AudioDeviceList audio_devices; + cras_audio_handler_->GetAudioDevices(&audio_devices); + EXPECT_EQ(audio_nodes.size(), audio_devices.size()); + EXPECT_EQ(0, test_observer_->audio_nodes_changed_count()); + + // Verify the bluetooth headset has been selected as the active output. + EXPECT_EQ(0, test_observer_->active_output_node_changed_count()); + AudioDevice active_output; + EXPECT_TRUE(cras_audio_handler_->GetActiveOutputDevice(&active_output)); + EXPECT_EQ(kBluetoothHeadset.id, active_output.id); + EXPECT_EQ(kBluetoothHeadset.id, cras_audio_handler_->GetActiveOutputNode()); + EXPECT_TRUE(cras_audio_handler_->has_alternative_output()); +} + +TEST_F(CrasAudioHandlerTest, ConnectAndDisconnectBluetoothHeadset) { + // Initialize with internal speaker and headphone. + AudioNodeList audio_nodes; + audio_nodes.push_back(kInternalSpeaker); + audio_nodes.push_back(kHeadphone); + 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 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(kHeadphone.id, active_output.id); + EXPECT_EQ(kHeadphone.id, cras_audio_handler_->GetActiveOutputNode()); + EXPECT_TRUE(cras_audio_handler_->has_alternative_output()); + + // Connect to bluetooth headset. Since it is plugged in later than + // headphone, active output should be switched to it. + audio_nodes.clear(); + audio_nodes.push_back(kInternalSpeaker); + AudioNode headphone(kHeadphone); + headphone.plugged_time = 80000000; + headphone.active = true; + audio_nodes.push_back(headphone); + AudioNode bluetooth_headset(kBluetoothHeadset); + bluetooth_headset.plugged_time = 90000000; + audio_nodes.push_back(bluetooth_headset); + 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 bluetooth headset, 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(kBluetoothHeadset.id, active_output.id); + EXPECT_EQ(kBluetoothHeadset.id, cras_audio_handler_->GetActiveOutputNode()); + EXPECT_TRUE(cras_audio_handler_->has_alternative_output()); + + // Disconnect bluetooth headset. + audio_nodes.clear(); + audio_nodes.push_back(kInternalSpeaker); + audio_nodes.push_back(headphone); + 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 is switched to headphone, and + // ActiveOutputChanged event is fired. + EXPECT_EQ(2, 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()); +} + +TEST_F(CrasAudioHandlerTest, InitializeWithHDMIOutput) { + AudioNodeList audio_nodes; + audio_nodes.push_back(kInternalSpeaker); + audio_nodes.push_back(kHDMIOutput); + SetUpCrasAudioHandler(audio_nodes); + + // Verify the audio devices size. + AudioDeviceList audio_devices; + cras_audio_handler_->GetAudioDevices(&audio_devices); + EXPECT_EQ(audio_nodes.size(), audio_devices.size()); + EXPECT_EQ(0, test_observer_->audio_nodes_changed_count()); + + // Verify the HDMI device has been selected as the active output. + EXPECT_EQ(0, test_observer_->active_output_node_changed_count()); + AudioDevice active_output; + EXPECT_TRUE(cras_audio_handler_->GetActiveOutputDevice(&active_output)); + EXPECT_EQ(kHDMIOutput.id, active_output.id); + EXPECT_EQ(kHDMIOutput.id, cras_audio_handler_->GetActiveOutputNode()); + EXPECT_TRUE(cras_audio_handler_->has_alternative_output()); +} + +TEST_F(CrasAudioHandlerTest, ConnectAndDisconnectHDMIOutput) { + // Initialize with internal speaker. + AudioNodeList audio_nodes; + audio_nodes.push_back(kInternalSpeaker); + 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 internal speaker 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(kInternalSpeaker.id, active_output.id); + EXPECT_EQ(kInternalSpeaker.id, cras_audio_handler_->GetActiveOutputNode()); + EXPECT_FALSE(cras_audio_handler_->has_alternative_output()); + + // Connect to HDMI output. + audio_nodes.clear(); + AudioNode internal_speaker(kInternalSpeaker); + internal_speaker.active = true; + internal_speaker.plugged_time = 80000000; + audio_nodes.push_back(internal_speaker); + AudioNode hdmi(kHDMIOutput); + hdmi.plugged_time = 90000000; + audio_nodes.push_back(hdmi); + 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 hdmi output, 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(kHDMIOutput.id, active_output.id); + EXPECT_EQ(kHDMIOutput.id, cras_audio_handler_->GetActiveOutputNode()); + EXPECT_TRUE(cras_audio_handler_->has_alternative_output()); + + // Disconnect hdmi headset. + audio_nodes.clear(); + audio_nodes.push_back(kInternalSpeaker); + 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 is switched to internal speaker, and + // ActiveOutputChanged 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()); + EXPECT_FALSE(cras_audio_handler_->has_alternative_output()); +} + +TEST_F(CrasAudioHandlerTest, HandleHeadphoneAndHDMIOutput) { + // Initialize with internal speaker, headphone and HDMI output. + AudioNodeList audio_nodes; + audio_nodes.push_back(kInternalSpeaker); + audio_nodes.push_back(kHeadphone); + audio_nodes.push_back(kHDMIOutput); + 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 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(kHeadphone.id, active_output.id); + EXPECT_EQ(kHeadphone.id, cras_audio_handler_->GetActiveOutputNode()); + EXPECT_TRUE(cras_audio_handler_->has_alternative_output()); + + // Disconnect HDMI output. + audio_nodes.clear(); + audio_nodes.push_back(kInternalSpeaker); + audio_nodes.push_back(kHDMIOutput); + ChangeAudioNodes(audio_nodes); + + // Verify the AudioNodesChanged event is fired and one audio device is + // removed. + 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 HDMI output, 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(kHDMIOutput.id, active_output.id); + EXPECT_EQ(kHDMIOutput.id, cras_audio_handler_->GetActiveOutputNode()); + EXPECT_TRUE(cras_audio_handler_->has_alternative_output()); +} + +TEST_F(CrasAudioHandlerTest, InitializeWithUSBHeadphone) { + AudioNodeList audio_nodes; + audio_nodes.push_back(kInternalSpeaker); + audio_nodes.push_back(kUSBHeadphone1); + SetUpCrasAudioHandler(audio_nodes); + + // Verify the audio devices size. + AudioDeviceList audio_devices; + cras_audio_handler_->GetAudioDevices(&audio_devices); + EXPECT_EQ(audio_nodes.size(), audio_devices.size()); + EXPECT_EQ(0, test_observer_->audio_nodes_changed_count()); + + // Verify the usb headphone has been selected as the active output. + 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()); +} + +TEST_F(CrasAudioHandlerTest, PlugAndUnplugUSBHeadphone) { + // Initialize with internal speaker. + AudioNodeList audio_nodes; + audio_nodes.push_back(kInternalSpeaker); + 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 internal speaker 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(kInternalSpeaker.id, active_output.id); + EXPECT_EQ(kInternalSpeaker.id, cras_audio_handler_->GetActiveOutputNode()); + EXPECT_FALSE(cras_audio_handler_->has_alternative_output()); + + // Plug in usb headphone + audio_nodes.clear(); + AudioNode internal_speaker(kInternalSpeaker); + internal_speaker.active = true; + internal_speaker.plugged_time = 80000000; + audio_nodes.push_back(internal_speaker); + AudioNode usb_headphone(kUSBHeadphone1); + usb_headphone.plugged_time = 90000000; + audio_nodes.push_back(usb_headphone); + 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 usb headphone, 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(kUSBHeadphone1.id, active_output.id); + EXPECT_EQ(kUSBHeadphone1.id, cras_audio_handler_->GetActiveOutputNode()); + EXPECT_TRUE(cras_audio_handler_->has_alternative_output()); + + // Unplug usb headphone. + audio_nodes.clear(); + audio_nodes.push_back(kInternalSpeaker); + 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 is switched to internal speaker, and + // ActiveOutputChanged 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()); + EXPECT_FALSE(cras_audio_handler_->has_alternative_output()); +} + +TEST_F(CrasAudioHandlerTest, HandleMultipleUSBHeadphones) { + // 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 another usb headphone. + 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 usb_headphone_2(kUSBHeadphone2); + usb_headphone_2.plugged_time = 90000000; + audio_nodes.push_back(usb_headphone_2); + 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 2nd usb headphone, 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(kUSBHeadphone2.id, active_output.id); + EXPECT_EQ(kUSBHeadphone2.id, cras_audio_handler_->GetActiveOutputNode()); + EXPECT_TRUE(cras_audio_handler_->has_alternative_output()); + + // Unplug the 2nd usb headphone. + audio_nodes.clear(); + audio_nodes.push_back(kInternalSpeaker); + audio_nodes.push_back(kUSBHeadphone1); + 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 is switched to the first usb headphone, and + // ActiveOutputChanged event is fired. + EXPECT_EQ(2, test_observer_->active_output_node_changed_count()); + 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()); +} + +TEST_F(CrasAudioHandlerTest, PlugUSBMic) { + // Set up initial audio devices, only with internal mic. + AudioNodeList audio_nodes; + audio_nodes.push_back(kInternalMic); + 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 internal mic is selected as the active output. + EXPECT_EQ(0, test_observer_->active_input_node_changed_count()); + EXPECT_EQ(kInternalMic.id, cras_audio_handler_->GetActiveInputNode()); + EXPECT_FALSE(cras_audio_handler_->has_alternative_input()); + + // Plug the USB Mic. + audio_nodes.push_back(kUSBMic); + 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 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(kUSBMicId, cras_audio_handler_->GetActiveInputNode()); + EXPECT_TRUE(cras_audio_handler_->has_alternative_input()); +} + +TEST_F(CrasAudioHandlerTest, UnplugUSBMic) { + // Set up initial audio devices, with internal mic and USB Mic. + AudioNodeList audio_nodes; + audio_nodes.push_back(kInternalMic); + audio_nodes.push_back(kUSBMic); + 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 USB mic is selected as the active output. + EXPECT_EQ(0, test_observer_->active_input_node_changed_count()); + EXPECT_EQ(kUSBMicId, cras_audio_handler_->GetActiveInputNode()); + EXPECT_TRUE(cras_audio_handler_->has_alternative_input()); + + // Unplug the USB Mic. + audio_nodes.clear(); + audio_nodes.push_back(kInternalMic); + ChangeAudioNodes(audio_nodes); + + // Verify the AudioNodesChanged event is fired, and one audio device is + // removed. + 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 internal mic, and + // and ActiveInputChanged event is fired. + EXPECT_EQ(1, test_observer_->active_input_node_changed_count()); + EXPECT_EQ(kInternalMic.id, cras_audio_handler_->GetActiveInputNode()); + EXPECT_FALSE(cras_audio_handler_->has_alternative_input()); +} + +TEST_F(CrasAudioHandlerTest, SetOutputMute) { + AudioNodeList audio_nodes; + audio_nodes.push_back(kInternalSpeaker); + SetUpCrasAudioHandler(audio_nodes); + EXPECT_EQ(0, test_observer_->output_mute_changed_count()); + + // Mute the device. + cras_audio_handler_->SetOutputMute(true); + + // Verify the output is muted, OnOutputMuteChanged event is fired, + // and mute value is saved in the preferences. + EXPECT_TRUE(cras_audio_handler_->IsOutputMuted()); + EXPECT_EQ(1, test_observer_->output_mute_changed_count()); + AudioDevice speaker(kInternalSpeaker); + EXPECT_TRUE(audio_pref_handler_->GetMuteValue(speaker)); + + // Unmute the device. + cras_audio_handler_->SetOutputMute(false); + + // Verify the output is unmuted, OnOutputMuteChanged event is fired, + // and mute value is saved in the preferences. + EXPECT_FALSE(cras_audio_handler_->IsOutputMuted()); + EXPECT_EQ(2, test_observer_->output_mute_changed_count()); + EXPECT_FALSE(audio_pref_handler_->GetMuteValue(speaker)); +} + +TEST_F(CrasAudioHandlerTest, SetInputMute) { + AudioNodeList audio_nodes; + audio_nodes.push_back(kInternalMic); + SetUpCrasAudioHandler(audio_nodes); + EXPECT_EQ(0, test_observer_->input_mute_changed_count()); + + // Mute the device. + cras_audio_handler_->SetInputMute(true); + + // Verify the input is muted, OnInputMuteChanged event is fired, + // and mute value is saved in the preferences. + EXPECT_TRUE(cras_audio_handler_->IsInputMuted()); + EXPECT_EQ(1, test_observer_->input_mute_changed_count()); + AudioDevice internal_mic(kInternalMic); + EXPECT_TRUE(audio_pref_handler_->GetMuteValue(internal_mic)); + + // Unmute the device. + cras_audio_handler_->SetInputMute(false); + + // Verify the input is unmuted, OnInputMuteChanged event is fired, + // and mute value is saved in the preferences. + EXPECT_FALSE(cras_audio_handler_->IsInputMuted()); + EXPECT_EQ(2, test_observer_->input_mute_changed_count()); + EXPECT_FALSE(audio_pref_handler_->GetMuteValue(internal_mic)); +} + +TEST_F(CrasAudioHandlerTest, SetOutputVolumePercent) { + AudioNodeList audio_nodes; + audio_nodes.push_back(kInternalSpeaker); + SetUpCrasAudioHandler(audio_nodes); + EXPECT_EQ(0, test_observer_->output_volume_changed_count()); + + cras_audio_handler_->SetOutputVolumePercent(60); + + // Verify the output volume is changed to the designated value, + // OnOutputVolumeChanged event is fired, and the device volume value + // is saved the preferences. + const int kVolume = 60; + EXPECT_EQ(kVolume, cras_audio_handler_->GetOutputVolumePercent()); + EXPECT_EQ(1, test_observer_->output_volume_changed_count()); + AudioDevice device; + EXPECT_TRUE(cras_audio_handler_->GetActiveOutputDevice(&device)); + EXPECT_EQ(device.id, kInternalSpeaker.id); + EXPECT_EQ(kVolume, audio_pref_handler_->GetVolumeGainValue(device)); +} + +TEST_F(CrasAudioHandlerTest, SetInputGainPercent) { + AudioNodeList audio_nodes; + audio_nodes.push_back(kInternalMic); + SetUpCrasAudioHandler(audio_nodes); + EXPECT_EQ(0, test_observer_->input_gain_changed_count()); + + cras_audio_handler_->SetInputGainPercent(60); + + // Verify the input gain changed to the designated value, + // OnInputGainChanged event is fired, and the device gain value + // is saved in the preferences. + const int kGain = 60; + EXPECT_EQ(kGain, cras_audio_handler_->GetInputGainPercent()); + EXPECT_EQ(1, test_observer_->input_gain_changed_count()); + AudioDevice internal_mic(kInternalMic); + EXPECT_EQ(kGain, audio_pref_handler_->GetVolumeGainValue(internal_mic)); +} + +TEST_F(CrasAudioHandlerTest, SetMuteForDevice) { + AudioNodeList audio_nodes; + audio_nodes.push_back(kInternalSpeaker); + audio_nodes.push_back(kHeadphone); + audio_nodes.push_back(kInternalMic); + audio_nodes.push_back(kUSBMic); + SetUpCrasAudioHandler(audio_nodes); + + // Mute the active output device. + EXPECT_EQ(kHeadphone.id, cras_audio_handler_->GetActiveOutputNode()); + cras_audio_handler_->SetMuteForDevice(kHeadphone.id, true); + + // Verify the headphone is muted and mute value is saved in the preferences. + EXPECT_TRUE(cras_audio_handler_->IsOutputMutedForDevice(kHeadphone.id)); + AudioDevice headphone(kHeadphone); + EXPECT_TRUE(audio_pref_handler_->GetMuteValue(headphone)); + + // Mute the non-active output device. + cras_audio_handler_->SetMuteForDevice(kInternalSpeaker.id, true); + + // Verify the internal speaker is muted and mute value is saved in the + // preferences. + EXPECT_TRUE(cras_audio_handler_->IsOutputMutedForDevice(kInternalSpeaker.id)); + AudioDevice internal_speaker(kInternalSpeaker); + EXPECT_TRUE(audio_pref_handler_->GetMuteValue(internal_speaker)); + + // Mute the active input device. + EXPECT_EQ(kUSBMic.id, cras_audio_handler_->GetActiveInputNode()); + cras_audio_handler_->SetMuteForDevice(kUSBMic.id, true); + + // Verify the USB Mic is muted and mute state is saved in the preferences. + EXPECT_TRUE(cras_audio_handler_->IsOutputMutedForDevice(kUSBMic.id)); + AudioDevice usb_mic(kUSBMic); + EXPECT_TRUE(audio_pref_handler_->GetMuteValue(usb_mic)); + + // Mute the non-active input device. + cras_audio_handler_->SetMuteForDevice(kInternalMic.id, true); + + // Verify the internal mic is muted and mute value is saved in the + // preferences. + EXPECT_TRUE(cras_audio_handler_->IsOutputMutedForDevice(kInternalMic.id)); + AudioDevice internal_mic(kInternalMic); + EXPECT_TRUE(audio_pref_handler_->GetMuteValue(internal_mic)); +} + +TEST_F(CrasAudioHandlerTest, SetVolumeGainPercentForDevice) { + AudioNodeList audio_nodes; + audio_nodes.push_back(kInternalSpeaker); + audio_nodes.push_back(kHeadphone); + audio_nodes.push_back(kInternalMic); + audio_nodes.push_back(kUSBMic); + SetUpCrasAudioHandler(audio_nodes); + + // Set volume percent for active output device. + const int kHeadphoneVolume = 30; + EXPECT_EQ(kHeadphone.id, cras_audio_handler_->GetActiveOutputNode()); + cras_audio_handler_->SetVolumeGainPercentForDevice(kHeadphone.id, + kHeadphoneVolume); + + // Verify the volume percent of headphone is set, and saved in preferences. + EXPECT_EQ(kHeadphoneVolume, + cras_audio_handler_->GetOutputVolumePercentForDevice( + kHeadphone.id)); + AudioDevice headphone(kHeadphone); + EXPECT_EQ(kHeadphoneVolume, + audio_pref_handler_->GetVolumeGainValue(headphone)); + + // Set volume percent for non-active output device. + const int kSpeakerVolume = 60; + cras_audio_handler_->SetVolumeGainPercentForDevice(kInternalSpeaker.id, + kSpeakerVolume); + + // Verify the volume percent of speaker is set, and saved in preferences. + EXPECT_EQ(kSpeakerVolume, + cras_audio_handler_->GetOutputVolumePercentForDevice( + kInternalSpeaker.id)); + AudioDevice speaker(kInternalSpeaker); + EXPECT_EQ(kSpeakerVolume, + audio_pref_handler_->GetVolumeGainValue(speaker)); + + // Set gain percent for active input device. + const int kUSBMicGain = 30; + EXPECT_EQ(kUSBMic.id, cras_audio_handler_->GetActiveInputNode()); + cras_audio_handler_->SetVolumeGainPercentForDevice(kUSBMic.id, + kUSBMicGain); + + // Verify the gain percent of USB mic is set, and saved in preferences. + EXPECT_EQ(kUSBMicGain, + cras_audio_handler_->GetOutputVolumePercentForDevice(kUSBMic.id)); + AudioDevice usb_mic(kHeadphone); + EXPECT_EQ(kUSBMicGain, + audio_pref_handler_->GetVolumeGainValue(usb_mic)); + + // Set gain percent for non-active input device. + const int kInternalMicGain = 60; + cras_audio_handler_->SetVolumeGainPercentForDevice(kInternalMic.id, + kInternalMicGain); + + // Verify the gain percent of internal mic is set, and saved in preferences. + EXPECT_EQ(kInternalMicGain, + cras_audio_handler_->GetOutputVolumePercentForDevice( + kInternalMic.id)); + AudioDevice internal_mic(kInternalMic); + EXPECT_EQ(kInternalMicGain, + audio_pref_handler_->GetVolumeGainValue(internal_mic)); +} + +TEST_F(CrasAudioHandlerTest, HandleOtherDeviceType) { + const size_t kNumValidAudioDevices = 4; + AudioNodeList audio_nodes; + audio_nodes.push_back(kInternalSpeaker); + audio_nodes.push_back(kOtherTypeOutput); + audio_nodes.push_back(kInternalMic); + audio_nodes.push_back(kOtherTypeInput); + SetUpCrasAudioHandler(audio_nodes); + + // Verify the audio devices size. + AudioDeviceList audio_devices; + cras_audio_handler_->GetAudioDevices(&audio_devices); + EXPECT_EQ(kNumValidAudioDevices, audio_devices.size()); + + // Verify the internal speaker has been selected as the active output, + // and the output device with some randown unknown type is handled gracefully. + 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()); + EXPECT_TRUE(cras_audio_handler_->has_alternative_output()); + + // Ensure the internal microphone has been selected as the active input, + // and the input device with some random unknown type is handled gracefully. + AudioDevice active_input; + EXPECT_EQ(kInternalMic.id, cras_audio_handler_->GetActiveInputNode()); + EXPECT_TRUE(cras_audio_handler_->has_alternative_input()); +} + +} // namespace chromeos diff --git a/chromeos/audio/mock_cras_audio_handler.cc b/chromeos/audio/mock_cras_audio_handler.cc deleted file mode 100644 index a9d3cf4..0000000 --- a/chromeos/audio/mock_cras_audio_handler.cc +++ /dev/null @@ -1,73 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chromeos/audio/mock_cras_audio_handler.h" - -#include "chromeos/audio/audio_devices_pref_handler.h" - -namespace chromeos { - -void MockCrasAudioHandler::AddAudioObserver(AudioObserver* observer) { -} - -void MockCrasAudioHandler::RemoveAudioObserver(AudioObserver* observer) { -} - -bool MockCrasAudioHandler::IsOutputMuted() { - return false; -} - -bool MockCrasAudioHandler::IsInputMuted() { - return false; -} - -int MockCrasAudioHandler::GetOutputVolumePercent() { - return 0; -} - -uint64 MockCrasAudioHandler::GetActiveOutputNode() const { - return 0; -} - -uint64 MockCrasAudioHandler::GetActiveInputNode() const { - return 0; -} - -void MockCrasAudioHandler::GetAudioDevices(AudioDeviceList* device_list) const { -} - -bool MockCrasAudioHandler::GetActiveOutputDevice(AudioDevice* device) const { - return false; -} - -bool MockCrasAudioHandler::has_alternative_input() const { - return false; -} - -bool MockCrasAudioHandler::has_alternative_output() const { - return false; -} - -void MockCrasAudioHandler::SetOutputVolumePercent(int volume_percent) { -} - -void MockCrasAudioHandler::AdjustOutputVolumeByPercent(int adjust_by_percent) { -} - -void MockCrasAudioHandler::SetOutputMute(bool mute_on) { -} - -void MockCrasAudioHandler::SetInputMute(bool mute_on) { -} - -void MockCrasAudioHandler::SwitchToDevice(const AudioDevice& device) { -} - -MockCrasAudioHandler::MockCrasAudioHandler() : CrasAudioHandler(NULL) { -} - -MockCrasAudioHandler::~MockCrasAudioHandler() { -} - -} // namespace chromeos diff --git a/chromeos/audio/mock_cras_audio_handler.h b/chromeos/audio/mock_cras_audio_handler.h deleted file mode 100644 index 9a5c445..0000000 --- a/chromeos/audio/mock_cras_audio_handler.h +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROMEOS_AUDIO_MOCK_CRAS_AUDIO_HANDLER_H_ -#define CHROMEOS_AUDIO_MOCK_CRAS_AUDIO_HANDLER_H_ - -#include "chromeos/audio/cras_audio_handler.h" - -namespace chromeos { - -// Mock class for CrasAudioHandler. -class CHROMEOS_EXPORT MockCrasAudioHandler : public CrasAudioHandler { - public: - MockCrasAudioHandler(); - virtual ~MockCrasAudioHandler(); - - virtual void AddAudioObserver(AudioObserver* observer) OVERRIDE; - virtual void RemoveAudioObserver(AudioObserver* observer) OVERRIDE; - virtual bool IsOutputMuted() OVERRIDE; - virtual bool IsInputMuted() OVERRIDE; - virtual int GetOutputVolumePercent() OVERRIDE; - virtual uint64 GetActiveOutputNode() const OVERRIDE; - virtual uint64 GetActiveInputNode() const OVERRIDE; - virtual void GetAudioDevices(AudioDeviceList* device_list) const OVERRIDE; - virtual bool GetActiveOutputDevice(AudioDevice* device) const OVERRIDE; - virtual bool has_alternative_input() const OVERRIDE; - virtual bool has_alternative_output() const OVERRIDE; - virtual void SetOutputVolumePercent(int volume_percent) OVERRIDE; - virtual void AdjustOutputVolumeByPercent(int adjust_by_percent) OVERRIDE; - virtual void SetOutputMute(bool mute_on) OVERRIDE; - virtual void SetInputMute(bool mute_on) OVERRIDE; - virtual void SwitchToDevice(const AudioDevice& device) OVERRIDE; - - private: - DISALLOW_COPY_AND_ASSIGN(MockCrasAudioHandler); -}; - -} // namespace chromeos - -#endif // CHROMEOS_AUDIO_MOCK_CRAS_AUDIO_HANDLER_H_ |