• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright 2014 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 display lid close and open test using the Chameleon board."""
6
7import logging, time
8
9from autotest_lib.client.common_lib import error
10from autotest_lib.client.cros.chameleon import chameleon_port_finder
11from autotest_lib.client.cros.chameleon import chameleon_screen_test
12from autotest_lib.server import test
13from autotest_lib.server.cros.multimedia import remote_facade_factory
14
15class display_LidCloseOpen(test.test):
16    """External Display Lid Close/Open test. """
17    version = 1
18
19    # Time to check if device is suspended
20    TIMEOUT_SUSPEND_CHECK = 5
21    # Allowed timeout for the transition of suspend.
22    TIMEOUT_SUSPEND_TRANSITION = 30
23    # Allowed timeout for the transition of resume.
24    TIMEOUT_RESUME_TRANSITION = 60
25    # Time to allow for table video input
26    WAIT_TIME_STABLE_VIDEO_INPUT = 10
27    # Time to allow lid transition to take effect
28    WAIT_TIME_LID_TRANSITION = 5
29    # Time to allow display port plug transition to take effect
30    WAIT_TIME_PLUG_TRANSITION = 5
31    # Some boards do not play well with servo - crosbug.com/p/27591
32    INCOMPATIBLE_SERVO_BOARDS = ['daisy', 'falco', 'auron_paine']
33
34
35    def close_lid(self):
36        """Close lid through servo"""
37        logging.info('CLOSING LID...')
38        self.host.servo.lid_close()
39        time.sleep(self.WAIT_TIME_LID_TRANSITION)
40
41
42    def open_lid(self):
43        """Open lid through servo"""
44        logging.info('OPENING LID...')
45        self.host.servo.lid_open()
46        time.sleep(self.WAIT_TIME_LID_TRANSITION)
47
48
49    def check_primary_display_on_internal_screen(self):
50        """Checks primary display is on onboard/internal screen"""
51        if not self.display_facade.is_display_primary(internal=True):
52            raise error.TestFail('Primary display is not on internal screen')
53
54
55    def check_primary_display_on_external_screen(self):
56        """Checks primary display is on external screen"""
57        if not self.display_facade.is_display_primary(internal=False):
58            raise error.TestFail('Primary display is not on external screen')
59
60
61    def check_mode(self):
62        """Checks the display mode is as expected"""
63        if self.display_facade.is_mirrored_enabled() is not self.test_mirrored:
64            raise error.TestFail('Display mode %s is not preserved!' %
65                                 ('mirrored' if self.test_mirrored
66                                     else 'extended'))
67
68
69    def check_docked(self):
70        """Checks DUT is docked"""
71        # Device does not suspend
72        if self.host.ping_wait_down(timeout=self.TIMEOUT_SUSPEND_TRANSITION):
73            raise error.TestFail('Device suspends when docked!')
74        # Verify Chameleon displays main screen
75        self.check_primary_display_on_external_screen()
76        logging.info('DUT IS DOCKED!')
77        return self.chameleon_port.wait_video_input_stable(
78            timeout=self.WAIT_TIME_STABLE_VIDEO_INPUT)
79
80
81    def check_still_suspended(self):
82        """Checks DUT is (still) suspended"""
83        if not self.host.ping_wait_down(timeout=self.TIMEOUT_SUSPEND_CHECK):
84            raise error.TestFail('Device does not stay suspended!')
85        logging.info('DUT STILL SUSPENDED')
86
87
88    def check_external_display(self):
89        """Display status check"""
90        # Check connector
91        if self.screen_test.check_external_display_connected(
92                self.connector_used, self.errors) is None:
93            # Check mode is same as beginning of the test
94            self.check_mode()
95            # Check test image
96            resolution = self.chameleon_port.get_resolution()
97            self.screen_test.test_screen_with_image(
98                    resolution, self.test_mirrored, self.errors)
99
100
101    def run_once(self, host, plug_status, test_mirrored=False):
102
103        # Check for chromebook type devices
104        if not host.get_board_type() == 'CHROMEBOOK':
105            raise error.TestNAError('DUT is not Chromebook. Test Skipped')
106
107        # Check for incompatible with servo chromebooks
108        board_name = host.get_board().split(':')[1]
109        if board_name in self.INCOMPATIBLE_SERVO_BOARDS:
110            raise error.TestNAError(
111                    'DUT is incompatible with servo. Skipping test.')
112
113        self.host = host
114        self.test_mirrored = test_mirrored
115        self.errors = list()
116
117        # Check the servo object
118        if self.host.servo is None:
119            raise error.TestError('Invalid servo object found on the host.')
120
121        factory = remote_facade_factory.RemoteFacadeFactory(host)
122        display_facade = factory.create_display_facade()
123        chameleon_board = host.chameleon
124
125        chameleon_board.setup_and_reset(self.outputdir)
126        finder = chameleon_port_finder.ChameleonVideoInputFinder(
127                chameleon_board, display_facade)
128        for chameleon_port in finder.iterate_all_ports():
129            self.run_test_on_port(chameleon_port, display_facade, plug_status)
130
131
132    def run_test_on_port(self, chameleon_port, display_facade, plug_status):
133        """Run the test on the given Chameleon port.
134
135        @param chameleon_port: a ChameleonPorts object.
136        @param display_facade: a display facade object.
137        @param plug_status: the plugged status before_close, after_close,
138           and before_open
139        """
140        self.chameleon_port = chameleon_port
141        self.display_facade = display_facade
142        self.screen_test = chameleon_screen_test.ChameleonScreenTest(
143                self.host, chameleon_port, display_facade, self.outputdir)
144
145        # Get connector type used (HDMI,DP,...)
146        self.connector_used = self.display_facade.get_external_connector_name()
147        # Set main display mode for the test
148        self.display_facade.set_mirrored(self.test_mirrored)
149
150        for (plugged_before_close,
151             plugged_after_close,
152             plugged_before_open) in plug_status:
153            logging.info('TEST CASE: %s > CLOSE_LID > %s > %s > OPEN_LID',
154                'PLUG' if plugged_before_close else 'UNPLUG',
155                'PLUG' if plugged_after_close else 'UNPLUG',
156                'PLUG' if plugged_before_open else 'UNPLUG')
157
158            is_suspended = False
159            boot_id = self.host.get_boot_id()
160
161            # Plug before close
162            self.chameleon_port.set_plug(plugged_before_close)
163            self.chameleon_port.wait_video_input_stable(
164                    timeout=self.WAIT_TIME_STABLE_VIDEO_INPUT)
165
166            # Close lid and check
167            self.close_lid()
168            if plugged_before_close:
169                self.check_docked()
170            else:
171                self.host.test_wait_for_sleep(self.TIMEOUT_SUSPEND_TRANSITION)
172                is_suspended = True
173
174            # Plug after close and check
175            if plugged_after_close is not plugged_before_close:
176                self.chameleon_port.set_plug(plugged_after_close)
177                self.chameleon_port.wait_video_input_stable(
178                        timeout=self.WAIT_TIME_STABLE_VIDEO_INPUT)
179                if not plugged_before_close:
180                    self.check_still_suspended()
181                else:
182                    self.host.test_wait_for_sleep(
183                        self.TIMEOUT_SUSPEND_TRANSITION)
184                    is_suspended = True
185
186            # Plug before open and check
187            if plugged_before_open is not plugged_after_close:
188                self.chameleon_port.set_plug(plugged_before_open)
189                self.chameleon_port.wait_video_input_stable(
190                        timeout=self.WAIT_TIME_STABLE_VIDEO_INPUT)
191                if not plugged_before_close or not plugged_after_close:
192                    self.check_still_suspended()
193                else:
194                    self.host.test_wait_for_sleep(
195                        self.TIMEOUT_SUSPEND_TRANSITION)
196                    is_suspended = True
197
198            # Open lid and check
199            self.open_lid()
200            if is_suspended:
201                self.host.test_wait_for_resume(boot_id,
202                                               self.TIMEOUT_RESUME_TRANSITION)
203                is_suspended = False
204
205            # Check internal screen switch to primary display
206            self.check_primary_display_on_internal_screen()
207
208            # Plug monitor if not plugged, such that we can test the screen.
209            if not plugged_before_open:
210                self.chameleon_port.set_plug(True)
211                self.chameleon_port.wait_video_input_stable(
212                        timeout=self.WAIT_TIME_STABLE_VIDEO_INPUT)
213
214            # Check status
215            self.check_external_display()
216
217            if self.errors:
218                raise error.TestFail('; '.join(set(self.errors)))
219
220    def cleanup(self):
221        """Test cleanup"""
222        # Keep device in lid open sate.
223        self.open_lid()
224