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