blob: ff8a7e0a48074f2d5b1e1428f96db3e9f5f79318 [file] [log] [blame]
Kuo Jen Wei7f00bb32018-11-01 15:35:24 +08001# Copyright 2018 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 contextlib
6import json
7import logging
8from lxml import etree
9import os
10import StringIO
11
12from autotest_lib.client.common_lib import utils
Kuo Jen Wei377e99b2020-02-25 16:39:42 +080013from autotest_lib.server.cros.tradefed import tradefed_chromelogin as login
Kuo Jen Wei7f00bb32018-11-01 15:35:24 +080014
15
16class ChartFixture:
17 """Sets up chart tablet to display dummy scene image."""
18 DISPLAY_SCRIPT = '/usr/local/autotest/bin/display_chart.py'
19
20 def __init__(self, chart_host, scene_uri):
21 self.host = chart_host
22 self.scene_uri = scene_uri
23 self.display_pid = None
24
25 def initialize(self):
26 """Prepare scene file and display it on chart host."""
27 logging.info('Prepare scene file')
28 chart_dir = self.host.get_tmp_dir()
29 scene_path = os.path.join(
30 chart_dir, self.scene_uri[self.scene_uri.rfind('/') + 1:])
31 self.host.run('wget', args=('-O', scene_path, self.scene_uri))
32 self.host.run('chmod', args=('-R', '755', chart_dir))
33
34 logging.info('Display scene file')
35 self.display_pid = self.host.run_background(
Kuo Jen Wei377e99b2020-02-25 16:39:42 +080036 'python2 %s %s' % (self.DISPLAY_SCRIPT, scene_path))
Kuo Jen Wei7f00bb32018-11-01 15:35:24 +080037 # TODO(inker): Suppose chart should be displayed very soon. Or require
38 # of waiting until chart actually displayed.
39
40 def cleanup(self):
41 """Cleanup display script."""
42 if self.display_pid is not None:
43 self.host.run('kill', args=('-2', str(self.display_pid)))
44
45
46def get_chart_address(host_address, args):
Kuo Jen Wei3e89c442019-01-29 14:27:26 +080047 """Get address of chart tablet from commandline args or mapping logic in
48 test lab.
49
50 @param host_address: a list of hostname strings.
51 @param args: a dict parse from commandline args.
52 @return:
53 A list of strings for chart tablet addresses.
54 """
Kuo Jen Wei7f00bb32018-11-01 15:35:24 +080055 address = utils.args_to_dict(args).get('chart')
56 if address is not None:
57 return address.split(',')
58 elif utils.is_in_container():
Kuo Jen Wei377e99b2020-02-25 16:39:42 +080059 return [utils.get_lab_chart_address(host) for host in host_address]
Kuo Jen Wei7f00bb32018-11-01 15:35:24 +080060 else:
61 return None
62
63
64class DUTFixture:
65 """Sets up camera filter for target camera facing on DUT."""
66 TEST_CONFIG_PATH = '/var/cache/camera/test_config.json'
Kuo Jen Wei7f00bb32018-11-01 15:35:24 +080067 CAMERA_PROFILE_PATH = ('/mnt/stateful_partition/encrypted/var/cache/camera'
68 '/media_profiles.xml')
69
70 def __init__(self, test, host, facing):
71 self.test = test
72 self.host = host
73 self.facing = facing
74
75 @contextlib.contextmanager
76 def _set_selinux_permissive(self):
77 selinux_mode = self.host.run_output('getenforce')
78 self.host.run('setenforce 0')
79 yield
80 self.host.run('setenforce', args=(selinux_mode, ))
81
82 def _filter_camera_profile(self, content, facing):
83 """Filter camera profile of target facing from content of camera
84 profile.
85
86 @return:
87 New camera profile with only target facing, camera ids are
88 renumbered from 0.
89 """
90 tree = etree.parse(
91 StringIO.StringIO(content),
92 parser=etree.XMLParser(compact=False))
93 root = tree.getroot()
94 profiles = root.findall('CamcorderProfiles')
95 logging.debug('%d number of camera(s) found in camera profile',
96 len(profiles))
97 assert 1 <= len(profiles) <= 2
98 if len(profiles) == 2:
99 cam_id = 0 if facing == 'back' else 1
100 for p in profiles:
101 if cam_id == int(p.attrib['cameraId']):
102 p.attrib['cameraId'] = '0'
103 else:
104 root.remove(p)
105 else:
Kuo Jen Wei377e99b2020-02-25 16:39:42 +0800106 with login.login_chrome(
107 hosts=[self.host],
Kuo Jen Wei7f00bb32018-11-01 15:35:24 +0800108 board=self.test._get_board_name(),
Kuo Jen Wei377e99b2020-02-25 16:39:42 +0800109 ), self._set_selinux_permissive():
Kuo Jen Wei7f00bb32018-11-01 15:35:24 +0800110 has_front_camera = (
111 'feature:android.hardware.camera.front' in self.host.
112 run_output('android-sh -c "pm list features"'))
113 logging.debug('has_front_camera=%s', has_front_camera)
114 if (facing == 'front') != has_front_camera:
115 root.remove(profiles[0])
116 return etree.tostring(
117 tree, xml_declaration=True, encoding=tree.docinfo.encoding)
118
119 def _read_file(self, filepath):
120 """Read content of filepath from host."""
121 tmp_path = os.path.join(self.test.tmpdir, os.path.basename(filepath))
122 self.host.get_file(filepath, tmp_path, delete_dest=True)
123 with open(tmp_path) as f:
124 return f.read()
125
126 def _write_file(self, filepath, content, permission=None, owner=None):
127 """Write content to filepath on remote host.
128 @param permission: set permission to 0xxx octal number of remote file.
129 @param owner: set owner of remote file.
130 """
131 tmp_path = os.path.join(self.test.tmpdir, os.path.basename(filepath))
132 with open(tmp_path, 'w') as f:
133 f.write(content)
134 if permission is not None:
135 os.chmod(tmp_path, permission)
136 self.host.send_file(tmp_path, filepath, delete_dest=True)
137 if owner is not None:
138 self.host.run('chown', args=(owner, filepath))
139
140 def initialize(self):
141 """Filter out camera other than target facing on DUT."""
142 logging.info('Restart camera service with filter option')
143 self._write_file(
144 self.TEST_CONFIG_PATH,
145 json.dumps({
146 'enable_back_camera': self.facing == 'back',
147 'enable_front_camera': self.facing == 'front',
148 'enable_external_camera': False
149 }),
150 owner='arc-camera')
151 self.host.run('restart cros-camera')
152
Kuo Jen Wei7f00bb32018-11-01 15:35:24 +0800153 logging.info('Replace camera profile in ARC++ container')
Kuo Jen Wei7f00bb32018-11-01 15:35:24 +0800154 profile = self._read_file(self.CAMERA_PROFILE_PATH)
155 new_profile = self._filter_camera_profile(profile, self.facing)
156 self._write_file(self.CAMERA_PROFILE_PATH, new_profile)
157 self.host.run('restart ui')
158
159 def cleanup(self):
160 """Cleanup camera filter."""
161 logging.info('Remove filter option and restore camera service')
162 self.host.run('rm', args=('-f', self.TEST_CONFIG_PATH))
163 self.host.run('restart cros-camera')
164
Kuo Jen Wei7f00bb32018-11-01 15:35:24 +0800165 logging.info('Restore camera profile in ARC++ container')
Kuo Jen Wei7f00bb32018-11-01 15:35:24 +0800166 self.host.run('restart ui')