// 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 #include #include "base/message_loop/message_loop.h" #include "build/build_config.h" #include "extensions/shell/test/shell_apitest.h" #if defined(OS_CHROMEOS) #include "chromeos/audio/audio_devices_pref_handler_stub.h" #include "chromeos/audio/cras_audio_handler.h" #include "chromeos/dbus/dbus_thread_manager.h" #include "chromeos/dbus/fake_cras_audio_client.h" #endif #include "extensions/test/extension_test_message_listener.h" namespace extensions { #if defined(OS_CHROMEOS) using chromeos::AudioDevice; using chromeos::AudioDeviceList; using chromeos::AudioNode; using chromeos::AudioNodeList; const uint64_t kJabraSpeaker1Id = 30001; const uint64_t kJabraSpeaker1StableDeviceId = 80001; const uint64_t kJabraSpeaker2Id = 30002; const uint64_t kJabraSpeaker2StableDeviceId = 80002; const uint64_t kHDMIOutputId = 30003; const uint64_t kHDMIOutputStabeDevicelId = 80003; const uint64_t kJabraMic1Id = 40001; const uint64_t kJabraMic1StableDeviceId = 90001; const uint64_t kJabraMic2Id = 40002; const uint64_t kJabraMic2StableDeviceId = 90002; const uint64_t kWebcamMicId = 40003; const uint64_t kWebcamMicStableDeviceId = 90003; const AudioNode kJabraSpeaker1(false, kJabraSpeaker1Id, kJabraSpeaker1StableDeviceId, "Jabra Speaker", "USB", "Jabra Speaker 1", false, 0); const AudioNode kJabraSpeaker2(false, kJabraSpeaker2Id, kJabraSpeaker2StableDeviceId, "Jabra Speaker", "USB", "Jabra Speaker 2", false, 0); const AudioNode kHDMIOutput(false, kHDMIOutputId, kHDMIOutputStabeDevicelId, "HDMI output", "HDMI", "HDA Intel MID", false, 0); const AudioNode kJabraMic1(true, kJabraMic1Id, kJabraMic1StableDeviceId, "Jabra Mic", "USB", "Jabra Mic 1", false, 0); const AudioNode kJabraMic2(true, kJabraMic2Id, kJabraMic2StableDeviceId, "Jabra Mic", "USB", "Jabra Mic 2", false, 0); const AudioNode kUSBCameraMic(true, kWebcamMicId, kWebcamMicStableDeviceId, "Webcam Mic", "USB", "Logitech Webcam", false, 0); class AudioApiTest : public ShellApiTest { public: AudioApiTest() : cras_audio_handler_(NULL), fake_cras_audio_client_(NULL) {} ~AudioApiTest() override {} void SetUpCrasAudioHandlerWithTestingNodes(const AudioNodeList& audio_nodes) { chromeos::DBusThreadManager* dbus_manager = chromeos::DBusThreadManager::Get(); DCHECK(dbus_manager); fake_cras_audio_client_ = static_cast( dbus_manager->GetCrasAudioClient()); fake_cras_audio_client_->SetAudioNodesAndNotifyObserversForTesting( audio_nodes); cras_audio_handler_ = chromeos::CrasAudioHandler::Get(); DCHECK(cras_audio_handler_); message_loop_.RunUntilIdle(); } void ChangeAudioNodes(const AudioNodeList& audio_nodes) { DCHECK(fake_cras_audio_client_); fake_cras_audio_client_->SetAudioNodesAndNotifyObserversForTesting( audio_nodes); message_loop_.RunUntilIdle(); } protected: base::MessageLoopForUI message_loop_; chromeos::CrasAudioHandler* cras_audio_handler_; // Not owned. chromeos::FakeCrasAudioClient* fake_cras_audio_client_; // Not owned. }; IN_PROC_BROWSER_TEST_F(AudioApiTest, Audio) { // Set up the audio nodes for testing. AudioNodeList audio_nodes; audio_nodes.push_back(kJabraSpeaker1); audio_nodes.push_back(kJabraSpeaker2); audio_nodes.push_back(kHDMIOutput); audio_nodes.push_back(kJabraMic1); audio_nodes.push_back(kJabraMic2); audio_nodes.push_back(kUSBCameraMic); SetUpCrasAudioHandlerWithTestingNodes(audio_nodes); EXPECT_TRUE(RunAppTest("api_test/audio")) << message_; } IN_PROC_BROWSER_TEST_F(AudioApiTest, OnLevelChangedOutputDevice) { AudioNodeList audio_nodes; audio_nodes.push_back(kJabraSpeaker1); audio_nodes.push_back(kHDMIOutput); SetUpCrasAudioHandlerWithTestingNodes(audio_nodes); // Verify the jabra speaker is the active output device. AudioDevice device; EXPECT_TRUE(cras_audio_handler_->GetPrimaryActiveOutputDevice(&device)); EXPECT_EQ(device.id, kJabraSpeaker1.id); // Loads background app. ExtensionTestMessageListener load_listener("loaded", false); ExtensionTestMessageListener result_listener("success", false); result_listener.set_failure_message("failure"); ASSERT_TRUE(LoadApp("api_test/audio/volume_change")); ASSERT_TRUE(load_listener.WaitUntilSatisfied()); // Change output device volume. const int kVolume = 60; cras_audio_handler_->SetOutputVolumePercent(kVolume); // Verify the output volume is changed to the designated value. EXPECT_EQ(kVolume, cras_audio_handler_->GetOutputVolumePercent()); EXPECT_EQ(kVolume, cras_audio_handler_->GetOutputVolumePercentForDevice(device.id)); // Verify the background app got the OnOutputNodeVolumeChanged event // with the expected node id and volume value. ASSERT_TRUE(result_listener.WaitUntilSatisfied()); EXPECT_EQ("success", result_listener.message()); } IN_PROC_BROWSER_TEST_F(AudioApiTest, OnOutputMuteChanged) { AudioNodeList audio_nodes; audio_nodes.push_back(kJabraSpeaker1); audio_nodes.push_back(kHDMIOutput); SetUpCrasAudioHandlerWithTestingNodes(audio_nodes); // Verify the jabra speaker is the active output device. AudioDevice device; EXPECT_TRUE(cras_audio_handler_->GetPrimaryActiveOutputDevice(&device)); EXPECT_EQ(device.id, kJabraSpeaker1.id); // Mute the output. cras_audio_handler_->SetOutputMute(true); EXPECT_TRUE(cras_audio_handler_->IsOutputMuted()); // Loads background app. ExtensionTestMessageListener load_listener("loaded", false); ExtensionTestMessageListener result_listener("success", false); result_listener.set_failure_message("failure"); ASSERT_TRUE(LoadApp("api_test/audio/output_mute_change")); ASSERT_TRUE(load_listener.WaitUntilSatisfied()); // Un-mute the output. cras_audio_handler_->SetOutputMute(false); EXPECT_FALSE(cras_audio_handler_->IsOutputMuted()); // Verify the background app got the OnMuteChanged event // with the expected output un-muted state. ASSERT_TRUE(result_listener.WaitUntilSatisfied()); EXPECT_EQ("success", result_listener.message()); } IN_PROC_BROWSER_TEST_F(AudioApiTest, OnInputMuteChanged) { AudioNodeList audio_nodes; audio_nodes.push_back(kJabraMic1); audio_nodes.push_back(kUSBCameraMic); SetUpCrasAudioHandlerWithTestingNodes(audio_nodes); // Set the jabra mic to be the active input device. AudioDevice jabra_mic(kJabraMic1); cras_audio_handler_->SwitchToDevice(jabra_mic, true); EXPECT_EQ(kJabraMic1.id, cras_audio_handler_->GetPrimaryActiveInputNode()); // Un-mute the input. cras_audio_handler_->SetInputMute(false); EXPECT_FALSE(cras_audio_handler_->IsInputMuted()); // Loads background app. ExtensionTestMessageListener load_listener("loaded", false); ExtensionTestMessageListener result_listener("success", false); result_listener.set_failure_message("failure"); ASSERT_TRUE(LoadApp("api_test/audio/input_mute_change")); ASSERT_TRUE(load_listener.WaitUntilSatisfied()); // Mute the input. cras_audio_handler_->SetInputMute(true); EXPECT_TRUE(cras_audio_handler_->IsInputMuted()); // Verify the background app got the OnMuteChanged event // with the expected input muted state. ASSERT_TRUE(result_listener.WaitUntilSatisfied()); EXPECT_EQ("success", result_listener.message()); } IN_PROC_BROWSER_TEST_F(AudioApiTest, OnNodesChangedAddNodes) { AudioNodeList audio_nodes; audio_nodes.push_back(kJabraSpeaker1); audio_nodes.push_back(kJabraSpeaker2); SetUpCrasAudioHandlerWithTestingNodes(audio_nodes); const size_t init_device_size = audio_nodes.size(); AudioDeviceList audio_devices; cras_audio_handler_->GetAudioDevices(&audio_devices); EXPECT_EQ(init_device_size, audio_devices.size()); // Load background app. ExtensionTestMessageListener load_listener("loaded", false); ExtensionTestMessageListener result_listener("success", false); result_listener.set_failure_message("failure"); ASSERT_TRUE(LoadApp("api_test/audio/add_nodes")); ASSERT_TRUE(load_listener.WaitUntilSatisfied()); // Plug in HDMI output. audio_nodes.push_back(kHDMIOutput); ChangeAudioNodes(audio_nodes); cras_audio_handler_->GetAudioDevices(&audio_devices); EXPECT_EQ(init_device_size + 1, audio_devices.size()); // Verify the background app got the OnNodesChanged event // with the new node added. ASSERT_TRUE(result_listener.WaitUntilSatisfied()); EXPECT_EQ("success", result_listener.message()); } IN_PROC_BROWSER_TEST_F(AudioApiTest, OnNodesChangedRemoveNodes) { AudioNodeList audio_nodes; audio_nodes.push_back(kJabraMic1); audio_nodes.push_back(kJabraMic2); audio_nodes.push_back(kUSBCameraMic); SetUpCrasAudioHandlerWithTestingNodes(audio_nodes); const size_t init_device_size = audio_nodes.size(); AudioDeviceList audio_devices; cras_audio_handler_->GetAudioDevices(&audio_devices); EXPECT_EQ(init_device_size, audio_devices.size()); // Load background app. ExtensionTestMessageListener load_listener("loaded", false); ExtensionTestMessageListener result_listener("success", false); result_listener.set_failure_message("failure"); ASSERT_TRUE(LoadApp("api_test/audio/remove_nodes")); ASSERT_TRUE(load_listener.WaitUntilSatisfied()); // Remove camera mic. audio_nodes.erase(audio_nodes.begin() + init_device_size - 1); ChangeAudioNodes(audio_nodes); cras_audio_handler_->GetAudioDevices(&audio_devices); EXPECT_EQ(init_device_size - 1, audio_devices.size()); // Verify the background app got the onNodesChanged event // with the last node removed. ASSERT_TRUE(result_listener.WaitUntilSatisfied()); EXPECT_EQ("success", result_listener.message()); } #endif // OS_CHROMEOS } // namespace extensions