1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "extensions/shell/browser/shell_audio_controller_chromeos.h"
7 #include "base/macros.h"
8 #include "chromeos/audio/audio_device.h"
9 #include "chromeos/audio/audio_devices_pref_handler.h"
10 #include "chromeos/audio/cras_audio_handler.h"
11 #include "chromeos/dbus/audio_node.h"
12 #include "chromeos/dbus/dbus_thread_manager.h"
13 #include "chromeos/dbus/fake_cras_audio_client.h"
14 #include "testing/gtest/include/gtest/gtest.h"
16 using chromeos::AudioDevice
;
17 using chromeos::AudioNode
;
18 using chromeos::AudioNodeList
;
20 namespace extensions
{
22 class ShellAudioControllerTest
: public testing::Test
{
24 ShellAudioControllerTest() : next_node_id_(1) {
25 // This also initializes DBusThreadManager.
26 scoped_ptr
<chromeos::DBusThreadManagerSetter
> dbus_setter
=
27 chromeos::DBusThreadManager::GetSetterForTesting();
29 audio_client_
= new chromeos::FakeCrasAudioClient();
30 audio_client_
->SetAudioNodesForTesting(AudioNodeList());
31 dbus_setter
->SetCrasAudioClient(make_scoped_ptr(audio_client_
));
33 chromeos::CrasAudioHandler::InitializeForTesting();
34 audio_handler_
= chromeos::CrasAudioHandler::Get();
36 controller_
.reset(new ShellAudioController());
39 ~ShellAudioControllerTest() override
{
41 chromeos::CrasAudioHandler::Shutdown();
42 chromeos::DBusThreadManager::Shutdown();
46 // Fills a AudioNode for use by tests.
47 AudioNode
CreateNode(chromeos::AudioDeviceType type
) {
50 type
== chromeos::AUDIO_TYPE_MIC
||
51 type
== chromeos::AUDIO_TYPE_INTERNAL_MIC
||
52 type
== chromeos::AUDIO_TYPE_KEYBOARD_MIC
;
53 node
.id
= next_node_id_
++;
54 node
.type
= AudioDevice::GetTypeString(type
);
58 // Changes the active state of the node with |id| in |nodes|.
59 void SetNodeActive(AudioNodeList
* nodes
, uint64 id
, bool active
) {
60 for (AudioNodeList::iterator it
= nodes
->begin();
61 it
!= nodes
->end(); ++it
) {
67 ASSERT_TRUE(false) << "Didn't find ID " << id
;
70 chromeos::FakeCrasAudioClient
* audio_client_
; // Not owned.
71 chromeos::CrasAudioHandler
* audio_handler_
; // Not owned.
72 scoped_ptr
<ShellAudioController
> controller_
;
74 // Next audio node ID to be returned by CreateNode().
78 DISALLOW_COPY_AND_ASSIGN(ShellAudioControllerTest
);
81 // Tests that higher-priority devices are activated as soon as they're
83 TEST_F(ShellAudioControllerTest
, SelectBestDevices
) {
84 AudioNode internal_speaker
=
85 CreateNode(chromeos::AUDIO_TYPE_INTERNAL_SPEAKER
);
86 AudioNode internal_mic
= CreateNode(chromeos::AUDIO_TYPE_INTERNAL_MIC
);
87 AudioNode headphone
= CreateNode(chromeos::AUDIO_TYPE_HEADPHONE
);
88 AudioNode external_mic
= CreateNode(chromeos::AUDIO_TYPE_MIC
);
90 // AudioDevice gives the headphone jack a higher priority than the internal
91 // speaker and an external mic a higher priority than the internal mic, so we
92 // should start out favoring headphones and the external mic.
93 AudioNodeList all_nodes
;
94 all_nodes
.push_back(internal_speaker
);
95 all_nodes
.push_back(internal_mic
);
96 all_nodes
.push_back(headphone
);
97 all_nodes
.push_back(external_mic
);
98 audio_client_
->SetAudioNodesAndNotifyObserversForTesting(all_nodes
);
99 EXPECT_EQ(headphone
.id
, audio_handler_
->GetPrimaryActiveOutputNode());
100 EXPECT_EQ(external_mic
.id
, audio_handler_
->GetPrimaryActiveInputNode());
102 // Unplug the headphones and mic and check that we switch to the internal
104 AudioNodeList internal_nodes
;
105 internal_nodes
.push_back(internal_speaker
);
106 internal_nodes
.push_back(internal_mic
);
107 audio_client_
->SetAudioNodesAndNotifyObserversForTesting(internal_nodes
);
108 EXPECT_EQ(internal_speaker
.id
, audio_handler_
->GetPrimaryActiveOutputNode());
109 EXPECT_EQ(internal_mic
.id
, audio_handler_
->GetPrimaryActiveInputNode());
111 // Switch back to the external devices. Mark the previously-activated internal
112 // devices as being active so CrasAudioHandler doesn't complain.
113 SetNodeActive(&all_nodes
, internal_speaker
.id
, true);
114 SetNodeActive(&all_nodes
, internal_mic
.id
, true);
115 audio_client_
->SetAudioNodesAndNotifyObserversForTesting(all_nodes
);
116 EXPECT_EQ(headphone
.id
, audio_handler_
->GetPrimaryActiveOutputNode());
117 EXPECT_EQ(external_mic
.id
, audio_handler_
->GetPrimaryActiveInputNode());
120 // Tests that active audio devices are unmuted and have correct initial volume.
121 TEST_F(ShellAudioControllerTest
, InitialVolume
) {
123 nodes
.push_back(CreateNode(chromeos::AUDIO_TYPE_INTERNAL_SPEAKER
));
124 nodes
.push_back(CreateNode(chromeos::AUDIO_TYPE_INTERNAL_MIC
));
125 audio_client_
->SetAudioNodesAndNotifyObserversForTesting(nodes
);
127 EXPECT_FALSE(audio_handler_
->IsOutputMuted());
128 EXPECT_FALSE(audio_handler_
->IsInputMuted());
129 EXPECT_EQ(static_cast<double>(
130 chromeos::AudioDevicesPrefHandler::kDefaultOutputVolumePercent
),
131 audio_handler_
->GetOutputVolumePercent());
133 // TODO(rkc): The default value for gain is wrong. http://crbug.com/442489
134 EXPECT_EQ(75.0, audio_handler_
->GetInputGainPercent());
137 } // namespace extensions