| # 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 = 2 |
| # Allowed timeout for the transition of suspend. |
| TIMEOUT_SUSPEND_TRANSITION = 10 |
| # Allowed timeout for the transition of resume. |
| TIMEOUT_RESUME_TRANSITION = 20 |
| # 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 |
| # Plugged status (before_close, after_close, before_open) |
| PLUG_CONFIGS = [(True, True, True), |
| (True, False, False), |
| (True, False, True), |
| (False, True, True), |
| (False, True, False)] |
| |
| def wait_to_suspend(self): |
| """Wait for DUT to suspend. |
| |
| @raise TestFail: If fail to suspend in time. |
| """ |
| if not self.host.ping_wait_down( |
| timeout=self.TIMEOUT_SUSPEND_TRANSITION): |
| raise error.TestFail('Failed to SUSPEND within tieout') |
| logging.debug('DUT is suspended.') |
| |
| |
| def wait_to_resume(self): |
| """Wait for DUT to resume. |
| |
| @raise TestFail: if fail to resume in time. |
| """ |
| if not self.host.wait_up(timeout=self.TIMEOUT_RESUME_TRANSITION): |
| raise error.TestFail( |
| 'Failed to RESUME within timeout') |
| logging.debug('DUT is resumed.') |
| |
| |
| def close_lid(self): |
| """Close lid through servo""" |
| logging.debug('Closing lid') |
| self.host.servo.lid_close() |
| time.sleep(self.WAIT_TIME_LID_TRANSITION) |
| |
| |
| def open_lid(self): |
| """Open the lid through servo""" |
| logging.debug('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): |
| self.errors.append('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): |
| self.errors.append('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: |
| self.errors.append('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.debug('DUT is docked!') |
| return self.chameleon_port.wait_video_input_stable( |
| timeout=self.WAIT_TIME_LID_TRANSITION) |
| |
| |
| 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.debug('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, test_mirrored=False): |
| 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.reset() |
| 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) |
| |
| |
| def run_test_on_port(self, chameleon_port, display_facade): |
| """Run the test on the given Chameleon port. |
| |
| @param chameleon_port: a ChameleonPorts object. |
| @param display_facade: a display facade object. |
| """ |
| self.chameleon_port = chameleon_port |
| self.display_facade = display_facade |
| self.screen_test = chameleon_screen_test.ChameleonScreenTest( |
| 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 self.PLUG_CONFIGS: |
| is_suspended = False |
| |
| # Plug before close |
| self.chameleon_port.set_plug(plugged_before_close) |
| self.chameleon_port.wait_video_input_stable( |
| timeout=self.WAIT_TIME_PLUG_TRANSITION) |
| |
| # Close lid and check |
| self.close_lid() |
| if plugged_before_close: |
| self.check_docked() |
| else: |
| self.wait_to_suspend() |
| 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_PLUG_TRANSITION) |
| if not plugged_before_close: |
| self.check_still_suspended() |
| else: |
| self.wait_to_suspend() |
| 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_PLUG_TRANSITION) |
| if not plugged_before_close or not plugged_after_close: |
| self.check_still_suspended() |
| else: |
| self.wait_to_suspend() |
| is_suspended = True |
| |
| # Open lid and check |
| self.open_lid() |
| if is_suspended: |
| self.wait_to_resume() |
| 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_PLUG_TRANSITION) |
| |
| # Check status |
| self.check_external_display() |
| |
| if self.errors: |
| raise error.TestFail('; '.join(set(self.errors))) |