blob: 73c8934f8d6a7bbb57ad1144bf89e3b1a9b70e99 [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
Tom Wai-Hong Tam23362632014-04-09 16:38:37 +080022 HTTP_PORT = 8000
Tom Wai-Hong Tamb2d39dc2014-01-21 15:26:23 +080023
24
25 def __init__(self, host):
26 """Construct a DisplayClient.
27
28 @param host: Host object representing a remote host.
29 """
30 self._client = host
31 self._display_xmlrpc_client = None
Wai-Hong Tam44cb5452014-03-18 16:14:24 -070032 module_dir = os.path.dirname(sys.modules[__name__].__file__)
33 self._source_images_dir = os.path.join(module_dir, 'calibration_images')
34 self._dest_tmp_dir = '/tmp'
Tom Wai-Hong Tamb2d39dc2014-01-21 15:26:23 +080035
36
Wai-Hong Tam44cb5452014-03-18 16:14:24 -070037 def initialize(self):
Tom Wai-Hong Tamb2d39dc2014-01-21 15:26:23 +080038 """Initializes some required servers, like HTTP daemon, RPC connection.
Tom Wai-Hong Tamb2d39dc2014-01-21 15:26:23 +080039 """
40 # Make sure the client library is on the device so that the proxy code
41 # is there when we try to call it.
42 client_at = autotest.Autotest(self._client)
43 client_at.install()
Tom Wai-Hong Tamfe395092014-02-12 20:16:22 +080044 self.connect()
Tom Wai-Hong Tamb2d39dc2014-01-21 15:26:23 +080045
Tom Wai-Hong Tamb2d39dc2014-01-21 15:26:23 +080046
Tom Wai-Hong Tamfe395092014-02-12 20:16:22 +080047 def connect(self):
48 """Connects the XML-RPC proxy on the client."""
49 self._display_xmlrpc_client = self._client.xmlrpc_connect(
50 constants.DISPLAY_TESTING_XMLRPC_SERVER_COMMAND,
51 constants.DISPLAY_TESTING_XMLRPC_SERVER_PORT,
52 command_name=(
53 constants.DISPLAY_TESTING_XMLRPC_SERVER_CLEANUP_PATTERN
54 ),
55 ready_test_name=(
56 constants.DISPLAY_TESTING_XMLRPC_SERVER_READY_METHOD),
57 timeout_seconds=self.XMLRPC_CONNECT_TIMEOUT)
58
59
Tom Wai-Hong Tamb2d39dc2014-01-21 15:26:23 +080060 def cleanup(self):
61 """Cleans up."""
Tom Wai-Hong Tamb2d39dc2014-01-21 15:26:23 +080062 self._client.rpc_disconnect_all()
63
64
65 def __del__(self):
66 """Destructor of DisplayClient."""
67 self.cleanup()
68
69
70 def get_connector_name(self):
71 """Gets the name of the external output connector.
72
73 @return The external output connector name as a string.
74 """
75 return self._display_xmlrpc_client.get_ext_connector_name()
76
77
78 def load_calibration_image(self, resolution):
79 """Load a full screen calibration image from the HTTP server.
80
81 @param resolution: A tuple (width, height) of resolution.
82 """
Wai-Hong Tam44cb5452014-03-18 16:14:24 -070083 filename = '%dx%d.png' % resolution
84 image_path = os.path.join(self._source_images_dir, filename)
85 self._client.send_file(image_path, self._dest_tmp_dir)
Tom Wai-Hong Tam23362632014-04-09 16:38:37 +080086 page_url = ('http://localhost:%d/%s' % (self.HTTP_PORT, filename))
87 self._display_xmlrpc_client.start_httpd(self.HTTP_PORT,
88 self._dest_tmp_dir)
Tom Wai-Hong Tamb2d39dc2014-01-21 15:26:23 +080089 self._display_xmlrpc_client.load_url(page_url)
Tom Wai-Hong Tam23362632014-04-09 16:38:37 +080090 self._display_xmlrpc_client.stop_httpd()
Tom Wai-Hong Tamb2d39dc2014-01-21 15:26:23 +080091
92
93 def close_tab(self, index=-1):
94 """Closes the tab of the given index.
95
96 @param index: The tab index to close. Defaults to the last tab.
97 """
98 return self._display_xmlrpc_client.close_tab(index)
99
100
101 def set_mirrored(self, is_mirrored):
102 """Sets mirrored mode.
103
104 @param is_mirrored: True or False to indicate mirrored state.
105 """
106 return self._display_xmlrpc_client.set_mirrored(is_mirrored)
107
108
Tom Wai-Hong Tam328dbeb2014-02-14 11:20:19 +0800109 def suspend_resume(self, suspend_time=10):
110 """Suspends the DUT for a given time in second.
111
112 @param suspend_time: Suspend time in second, default: 10s.
113 """
Tom Wai-Hong Tamb2d39dc2014-01-21 15:26:23 +0800114 # TODO(waihong): Use other general API instead of this RPC.
Tom Wai-Hong Tam328dbeb2014-02-14 11:20:19 +0800115 return self._display_xmlrpc_client.suspend_resume(suspend_time)
116
117
118 def suspend_resume_bg(self, suspend_time=10):
119 """Suspends the DUT for a given time in second in the background.
120
121 @param suspend_time: Suspend time in second, default: 10s.
122 """
123 # TODO(waihong): Use other general API instead of this RPC.
124 return self._display_xmlrpc_client.suspend_resume_bg(suspend_time)
Tom Wai-Hong Tamb2d39dc2014-01-21 15:26:23 +0800125
126
127 def reconnect_output_and_wait(self):
128 """Reconnects output and waits it available."""
129 output = self.get_connector_name()
130 self._display_xmlrpc_client.reconnect_output(output)
131 self._display_xmlrpc_client.wait_output_connected(output)
132 utils.wait_for_value(lambda: (
133 len(self._display_xmlrpc_client.get_display_info())),
134 expected_value=2)
135
136
Hung-ying Tyan67541652014-03-12 11:44:46 +0800137 def hide_cursor(self):
138 """Hides mouse cursor by sending a keystroke."""
139 self._client.run('%s xdotool key Up' % self.X_ENV_VARIABLES)
Tom Wai-Hong Tamb2d39dc2014-01-21 15:26:23 +0800140
141
142 def capture_external_screen(self, file_path):
143 """Captures the external screen framebuffer.
144
145 @param file_path: The path of file for output.
146
147 @return: The byte-array for the screen.
148 """
149 output = self.get_connector_name()
150 fb_w, fb_h, fb_x, fb_y = (
151 self._display_xmlrpc_client.get_resolution(output))
152 basename = os.path.basename(file_path)
153 remote_path = os.path.join('/tmp', basename)
154 command = ('%s import -window root -depth 8 -crop %dx%d+%d+%d %s' %
155 (self.X_ENV_VARIABLES, fb_w, fb_h, fb_x, fb_y, remote_path))
156 self._client.run(command)
157 self._client.get_file(remote_path, file_path)
158 return open(file_path).read()