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 | |
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')
-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 | ||||
-rw-r--r-- | chromeos/chromeos.gyp | 7 | ||||
-rw-r--r-- | chromeos/dbus/audio_node.cc | 16 | ||||
-rw-r--r-- | chromeos/dbus/audio_node.h | 7 | ||||
-rw-r--r-- | chromeos/dbus/cras_audio_client.cc | 145 | ||||
-rw-r--r-- | chromeos/dbus/cras_audio_client_stub_impl.cc | 153 | ||||
-rw-r--r-- | chromeos/dbus/cras_audio_client_stub_impl.h | 52 |
14 files changed, 1457 insertions, 271 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_ diff --git a/chromeos/chromeos.gyp b/chromeos/chromeos.gyp index f387c94..4522321 100644 --- a/chromeos/chromeos.gyp +++ b/chromeos/chromeos.gyp @@ -40,8 +40,8 @@ 'audio/audio_pref_handler.h', 'audio/cras_audio_handler.cc', 'audio/cras_audio_handler.h', - 'audio/mock_cras_audio_handler.cc', - 'audio/mock_cras_audio_handler.h', + 'audio/audio_devices_pref_handler_stub.cc', + 'audio/audio_devices_pref_handler_stub.h', 'attestation/attestation_constants.cc', 'attestation/attestation_constants.h', 'attestation/attestation_flow.cc', @@ -79,6 +79,8 @@ 'dbus/bluetooth_profile_service_provider.h', 'dbus/cras_audio_client.cc', 'dbus/cras_audio_client.h', + 'dbus/cras_audio_client_stub_impl.cc', + 'dbus/cras_audio_client_stub_impl.h', 'dbus/cros_disks_client.cc', 'dbus/cros_disks_client.h', 'dbus/cryptohome_client.cc', @@ -455,6 +457,7 @@ 'sources': [ 'app_mode/kiosk_oem_manifest_parser_unittest.cc', 'attestation/attestation_flow_unittest.cc', + 'audio/cras_audio_handler_unittest.cc', 'dbus/blocking_method_caller_unittest.cc', 'dbus/cros_disks_client_unittest.cc', 'dbus/gsm_sms_client_unittest.cc', diff --git a/chromeos/dbus/audio_node.cc b/chromeos/dbus/audio_node.cc index fd3f653..2f56701 100644 --- a/chromeos/dbus/audio_node.cc +++ b/chromeos/dbus/audio_node.cc @@ -17,6 +17,22 @@ AudioNode::AudioNode() plugged_time(0) { } +AudioNode::AudioNode(bool is_input, + uint64 id, + std::string device_name, + std::string type, + std::string name, + bool active, + uint64 plugged_time) + : is_input(is_input), + id(id), + device_name(device_name), + type(type), + name(name), + active(active), + plugged_time(plugged_time) { +} + std::string AudioNode::ToString() const { std::string result; base::StringAppendF(&result, diff --git a/chromeos/dbus/audio_node.h b/chromeos/dbus/audio_node.h index f25c2ed..fd4b231 100644 --- a/chromeos/dbus/audio_node.h +++ b/chromeos/dbus/audio_node.h @@ -25,6 +25,13 @@ struct CHROMEOS_EXPORT AudioNode { uint64 plugged_time; AudioNode(); + AudioNode(bool is_input, + uint64 id, + std::string device_name, + std::string type, + std::string name, + bool active, + uint64 plugged_time); std::string ToString() const; }; diff --git a/chromeos/dbus/cras_audio_client.cc b/chromeos/dbus/cras_audio_client.cc index 8919e52..411314e 100644 --- a/chromeos/dbus/cras_audio_client.cc +++ b/chromeos/dbus/cras_audio_client.cc @@ -7,6 +7,7 @@ #include "base/bind.h" #include "base/format_macros.h" #include "base/strings/stringprintf.h" +#include "chromeos/dbus/cras_audio_client_stub_impl.h" #include "dbus/bus.h" #include "dbus/message.h" #include "dbus/object_path.h" @@ -350,150 +351,6 @@ class CrasAudioClientImpl : public CrasAudioClient { DISALLOW_COPY_AND_ASSIGN(CrasAudioClientImpl); }; -// The CrasAudioClient implementation used on Linux desktop, -// which does nothing. -class CrasAudioClientStubImpl : public CrasAudioClient { - public: - CrasAudioClientStubImpl() { - VLOG(1) << "CrasAudioClientStubImpl is created"; - - // Fake audio output nodes. - AudioNode node_1; - node_1.is_input = false; - node_1.id = 10001; - node_1.device_name = "Fake Speaker"; - node_1.type = "INTERNAL_SPEAKER"; - node_1.name = "Speaker"; - node_1.active = false; - node_list_.push_back(node_1); - - AudioNode node_2; - node_2.is_input = false; - node_2.id = 10002; - node_2.device_name = "Fake Headphone"; - node_2.type = "HEADPHONE"; - node_2.name = "Headphone"; - node_2.active = true; - node_list_.push_back(node_2); - active_output_node_id_ = node_2.id; - - AudioNode node_3; - node_3.is_input = false; - node_3.id = 10003; - node_3.device_name = "Fake Audio Output"; - node_3.type = "BLUETOOTH"; - node_3.name = "Bluetooth Headphone"; - node_3.active = false; - node_list_.push_back(node_3); - - // Fake audio input ndoes - AudioNode node_4; - node_4.is_input = true; - node_4.id = 10004; - node_4.device_name = "Fake Internal Mic"; - node_4.type = "INTERNAL_MIC"; - node_4.name = "Internal Mic"; - node_4.active = false; - node_list_.push_back(node_4); - - AudioNode node_5; - node_5.is_input = true; - node_5.id = 10005; - node_5.device_name = "Fake Internal Mic"; - node_5.type = "USB"; - node_5.name = "USB Mic"; - node_5.active = true; - node_list_.push_back(node_5); - active_input_node_id_ = node_5.id; - } - virtual ~CrasAudioClientStubImpl() { - } - - // CrasAudioClient overrides: - // TODO(jennyz): Implement the observers and callbacks in the stub for UI - // testing. - virtual void AddObserver(Observer* observer) OVERRIDE { - observers_.AddObserver(observer); - } - - virtual void RemoveObserver(Observer* observer) OVERRIDE { - observers_.RemoveObserver(observer); - } - - virtual bool HasObserver(Observer* observer) OVERRIDE { - return observers_.HasObserver(observer); - } - - virtual void GetVolumeState(const GetVolumeStateCallback& callback) OVERRIDE { - callback.Run(volume_state_, true); - } - - virtual void GetNodes(const GetNodesCallback& callback)OVERRIDE { - callback.Run(node_list_, true); - } - - virtual void SetOutputNodeVolume(uint64 node_id, int32 volume) OVERRIDE { - } - - virtual void SetOutputUserMute(bool mute_on) OVERRIDE { - volume_state_.output_user_mute = mute_on; - FOR_EACH_OBSERVER(Observer, - observers_, - OutputMuteChanged(volume_state_.output_user_mute)); - } - - virtual void SetInputNodeGain(uint64 node_id, int32 input_gain) OVERRIDE { - } - - virtual void SetInputMute(bool mute_on) OVERRIDE { - volume_state_.input_mute = mute_on; - FOR_EACH_OBSERVER(Observer, - observers_, - InputMuteChanged(volume_state_.input_mute)); - } - - virtual void SetActiveOutputNode(uint64 node_id) OVERRIDE { - if (active_output_node_id_ == node_id) - return; - - for (size_t i = 0; i < node_list_.size(); ++i) { - if (node_list_[i].id == active_output_node_id_) - node_list_[i].active = false; - else if (node_list_[i].id == node_id) - node_list_[i].active = true; - } - active_output_node_id_ = node_id; - FOR_EACH_OBSERVER(Observer, - observers_, - ActiveOutputNodeChanged(node_id)); - } - - virtual void SetActiveInputNode(uint64 node_id) OVERRIDE { - if (active_input_node_id_ == node_id) - return; - - for (size_t i = 0; i < node_list_.size(); ++i) { - if (node_list_[i].id == active_input_node_id_) - node_list_[i].active = false; - else if (node_list_[i].id == node_id) - node_list_[i].active = true; - } - active_input_node_id_ = node_id; - FOR_EACH_OBSERVER(Observer, - observers_, - ActiveInputNodeChanged(node_id)); - } - - private: - VolumeState volume_state_; - AudioNodeList node_list_; - uint64 active_input_node_id_; - uint64 active_output_node_id_; - ObserverList<Observer> observers_; - - DISALLOW_COPY_AND_ASSIGN(CrasAudioClientStubImpl); -}; - CrasAudioClient::Observer::~Observer() { } diff --git a/chromeos/dbus/cras_audio_client_stub_impl.cc b/chromeos/dbus/cras_audio_client_stub_impl.cc new file mode 100644 index 0000000..b5b61c23 --- /dev/null +++ b/chromeos/dbus/cras_audio_client_stub_impl.cc @@ -0,0 +1,153 @@ +// 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/dbus/cras_audio_client_stub_impl.h" + +namespace chromeos { + +CrasAudioClientStubImpl::CrasAudioClientStubImpl() { + VLOG(1) << "CrasAudioClientStubImpl is created"; + + // Fake audio output nodes. + AudioNode node_1; + node_1.is_input = false; + node_1.id = 10001; + node_1.device_name = "Fake Speaker"; + node_1.type = "INTERNAL_SPEAKER"; + node_1.name = "Speaker"; + node_1.active = false; + node_list_.push_back(node_1); + + AudioNode node_2; + node_2.is_input = false; + node_2.id = 10002; + node_2.device_name = "Fake Headphone"; + node_2.type = "HEADPHONE"; + node_2.name = "Headphone"; + node_2.active = false; + node_list_.push_back(node_2); + active_output_node_id_ = node_2.id; + + AudioNode node_3; + node_3.is_input = false; + node_3.id = 10003; + node_3.device_name = "Fake Bluetooth Headphone"; + node_3.type = "BLUETOOTH"; + node_3.name = "Bluetooth Headphone"; + node_3.active = false; + node_list_.push_back(node_3); + + // Fake audio input ndoes + AudioNode node_4; + node_4.is_input = true; + node_4.id = 10004; + node_4.device_name = "Fake Internal Mic"; + node_4.type = "INTERNAL_MIC"; + node_4.name = "Internal Mic"; + node_4.active = false; + node_list_.push_back(node_4); + + AudioNode node_5; + node_5.is_input = true; + node_5.id = 10005; + node_5.device_name = "Fake USB Mic"; + node_5.type = "USB"; + node_5.name = "USB Mic"; + node_5.active = true; + node_list_.push_back(node_5); + + active_input_node_id_ = node_5.id; +} + +CrasAudioClientStubImpl::~CrasAudioClientStubImpl() { +} + +void CrasAudioClientStubImpl::AddObserver(Observer* observer) { + observers_.AddObserver(observer); +} + +void CrasAudioClientStubImpl::RemoveObserver(Observer* observer) { + observers_.RemoveObserver(observer); +} + +bool CrasAudioClientStubImpl::HasObserver(Observer* observer) { + return observers_.HasObserver(observer); +} + +void CrasAudioClientStubImpl::GetVolumeState( + const GetVolumeStateCallback& callback) { + callback.Run(volume_state_, true); +} + +void CrasAudioClientStubImpl::GetNodes(const GetNodesCallback& callback) { + callback.Run(node_list_, true); +} + +void CrasAudioClientStubImpl::SetOutputNodeVolume(uint64 node_id, + int32 volume) { +} + +void CrasAudioClientStubImpl::SetOutputUserMute(bool mute_on) { + volume_state_.output_user_mute = mute_on; + FOR_EACH_OBSERVER(Observer, + observers_, + OutputMuteChanged(volume_state_.output_user_mute)); +} + +void CrasAudioClientStubImpl::SetInputNodeGain(uint64 node_id, + int32 input_gain) { +} + +void CrasAudioClientStubImpl::SetInputMute(bool mute_on) { + volume_state_.input_mute = mute_on; + FOR_EACH_OBSERVER(Observer, + observers_, + InputMuteChanged(volume_state_.input_mute)); +} + +void CrasAudioClientStubImpl::SetActiveOutputNode(uint64 node_id) { + if (active_output_node_id_ == node_id) + return; + + for (size_t i = 0; i < node_list_.size(); ++i) { + if (node_list_[i].id == active_output_node_id_) + node_list_[i].active = false; + else if (node_list_[i].id == node_id) + node_list_[i].active = true; + } + active_output_node_id_ = node_id; + FOR_EACH_OBSERVER(Observer, + observers_, + ActiveOutputNodeChanged(node_id)); +} + +void CrasAudioClientStubImpl::SetActiveInputNode(uint64 node_id) { + if (active_input_node_id_ == node_id) + return; + + for (size_t i = 0; i < node_list_.size(); ++i) { + if (node_list_[i].id == active_input_node_id_) + node_list_[i].active = false; + else if (node_list_[i].id == node_id) + node_list_[i].active = true; + } + active_input_node_id_ = node_id; + FOR_EACH_OBSERVER(Observer, + observers_, + ActiveInputNodeChanged(node_id)); +} + +void CrasAudioClientStubImpl::SetAudioDevices( + const AudioNodeList& audio_nodes) { + node_list_.clear(); + for (size_t i = 0; i < audio_nodes.size(); ++i) + node_list_.push_back(audio_nodes[i]); +} + +void CrasAudioClientStubImpl::ChangeAudioNodes(const AudioNodeList& new_nodes) { + SetAudioDevices(new_nodes); + FOR_EACH_OBSERVER(Observer, observers_, NodesChanged()); +} + +} // namespace chromeos diff --git a/chromeos/dbus/cras_audio_client_stub_impl.h b/chromeos/dbus/cras_audio_client_stub_impl.h new file mode 100644 index 0000000..032305f --- /dev/null +++ b/chromeos/dbus/cras_audio_client_stub_impl.h @@ -0,0 +1,52 @@ +// 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_DBUS_CRAS_AUDIO_CLIENT_STUB_IMPL_H_ +#define CHROMEOS_DBUS_CRAS_AUDIO_CLIENT_STUB_IMPL_H_ + +#include "chromeos/dbus/cras_audio_client.h" + +namespace chromeos { + +class CrasAudioHandlerTest; + +// The CrasAudioClient implementation used on Linux desktop. +class CrasAudioClientStubImpl : public CrasAudioClient { + public: + CrasAudioClientStubImpl(); + virtual ~CrasAudioClientStubImpl(); + + // CrasAudioClient overrides: + virtual void AddObserver(Observer* observer) OVERRIDE; + virtual void RemoveObserver(Observer* observer) OVERRIDE; + virtual bool HasObserver(Observer* observer) OVERRIDE; + virtual void GetVolumeState(const GetVolumeStateCallback& callback) OVERRIDE; + virtual void GetNodes(const GetNodesCallback& callback) OVERRIDE; + virtual void SetOutputNodeVolume(uint64 node_id, int32 volume) OVERRIDE; + virtual void SetOutputUserMute(bool mute_on) OVERRIDE; + virtual void SetInputNodeGain(uint64 node_id, int32 gain) OVERRIDE; + virtual void SetInputMute(bool mute_on) OVERRIDE; + virtual void SetActiveOutputNode(uint64 node_id) OVERRIDE; + virtual void SetActiveInputNode(uint64 node_id) OVERRIDE; + + protected: + // Helper functions for testing + virtual void SetAudioDevices(const AudioNodeList& audio_nodes); + virtual void ChangeAudioNodes(const AudioNodeList& new_nodes); + + private: + friend class CrasAudioHandlerTest; + + VolumeState volume_state_; + AudioNodeList node_list_; + uint64 active_input_node_id_; + uint64 active_output_node_id_; + ObserverList<Observer> observers_; + + DISALLOW_COPY_AND_ASSIGN(CrasAudioClientStubImpl); +}; + +} // namespace chromeos + +#endif // CHROMEOS_DBUS_CRAS_AUDIO_CLIENT_STUB_IMPL_H_ |