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 hot-plug and suspend test using the Chameleon board.""" 6 7 import logging 8 import time 9 10 from autotest_lib.client.bin import utils 11 from autotest_lib.client.common_lib import error 12 from autotest_lib.client.cros.chameleon import chameleon_port_finder 13 from autotest_lib.client.cros.chameleon import chameleon_screen_test 14 from autotest_lib.server import test 15 from autotest_lib.server.cros.multimedia import remote_facade_factory 16 17 18 class display_HotPlugAtSuspend(test.test): 19 """Display hot-plug and suspend test. 20 21 This test talks to a Chameleon board and a DUT to set up, run, and verify 22 DUT behavior response to different configuration of hot-plug during 23 suspend/resume. 24 """ 25 version = 1 26 # Duration of suspend, in second. 27 SUSPEND_DURATION = 30 28 # Allowed timeout for the transition of suspend. 29 SUSPEND_TIMEOUT = 20 30 # Allowed timeout for the transition of resume. 31 RESUME_TIMEOUT = 60 32 # Time margin to do plug/unplug before resume. 33 TIME_MARGIN_BEFORE_RESUME = 5 34 # Timeout of waiting DUT mirrored. 35 TIMEOUT_WAITING_MIRRORED = 5 36 37 38 def run_once(self, host, plug_status, test_mirrored=False): 39 if test_mirrored and not host.get_board_type() == 'CHROMEBOOK': 40 raise error.TestNAError('DUT is not Chromebook. Test Skipped') 41 42 factory = remote_facade_factory.RemoteFacadeFactory(host) 43 display_facade = factory.create_display_facade() 44 chameleon_board = host.chameleon 45 46 chameleon_board.setup_and_reset(self.outputdir) 47 finder = chameleon_port_finder.ChameleonVideoInputFinder( 48 chameleon_board, display_facade) 49 50 errors = [] 51 is_display_failure = False 52 for chameleon_port in finder.iterate_all_ports(): 53 screen_test = chameleon_screen_test.ChameleonScreenTest( 54 host, chameleon_port, display_facade, self.outputdir) 55 56 logging.info('See the display on Chameleon: port %d (%s)', 57 chameleon_port.get_connector_id(), 58 chameleon_port.get_connector_type()) 59 60 logging.info('Set mirrored: %s', test_mirrored) 61 display_facade.set_mirrored(test_mirrored) 62 63 # Keep the original connector name, for later comparison. 64 expected_connector = display_facade.get_external_connector_name() 65 resolution = display_facade.get_external_resolution() 66 logging.info('See the display on DUT: %s %r', 67 expected_connector, resolution) 68 69 for (plugged_before_suspend, plugged_after_suspend, 70 plugged_before_resume) in plug_status: 71 test_case = ('TEST CASE: %s > SUSPEND > %s > %s > RESUME' % 72 ('PLUG' if plugged_before_suspend else 'UNPLUG', 73 'PLUG' if plugged_after_suspend else 'UNPLUG', 74 'PLUG' if plugged_before_resume else 'UNPLUG')) 75 logging.info(test_case) 76 boot_id = host.get_boot_id() 77 chameleon_port.set_plug(plugged_before_suspend) 78 79 if screen_test.check_external_display_connected( 80 expected_connector if plugged_before_suspend else False, 81 errors): 82 is_display_failure = True 83 # Skip the following test if an unexpected display detected. 84 continue 85 86 logging.info('GOING TO SUSPEND FOR %d SECONDS...', 87 self.SUSPEND_DURATION) 88 time_before_suspend = time.time() 89 display_facade.suspend_resume_bg(self.SUSPEND_DURATION) 90 91 # Confirm DUT suspended. 92 logging.info('WAITING FOR SUSPEND...') 93 try: 94 host.test_wait_for_sleep(self.SUSPEND_TIMEOUT) 95 except error.TestFail, ex: 96 errors.append("%s - %s" % (test_case, str(ex))) 97 if plugged_after_suspend is not plugged_before_suspend: 98 chameleon_port.set_plug(plugged_after_suspend) 99 100 current_time = time.time() 101 sleep_time = (self.SUSPEND_DURATION - 102 (current_time - time_before_suspend) - 103 self.TIME_MARGIN_BEFORE_RESUME) 104 if sleep_time > 0: 105 logging.info('- Sleep for %.2f seconds...', sleep_time) 106 time.sleep(sleep_time) 107 if plugged_before_resume is not plugged_after_suspend: 108 chameleon_port.set_plug(plugged_before_resume) 109 time.sleep(self.TIME_MARGIN_BEFORE_RESUME) 110 111 logging.info('WAITING FOR RESUME...') 112 try: 113 host.test_wait_for_resume(boot_id, self.RESUME_TIMEOUT) 114 except error.TestFail, ex: 115 errors.append("%s - %s" % (test_case, str(ex))) 116 117 logging.info('Resumed back') 118 119 if screen_test.check_external_display_connected( 120 expected_connector if plugged_before_resume else False, 121 errors): 122 # Skip the following test if an unexpected display detected. 123 continue 124 125 if plugged_before_resume: 126 if test_mirrored and (not utils.wait_for_value( 127 display_facade.is_mirrored_enabled, True, 128 timeout_sec=self.TIMEOUT_WAITING_MIRRORED)): 129 error_message = 'Error: not resumed to mirrored mode' 130 errors.append("%s - %s" % (test_case, error_message)) 131 logging.error(error_message) 132 logging.info('Set mirrored: %s', True) 133 display_facade.set_mirrored(True) 134 elif screen_test.test_screen_with_image( 135 resolution, test_mirrored, errors): 136 is_display_failure = True 137 138 if errors: 139 if is_display_failure: 140 raise error.TestFail('; '.join(set(errors))) 141 else: 142 raise error.TestError('; '.join(set(errors))) 143