blob: 282a616140f9f5a51bcd3feacb8ee8869a75f093 [file] [log] [blame]
Tom Wai-Hong Tamb2d39dc2014-01-21 15:26:23 +08001# Copyright (c) 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
5import os
Tom Wai-Hong Tamc3846422014-02-17 16:41:57 +08006import sys
Tom Wai-Hong Tamb2d39dc2014-01-21 15:26:23 +08007
8from autotest_lib.client.bin import utils
Wai-Hong Tam44cb5452014-03-18 16:14:24 -07009from autotest_lib.client.cros import constants
Tom Wai-Hong Tamb2d39dc2014-01-21 15:26:23 +080010from autotest_lib.server import autotest
11
Tom Wai-Hong Tamb2d39dc2014-01-21 15:26:23 +080012class DisplayClient(object):
13 """DisplayClient is a layer to control display logic over a remote DUT.
14
15 The Autotest host object representing the remote DUT, passed to this
16 class on initialization, can be accessed from its _client property.
17
18 """
19
Tom Wai-Hong Tamb2d39dc2014-01-21 15:26:23 +080020 X_ENV_VARIABLES = 'DISPLAY=:0.0 XAUTHORITY=/home/chronos/.Xauthority'
21 XMLRPC_CONNECT_TIMEOUT = 30
22
23
24 def __init__(self, host):
25 """Construct a DisplayClient.
26
27 @param host: Host object representing a remote host.
28 """
29 self._client = host
30 self._display_xmlrpc_client = None
Wai-Hong Tam44cb5452014-03-18 16:14:24 -070031 module_dir = os.path.dirname(sys.modules[__name__].__file__)
32 self._source_images_dir = os.path.join(module_dir, 'calibration_images')
33 self._dest_tmp_dir = '/tmp'
Tom Wai-Hong Tamb2d39dc2014-01-21 15:26:23 +080034
35
Wai-Hong Tam44cb5452014-03-18 16:14:24 -070036 def initialize(self):
Tom Wai-Hong Tamb2d39dc2014-01-21 15:26:23 +080037 """Initializes some required servers, like HTTP daemon, RPC connection.
Tom Wai-Hong Tamb2d39dc2014-01-21 15:26:23 +080038 """
39 # Make sure the client library is on the device so that the proxy code
40 # is there when we try to call it.
41 client_at = autotest.Autotest(self._client)
42 client_at.install()
Tom Wai-Hong Tamfe395092014-02-12 20:16:22 +080043 self.connect()
Tom Wai-Hong Tamb2d39dc2014-01-21 15:26:23 +080044
Tom Wai-Hong Tamb2d39dc2014-01-21 15:26:23 +080045
Tom Wai-Hong Tamfe395092014-02-12 20:16:22 +080046 def connect(self):
47 """Connects the XML-RPC proxy on the client."""
48 self._display_xmlrpc_client = self._client.xmlrpc_connect(
49 constants.DISPLAY_TESTING_XMLRPC_SERVER_COMMAND,
50 constants.DISPLAY_TESTING_XMLRPC_SERVER_PORT,
51 command_name=(
52 constants.DISPLAY_TESTING_XMLRPC_SERVER_CLEANUP_PATTERN
53 ),
54 ready_test_name=(
55 constants.DISPLAY_TESTING_XMLRPC_SERVER_READY_METHOD),
56 timeout_seconds=self.XMLRPC_CONNECT_TIMEOUT)
57
58
Tom Wai-Hong Tamb2d39dc2014-01-21 15:26:23 +080059 def cleanup(self):
60 """Cleans up."""
Tom Wai-Hong Tamb2d39dc2014-01-21 15:26:23 +080061 self._client.rpc_disconnect_all()
62
63
64 def __del__(self):
65 """Destructor of DisplayClient."""
66 self.cleanup()
67
68
69 def get_connector_name(self):
70 """Gets the name of the external output connector.
71
72 @return The external output connector name as a string.
73 """
74 return self._display_xmlrpc_client.get_ext_connector_name()
75
76
77 def load_calibration_image(self, resolution):
78 """Load a full screen calibration image from the HTTP server.
79
80 @param resolution: A tuple (width, height) of resolution.
81 """
Wai-Hong Tam44cb5452014-03-18 16:14:24 -070082 filename = '%dx%d.png' % resolution
83 image_path = os.path.join(self._source_images_dir, filename)
84 self._client.send_file(image_path, self._dest_tmp_dir)
85 page_url = ('file://%s/%s' % (self._dest_tmp_dir, filename))
Tom Wai-Hong Tamb2d39dc2014-01-21 15:26:23 +080086 self._display_xmlrpc_client.load_url(page_url)
87
88
89 def close_tab(self, index=-1):
90 """Closes the tab of the given index.
91
92 @param index: The tab index to close. Defaults to the last tab.
93 """
94 return self._display_xmlrpc_client.close_tab(index)
95
96
97 def set_mirrored(self, is_mirrored):
98 """Sets mirrored mode.
99
100 @param is_mirrored: True or False to indicate mirrored state.
101 """
102 return self._display_xmlrpc_client.set_mirrored(is_mirrored)
103
104
Tom Wai-Hong Tam328dbeb2014-02-14 11:20:19 +0800105 def suspend_resume(self, suspend_time=10):
106 """Suspends the DUT for a given time in second.
107
108 @param suspend_time: Suspend time in second, default: 10s.
109 """
Tom Wai-Hong Tamb2d39dc2014-01-21 15:26:23 +0800110 # TODO(waihong): Use other general API instead of this RPC.
Tom Wai-Hong Tam328dbeb2014-02-14 11:20:19 +0800111 return self._display_xmlrpc_client.suspend_resume(suspend_time)
112
113
114 def suspend_resume_bg(self, suspend_time=10):
115 """Suspends the DUT for a given time in second in the background.
116
117 @param suspend_time: Suspend time in second, default: 10s.
118 """
119 # TODO(waihong): Use other general API instead of this RPC.
120 return self._display_xmlrpc_client.suspend_resume_bg(suspend_time)
Tom Wai-Hong Tamb2d39dc2014-01-21 15:26:23 +0800121
122
123 def reconnect_output_and_wait(self):
124 """Reconnects output and waits it available."""
125 output = self.get_connector_name()
126 self._display_xmlrpc_client.reconnect_output(output)
127 self._display_xmlrpc_client.wait_output_connected(output)
128 utils.wait_for_value(lambda: (
129 len(self._display_xmlrpc_client.get_display_info())),
130 expected_value=2)
131
132
Hung-ying Tyan67541652014-03-12 11:44:46 +0800133 def hide_cursor(self):
134 """Hides mouse cursor by sending a keystroke."""
135 self._client.run('%s xdotool key Up' % self.X_ENV_VARIABLES)
Tom Wai-Hong Tamb2d39dc2014-01-21 15:26:23 +0800136
137
138 def capture_external_screen(self, file_path):
139 """Captures the external screen framebuffer.
140
141 @param file_path: The path of file for output.
142
143 @return: The byte-array for the screen.
144 """
145 output = self.get_connector_name()
146 fb_w, fb_h, fb_x, fb_y = (
147 self._display_xmlrpc_client.get_resolution(output))
148 basename = os.path.basename(file_path)
149 remote_path = os.path.join('/tmp', basename)
150 command = ('%s import -window root -depth 8 -crop %dx%d+%d+%d %s' %
151 (self.X_ENV_VARIABLES, fb_w, fb_h, fb_x, fb_y, remote_path))
152 self._client.run(command)
153 self._client.get_file(remote_path, file_path)
154 return open(file_path).read()