blob: c953d0b6e344a2f735b46f7da53fbcdf3fdd0c9e [file] [log] [blame]
# 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.
"""An adapter to access the local display facade."""
import logging
import tempfile
from PIL import Image
from autotest_lib.client.common_lib import error
from autotest_lib.client.cros import sys_power
from autotest_lib.client.cros.multimedia import display_facade_native
from autotest_lib.client.cros.multimedia import facade_resource
from autotest_lib.client.cros.multimedia.display_info import DisplayInfo
class DisplayFacadeLocalAdapter(object):
"""DisplayFacadeLocalAdapter is an adapter to control the local display.
Methods with non-native-type arguments go to this class and do some
conversion; otherwise, go to the DisplayFacadeNative class.
"""
def __init__(self, chrome):
"""Construct a DisplayFacadeLocalAdapter.
@param chrome: A Chrome object.
"""
# Create a DisplayFacadeNative object as a component such that this
# class can expose and manipulate its interfaces.
self._display_component = display_facade_native.DisplayFacadeNative(
facade_resource.FacadeResource(chrome_object=chrome))
def get_external_connector_name(self):
"""Gets the name of the external output connector.
@return The external output connector name as a string; False if nothing
is connected.
"""
return self._display_component.get_external_connector_name()
def get_internal_connector_name(self):
"""Gets the name of the internal output connector.
@return The internal output connector name as a string; False if nothing
is connected.
"""
return self._display_component.get_internal_connector_name()
def move_to_display(self, display_index):
"""Moves the current window to the indicated display.
@param display_index: The index of the indicated display.
"""
self._display_component.move_to_display(display_index)
def set_fullscreen(self, is_fullscreen):
"""Sets the current window to full screen.
@param is_fullscreen: True or False to indicate fullscreen state.
@return True if success, False otherwise.
"""
return self._display_component.set_fullscreen(is_fullscreen)
def load_url(self, url):
"""Loads the given url in a new tab. The new tab will be active.
@param url: The url to load as a string.
@return a str, the tab descriptor of the opened tab.
"""
return self._display_component.load_url(url)
def load_calibration_image(self, resolution):
"""Load a full screen calibration image from the HTTP server.
@param resolution: A tuple (width, height) of resolution.
@return a str, the tab descriptor of the opened tab.
"""
return self._display_component.load_calibration_image(resolution)
def load_color_sequence(self, tab_descriptor, color_sequence):
"""Displays a series of colors on full screen on the tab.
tab_descriptor is returned by any open tab API of display facade.
e.g.,
tab_descriptor = load_url('about:blank')
load_color_sequence(tab_descriptor, color)
@param tab_descriptor: Indicate which tab to test.
@param color_sequence: An integer list for switching colors.
@return A list of the timestamp for each switch.
"""
return self._display_component.load_color_sequence(tab_descriptor,
color_sequence)
def close_tab(self, tab_descriptor):
"""Disables fullscreen and closes the tab of the given tab descriptor.
tab_descriptor is returned by any open tab API of display facade.
e.g.,
1.
tab_descriptor = load_url(url)
close_tab(tab_descriptor)
2.
tab_descriptor = load_calibration_image(resolution)
close_tab(tab_descriptor)
@param tab_descriptor: Indicate which tab to close.
"""
self._display_component.close_tab(tab_descriptor)
def is_mirrored_enabled(self):
"""Checks the mirrored state.
@return True if mirrored mode is enabled.
"""
return self._display_component.is_mirrored_enabled()
def set_mirrored(self, is_mirrored):
"""Sets mirrored mode.
@param is_mirrored: True or False to indicate mirrored state.
@throws error.TestError when the call fails.
"""
if not self._display_component.set_mirrored(is_mirrored):
raise error.TestError('Failed to set_mirrored(%s)' % is_mirrored)
def is_display_primary(self, internal=True):
"""Checks if internal screen is primary display.
@param internal: is internal/external screen primary status requested
@return boolean True if internal display is primary.
"""
return self._display_component.is_display_primary(internal)
def suspend_resume(self, suspend_time=10):
"""Suspends the DUT for a given time in second.
@param suspend_time: Suspend time in second.
"""
try:
self._display_component.suspend_resume(suspend_time)
except sys_power.SpuriousWakeupError as e:
# Log suspend/resume errors but continue the test.
logging.error('suspend_resume error: %s', str(e))
def suspend_resume_bg(self, suspend_time=10):
"""Suspends the DUT for a given time in second in the background.
@param suspend_time: Suspend time in second, default: 10s.
"""
self._display_component.suspend_resume_bg(suspend_time)
def wait_external_display_connected(self, display):
"""Waits for the specified display to be connected.
@param display: The display name as a string, like 'HDMI1', or
False if no external display is expected.
@return: True if display is connected; False otherwise.
"""
return self._display_component.wait_external_display_connected(display)
def hide_cursor(self):
"""Hides mouse cursor by sending a keystroke."""
self._display_component.hide_cursor()
def hide_typing_cursor(self):
"""Hides typing cursor by moving outside typing bar."""
self._display_component.hide_typing_cursor()
def set_content_protection(self, state):
"""Sets the content protection of the external screen.
@param state: One of the states 'Undesired', 'Desired', or 'Enabled'
"""
self._display_component.set_content_protection(state)
def get_content_protection(self):
"""Gets the state of the content protection.
@param output: The output name as a string.
@return: A string of the state, like 'Undesired', 'Desired', or 'Enabled'.
False if not supported.
"""
return self._display_component.get_content_protection()
def _take_screenshot(self, screenshot_func):
"""Gets screenshot from frame buffer.
@param screenshot_func: function to take a screenshot and save the image
to specified path. Usage: screenshot_func(path).
@return: An Image object.
Notice that the returned image may not be in RGB format,
depending on PIL implementation.
"""
with tempfile.NamedTemporaryFile(suffix='.png') as f:
screenshot_func(f.name)
return Image.open(f.name)
def capture_internal_screen(self):
"""Captures the internal screen framebuffer.
@return: An Image object.
"""
screenshot_func = self._display_component.take_internal_screenshot
return self._take_screenshot(screenshot_func)
# TODO(ihf): This function needs to be fixed for multiple screens.
def capture_external_screen(self):
"""Captures the external screen framebuffer.
@return: An Image object.
"""
screenshot_func = self._display_component.take_external_screenshot
return self._take_screenshot(screenshot_func)
def get_external_resolution(self):
"""Gets the resolution of the external screen.
@return The resolution tuple (width, height) or None if no external
display is connected.
"""
resolution = self._display_component.get_external_resolution()
return tuple(resolution) if resolution else None
def get_internal_resolution(self):
"""Gets the resolution of the internal screen.
@return The resolution tuple (width, height)
"""
return tuple(self._display_component.get_internal_resolution())
def set_resolution(self, display_index, width, height):
"""Sets the resolution on the specified display.
@param display_index: index of the display to set resolutions for.
@param width: width of the resolution
@param height: height of the resolution
"""
self._display_component.set_resolution(display_index, width, height)
def get_display_info(self):
"""Gets the information of all the displays that are connected to the
DUT.
@return: list of object DisplayInfo for display informtion
"""
return map(DisplayInfo, self._display_component.get_display_info())
def get_display_modes(self, display_index):
"""Gets the display modes of the specified display.
@param display_index: index of the display to get modes from; the index
is from the DisplayInfo list obtained by get_display_info().
@return: list of DisplayMode dicts.
"""
return self._display_component.get_display_modes(display_index)
def get_available_resolutions(self, display_index):
"""Gets the resolutions from the specified display.
@return a list of (width, height) tuples.
"""
return [tuple(r) for r in
self._display_component.get_available_resolutions(
display_index)]
def get_first_external_display_index(self):
"""Gets the first external display index.
@return the index of the first external display; False if not found.
"""
return self._display_component.get_first_external_display_index()
def reset_connector_if_applicable(self, connector_type):
"""Resets video connector from host end if applicable.
This is the workaround method for remote display facade adapter only.
Put an empty method here in local adapter to prevent AttributeError of
client test.
@param connector_type: A string, like "VGA", "DVI", "HDMI", or "DP".
"""
pass