1# Copyright 2015 The Chromium OS 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.
4
5"""This is a server side audio nodes s test using the Chameleon board."""
6
7import os
8import time
9
10from autotest_lib.client.common_lib import error
11from autotest_lib.client.cros.chameleon import audio_test_utils
12from autotest_lib.client.cros.chameleon import chameleon_audio_ids
13from autotest_lib.client.cros.chameleon import chameleon_audio_helper
14from autotest_lib.client.cros.chameleon import chameleon_port_finder
15
16from autotest_lib.client.cros.chameleon import edid as edid_lib
17from autotest_lib.server.cros.audio import audio_test
18from autotest_lib.server.cros.multimedia import remote_facade_factory
19
20
21
22class audio_AudioNodeSwitch(audio_test.AudioTest):
23    """Server side audio test.
24
25    This test talks to a Chameleon board and a Cros device to verify
26    audio nodes switch correctly.
27
28    """
29    version = 1
30    _APPLY_EDID_DELAY = 5
31    _PLUG_DELAY = 5
32    _VOLUMES = {'INTERNAL_SPEAKER': 100,
33                'HEADPHONE': 80,
34                'LINEOUT': 80,
35                'HDMI': 60,
36                'USB': 40,}
37
38    def check_default_nodes(self):
39        """Checks default audio nodes for devices with onboard audio support."""
40        if audio_test_utils.has_internal_microphone(self.host):
41            audio_test_utils.check_audio_nodes(self.audio_facade,
42                                               (None, ['INTERNAL_MIC']))
43        if audio_test_utils.has_internal_speaker(self.host):
44            audio_test_utils.check_audio_nodes(self.audio_facade,
45                                               (['INTERNAL_SPEAKER'], None))
46
47
48    def set_active_volume_to_node_volume(self, node):
49        """Sets Chrome volume to the specified volume of node.
50
51        @param node: One of node type in self._VOLUMES.
52
53        """
54        self.audio_facade.set_chrome_active_volume(self._VOLUMES[node])
55
56
57    def check_active_node_volume(self, node):
58        """Checks the active node type and checks if its volume is as expected.
59
60        @param node: The expected node.
61
62        @raises: TestFail if node volume is not as expected.
63
64        """
65        # Checks the node type is the active node type.
66        audio_test_utils.check_audio_nodes(self.audio_facade, ([node], None))
67        # Checks if active volume is the node volume.
68        volume, mute = self.audio_facade.get_chrome_active_volume_mute()
69        expected_volume = self._VOLUMES[node]
70        if volume != expected_volume:
71            raise error.TestFail(
72                    'Node %s volume %d != %d' % (node, volume, expected_volume))
73
74
75    def switch_nodes_and_check_volume(self, nodes):
76        """Switches between nodes and check the node volumes.
77
78        @param nodes: A list of node types to check.
79
80        """
81        if len(nodes) == 1:
82            self.check_active_node_volume(nodes[0])
83        for node in nodes:
84            # Switch nodes and check their volume.
85            self.audio_facade.set_chrome_active_node_type(node, None)
86            self.check_active_node_volume(node)
87
88
89    def run_once(self, host, jack_node=False, hdmi_node=False, usb_node=False):
90        self.host = host
91        chameleon_board = host.chameleon
92        audio_board = chameleon_board.get_audio_board()
93        factory = remote_facade_factory.RemoteFacadeFactory(
94                host, results_dir=self.resultsdir)
95
96        chameleon_board.setup_and_reset(self.outputdir)
97        self.audio_facade = factory.create_audio_facade()
98        self.display_facade = factory.create_display_facade()
99
100        self.check_default_nodes()
101        nodes = []
102        if audio_test_utils.has_internal_speaker(self.host):
103            self.set_active_volume_to_node_volume('INTERNAL_SPEAKER')
104            nodes.append('INTERNAL_SPEAKER')
105            self.switch_nodes_and_check_volume(nodes)
106
107
108        if hdmi_node:
109            edid_path = os.path.join(self.bindir,
110                                     'test_data/edids/HDMI_DELL_U2410.txt')
111            finder = chameleon_port_finder.ChameleonVideoInputFinder(
112                chameleon_board, self.display_facade)
113            hdmi_port = finder.find_port('HDMI')
114            hdmi_port.apply_edid(edid_lib.Edid.from_file(edid_path))
115            time.sleep(self._APPLY_EDID_DELAY)
116            hdmi_port.set_plug(True)
117            time.sleep(self._PLUG_DELAY * 2)
118
119            audio_test_utils.check_audio_nodes(self.audio_facade,
120                                               (['HDMI'], None))
121
122            self.set_active_volume_to_node_volume('HDMI')
123            nodes.append('HDMI')
124            self.switch_nodes_and_check_volume(nodes)
125
126        if jack_node:
127            jack_plugger = audio_board.get_jack_plugger()
128            jack_plugger.plug()
129            time.sleep(self._PLUG_DELAY)
130            audio_test_utils.dump_cros_audio_logs(host, self.audio_facade,
131                                                  self.resultsdir)
132
133            # Checks whether line-out or headphone is detected.
134            hp_jack_node_type = audio_test_utils.check_hp_or_lineout_plugged(
135                    self.audio_facade)
136
137            audio_test_utils.check_audio_nodes(self.audio_facade,
138                                               (None, ['MIC']))
139
140            self.set_active_volume_to_node_volume(hp_jack_node_type)
141
142            nodes.append(hp_jack_node_type)
143            self.switch_nodes_and_check_volume(nodes)
144
145        if usb_node:
146            widget_factory = chameleon_audio_helper.AudioWidgetFactory(
147                factory, host)
148
149            source = widget_factory.create_widget(
150                chameleon_audio_ids.CrosIds.USBOUT)
151            recorder = widget_factory.create_widget(
152                chameleon_audio_ids.ChameleonIds.USBIN)
153            binder = widget_factory.create_binder(source, recorder)
154
155            with chameleon_audio_helper.bind_widgets(binder):
156                time.sleep(self._PLUG_DELAY)
157                audio_test_utils.check_audio_nodes(self.audio_facade,
158                                                   (['USB'], ['USB']))
159                self.set_active_volume_to_node_volume('USB')
160                nodes.append('USB')
161                self.switch_nodes_and_check_volume(nodes)
162            time.sleep(self._PLUG_DELAY)
163            nodes.remove('USB')
164            self.switch_nodes_and_check_volume(nodes)
165
166        if jack_node:
167            if usb_node:
168                audio_test_utils.check_audio_nodes(self.audio_facade,
169                                                   ([hp_jack_node_type], ['MIC']))
170            jack_plugger.unplug()
171            time.sleep(self._PLUG_DELAY)
172            nodes.remove(hp_jack_node_type)
173            self.switch_nodes_and_check_volume(nodes)
174
175        if hdmi_node:
176            if usb_node or jack_node :
177                audio_test_utils.check_audio_nodes(self.audio_facade,
178                                                   (['HDMI'], None))
179            hdmi_port.set_plug(False)
180            time.sleep(self._PLUG_DELAY)
181            nodes.remove('HDMI')
182            self.switch_nodes_and_check_volume(nodes)
183
184        self.check_default_nodes()
185
186