# Copyright 2014 The Chromium OS Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. """This is a display lid close and open test using the Chameleon board.""" import logging, time from autotest_lib.client.common_lib import error from autotest_lib.client.cros.chameleon import chameleon_port_finder from autotest_lib.client.cros.chameleon import chameleon_screen_test from autotest_lib.server import test from autotest_lib.server.cros.multimedia import remote_facade_factory class display_LidCloseOpen(test.test): """External Display Lid Close/Open test. """ version = 1 # Time to check if device is suspended TIMEOUT_SUSPEND_CHECK = 5 # Allowed timeout for the transition of suspend. TIMEOUT_SUSPEND_TRANSITION = 30 # Allowed timeout for the transition of resume. TIMEOUT_RESUME_TRANSITION = 60 # Time to allow for table video input WAIT_TIME_STABLE_VIDEO_INPUT = 10 # Time to allow lid transition to take effect WAIT_TIME_LID_TRANSITION = 5 # Time to allow display port plug transition to take effect WAIT_TIME_PLUG_TRANSITION = 5 # Some boards do not play well with servo - crosbug.com/p/27591 INCOMPATIBLE_SERVO_BOARDS = ['daisy', 'falco', 'auron_paine'] def close_lid(self): """Close lid through servo""" logging.info('CLOSING LID...') self.host.servo.lid_close() time.sleep(self.WAIT_TIME_LID_TRANSITION) def open_lid(self): """Open lid through servo""" logging.info('OPENING LID...') self.host.servo.lid_open() time.sleep(self.WAIT_TIME_LID_TRANSITION) def check_primary_display_on_internal_screen(self): """Checks primary display is on onboard/internal screen""" if not self.display_facade.is_display_primary(internal=True): raise error.TestFail('Primary display is not on internal screen') def check_primary_display_on_external_screen(self): """Checks primary display is on external screen""" if not self.display_facade.is_display_primary(internal=False): raise error.TestFail('Primary display is not on external screen') def check_mode(self): """Checks the display mode is as expected""" if self.display_facade.is_mirrored_enabled() is not self.test_mirrored: raise error.TestFail('Display mode %s is not preserved!' % ('mirrored' if self.test_mirrored else 'extended')) def check_docked(self): """Checks DUT is docked""" # Device does not suspend if self.host.ping_wait_down(timeout=self.TIMEOUT_SUSPEND_TRANSITION): raise error.TestFail('Device suspends when docked!') # Verify Chameleon displays main screen self.check_primary_display_on_external_screen() logging.info('DUT IS DOCKED!') return self.chameleon_port.wait_video_input_stable( timeout=self.WAIT_TIME_STABLE_VIDEO_INPUT) def check_still_suspended(self): """Checks DUT is (still) suspended""" if not self.host.ping_wait_down(timeout=self.TIMEOUT_SUSPEND_CHECK): raise error.TestFail('Device does not stay suspended!') logging.info('DUT STILL SUSPENDED') def check_external_display(self): """Display status check""" # Check connector if self.screen_test.check_external_display_connected( self.connector_used, self.errors) is None: # Check mode is same as beginning of the test self.check_mode() # Check test image resolution = self.chameleon_port.get_resolution() self.screen_test.test_screen_with_image( resolution, self.test_mirrored, self.errors) def run_once(self, host, plug_status, test_mirrored=False): # Check for chromebook type devices if not host.get_board_type() == 'CHROMEBOOK': raise error.TestNAError('DUT is not Chromebook. Test Skipped') # Check for incompatible with servo chromebooks board_name = host.get_board().split(':')[1] if board_name in self.INCOMPATIBLE_SERVO_BOARDS: raise error.TestNAError( 'DUT is incompatible with servo. Skipping test.') self.host = host self.test_mirrored = test_mirrored self.errors = list() # Check the servo object if self.host.servo is None: raise error.TestError('Invalid servo object found on the host.') factory = remote_facade_factory.RemoteFacadeFactory(host) display_facade = factory.create_display_facade() chameleon_board = host.chameleon chameleon_board.setup_and_reset(self.outputdir) finder = chameleon_port_finder.ChameleonVideoInputFinder( chameleon_board, display_facade) for chameleon_port in finder.iterate_all_ports(): self.run_test_on_port(chameleon_port, display_facade, plug_status) def run_test_on_port(self, chameleon_port, display_facade, plug_status): """Run the test on the given Chameleon port. @param chameleon_port: a ChameleonPorts object. @param display_facade: a display facade object. @param plug_status: the plugged status before_close, after_close, and before_open """ self.chameleon_port = chameleon_port self.display_facade = display_facade self.screen_test = chameleon_screen_test.ChameleonScreenTest( self.host, chameleon_port, display_facade, self.outputdir) # Get connector type used (HDMI,DP,...) self.connector_used = self.display_facade.get_external_connector_name() # Set main display mode for the test self.display_facade.set_mirrored(self.test_mirrored) for (plugged_before_close, plugged_after_close, plugged_before_open) in plug_status: logging.info('TEST CASE: %s > CLOSE_LID > %s > %s > OPEN_LID', 'PLUG' if plugged_before_close else 'UNPLUG', 'PLUG' if plugged_after_close else 'UNPLUG', 'PLUG' if plugged_before_open else 'UNPLUG') is_suspended = False boot_id = self.host.get_boot_id() # Plug before close self.chameleon_port.set_plug(plugged_before_close) self.chameleon_port.wait_video_input_stable( timeout=self.WAIT_TIME_STABLE_VIDEO_INPUT) # Close lid and check self.close_lid() if plugged_before_close: self.check_docked() else: self.host.test_wait_for_sleep(self.TIMEOUT_SUSPEND_TRANSITION) is_suspended = True # Plug after close and check if plugged_after_close is not plugged_before_close: self.chameleon_port.set_plug(plugged_after_close) self.chameleon_port.wait_video_input_stable( timeout=self.WAIT_TIME_STABLE_VIDEO_INPUT) if not plugged_before_close: self.check_still_suspended() else: self.host.test_wait_for_sleep( self.TIMEOUT_SUSPEND_TRANSITION) is_suspended = True # Plug before open and check if plugged_before_open is not plugged_after_close: self.chameleon_port.set_plug(plugged_before_open) self.chameleon_port.wait_video_input_stable( timeout=self.WAIT_TIME_STABLE_VIDEO_INPUT) if not plugged_before_close or not plugged_after_close: self.check_still_suspended() else: self.host.test_wait_for_sleep( self.TIMEOUT_SUSPEND_TRANSITION) is_suspended = True # Open lid and check self.open_lid() if is_suspended: self.host.test_wait_for_resume(boot_id, self.TIMEOUT_RESUME_TRANSITION) is_suspended = False # Check internal screen switch to primary display self.check_primary_display_on_internal_screen() # Plug monitor if not plugged, such that we can test the screen. if not plugged_before_open: self.chameleon_port.set_plug(True) self.chameleon_port.wait_video_input_stable( timeout=self.WAIT_TIME_STABLE_VIDEO_INPUT) # Check status self.check_external_display() if self.errors: raise error.TestFail('; '.join(set(self.errors))) def cleanup(self): """Test cleanup""" # Keep device in lid open sate. self.open_lid()