Derek Beckett | 5fb683c | 2020-08-19 15:24:13 -0700 | [diff] [blame] | 1 | # Lint as: python2, python3 |
Kuo Jen Wei | 7f00bb3 | 2018-11-01 15:35:24 +0800 | [diff] [blame] | 2 | # Copyright 2018 The Chromium OS Authors. All rights reserved. |
| 3 | # Use of this source code is governed by a BSD-style license that can be |
| 4 | # found in the LICENSE file. |
| 5 | |
| 6 | import contextlib |
| 7 | import json |
| 8 | import logging |
Kuo Jen Wei | 7f00bb3 | 2018-11-01 15:35:24 +0800 | [diff] [blame] | 9 | import os |
Kuo Jen Wei | 987b7eb | 2020-05-28 15:39:45 +0800 | [diff] [blame] | 10 | import time |
Kuo Jen Wei | 7f00bb3 | 2018-11-01 15:35:24 +0800 | [diff] [blame] | 11 | |
Kuo Jen Wei | 987b7eb | 2020-05-28 15:39:45 +0800 | [diff] [blame] | 12 | from autotest_lib.client.common_lib import error, utils |
Kuo Jen Wei | 7f00bb3 | 2018-11-01 15:35:24 +0800 | [diff] [blame] | 13 | |
| 14 | |
| 15 | class ChartFixture: |
Derek Beckett | d30bb56 | 2021-02-23 10:00:34 -0800 | [diff] [blame] | 16 | """Sets up chart tablet to display placeholder scene image.""" |
Kuo Jen Wei | 7f00bb3 | 2018-11-01 15:35:24 +0800 | [diff] [blame] | 17 | DISPLAY_SCRIPT = '/usr/local/autotest/bin/display_chart.py' |
Kuo Jen Wei | a10200e | 2020-03-13 16:03:54 +0800 | [diff] [blame] | 18 | OUTPUT_LOG = '/tmp/chart_service.log' |
Kuo Jen Wei | 7f00bb3 | 2018-11-01 15:35:24 +0800 | [diff] [blame] | 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 |
Kuo Jen Wei | a10200e | 2020-03-13 16:03:54 +0800 | [diff] [blame] | 24 | self.host.run(['rm', '-f', self.OUTPUT_LOG]) |
Kuo Jen Wei | 7f00bb3 | 2018-11-01 15:35:24 +0800 | [diff] [blame] | 25 | |
| 26 | def initialize(self): |
| 27 | """Prepare scene file and display it on chart host.""" |
| 28 | logging.info('Prepare scene file') |
Kuo Jen Wei | a10200e | 2020-03-13 16:03:54 +0800 | [diff] [blame] | 29 | tmpdir = self.host.get_tmp_dir() |
Kuo Jen Wei | 7f00bb3 | 2018-11-01 15:35:24 +0800 | [diff] [blame] | 30 | scene_path = os.path.join( |
Kuo Jen Wei | a10200e | 2020-03-13 16:03:54 +0800 | [diff] [blame] | 31 | tmpdir, self.scene_uri[self.scene_uri.rfind('/') + 1:]) |
Kuo Jen Wei | 7f00bb3 | 2018-11-01 15:35:24 +0800 | [diff] [blame] | 32 | self.host.run('wget', args=('-O', scene_path, self.scene_uri)) |
Kuo Jen Wei | 7f00bb3 | 2018-11-01 15:35:24 +0800 | [diff] [blame] | 33 | |
| 34 | logging.info('Display scene file') |
| 35 | self.display_pid = self.host.run_background( |
Kuo Jen Wei | a10200e | 2020-03-13 16:03:54 +0800 | [diff] [blame] | 36 | 'python2 {script} {scene} >{log} 2>&1'.format( |
| 37 | script=self.DISPLAY_SCRIPT, |
| 38 | scene=scene_path, |
| 39 | log=self.OUTPUT_LOG)) |
Kuo Jen Wei | 987b7eb | 2020-05-28 15:39:45 +0800 | [diff] [blame] | 40 | |
| 41 | logging.info( |
| 42 | 'Poll for "is ready" message for ensuring chart is ready.') |
Kuo Jen Wei | e276607 | 2020-12-08 10:25:45 +0800 | [diff] [blame] | 43 | timeout = 60 |
Kuo Jen Wei | 987b7eb | 2020-05-28 15:39:45 +0800 | [diff] [blame] | 44 | poll_time_step = 0.1 |
| 45 | while timeout > 0: |
| 46 | if self.host.run( |
| 47 | 'grep', |
| 48 | args=('-q', 'Chart is ready.', self.OUTPUT_LOG), |
| 49 | ignore_status=True).exit_status == 0: |
| 50 | break |
| 51 | time.sleep(poll_time_step) |
| 52 | timeout -= poll_time_step |
| 53 | else: |
| 54 | raise error.TestError('Timeout waiting for chart ready') |
Kuo Jen Wei | 7f00bb3 | 2018-11-01 15:35:24 +0800 | [diff] [blame] | 55 | |
| 56 | def cleanup(self): |
| 57 | """Cleanup display script.""" |
| 58 | if self.display_pid is not None: |
Kuo Jen Wei | a10200e | 2020-03-13 16:03:54 +0800 | [diff] [blame] | 59 | self.host.run( |
| 60 | 'kill', |
| 61 | args=('-2', str(self.display_pid)), |
| 62 | ignore_status=True) |
| 63 | self.host.get_file(self.OUTPUT_LOG, '.') |
Kuo Jen Wei | 7f00bb3 | 2018-11-01 15:35:24 +0800 | [diff] [blame] | 64 | |
| 65 | |
| 66 | def get_chart_address(host_address, args): |
Kuo Jen Wei | 3e89c44 | 2019-01-29 14:27:26 +0800 | [diff] [blame] | 67 | """Get address of chart tablet from commandline args or mapping logic in |
| 68 | test lab. |
| 69 | |
| 70 | @param host_address: a list of hostname strings. |
| 71 | @param args: a dict parse from commandline args. |
| 72 | @return: |
| 73 | A list of strings for chart tablet addresses. |
| 74 | """ |
Kuo Jen Wei | 7f00bb3 | 2018-11-01 15:35:24 +0800 | [diff] [blame] | 75 | address = utils.args_to_dict(args).get('chart') |
| 76 | if address is not None: |
| 77 | return address.split(',') |
| 78 | elif utils.is_in_container(): |
Kuo Jen Wei | 377e99b | 2020-02-25 16:39:42 +0800 | [diff] [blame] | 79 | return [utils.get_lab_chart_address(host) for host in host_address] |
Kuo Jen Wei | 7f00bb3 | 2018-11-01 15:35:24 +0800 | [diff] [blame] | 80 | else: |
| 81 | return None |
| 82 | |
| 83 | |
| 84 | class DUTFixture: |
| 85 | """Sets up camera filter for target camera facing on DUT.""" |
| 86 | TEST_CONFIG_PATH = '/var/cache/camera/test_config.json' |
Kuo Jen Wei | 6f854a0 | 2020-05-20 12:01:33 +0800 | [diff] [blame] | 87 | CAMERA_SCENE_LOG = '/tmp/scene.jpg' |
Kuo Jen Wei | 7f00bb3 | 2018-11-01 15:35:24 +0800 | [diff] [blame] | 88 | |
| 89 | def __init__(self, test, host, facing): |
| 90 | self.test = test |
| 91 | self.host = host |
| 92 | self.facing = facing |
| 93 | |
| 94 | @contextlib.contextmanager |
| 95 | def _set_selinux_permissive(self): |
| 96 | selinux_mode = self.host.run_output('getenforce') |
| 97 | self.host.run('setenforce 0') |
| 98 | yield |
| 99 | self.host.run('setenforce', args=(selinux_mode, )) |
| 100 | |
Kuo Jen Wei | 7f00bb3 | 2018-11-01 15:35:24 +0800 | [diff] [blame] | 101 | def _write_file(self, filepath, content, permission=None, owner=None): |
| 102 | """Write content to filepath on remote host. |
| 103 | @param permission: set permission to 0xxx octal number of remote file. |
| 104 | @param owner: set owner of remote file. |
| 105 | """ |
| 106 | tmp_path = os.path.join(self.test.tmpdir, os.path.basename(filepath)) |
| 107 | with open(tmp_path, 'w') as f: |
| 108 | f.write(content) |
| 109 | if permission is not None: |
| 110 | os.chmod(tmp_path, permission) |
| 111 | self.host.send_file(tmp_path, filepath, delete_dest=True) |
| 112 | if owner is not None: |
| 113 | self.host.run('chown', args=(owner, filepath)) |
| 114 | |
| 115 | def initialize(self): |
| 116 | """Filter out camera other than target facing on DUT.""" |
Kuo Jen Wei | 7f00bb3 | 2018-11-01 15:35:24 +0800 | [diff] [blame] | 117 | self._write_file( |
| 118 | self.TEST_CONFIG_PATH, |
| 119 | json.dumps({ |
| 120 | 'enable_back_camera': self.facing == 'back', |
| 121 | 'enable_front_camera': self.facing == 'front', |
| 122 | 'enable_external_camera': False |
| 123 | }), |
| 124 | owner='arc-camera') |
Kuo Jen Wei | f82a7b9 | 2021-06-08 16:14:40 +0800 | [diff] [blame] | 125 | |
| 126 | # cros_camera_service will reference the test config to filter out |
| 127 | # undesired cameras. |
| 128 | logging.info('Restart camera service with filter option') |
Kuo Jen Wei | 9d68af8 | 2020-06-23 10:43:21 +0800 | [diff] [blame] | 129 | self.host.upstart_restart('cros-camera') |
Kuo Jen Wei | 7f00bb3 | 2018-11-01 15:35:24 +0800 | [diff] [blame] | 130 | |
Kuo Jen Wei | f82a7b9 | 2021-06-08 16:14:40 +0800 | [diff] [blame] | 131 | # arc_setup will reference the test config to filter out the media |
| 132 | # profile of undesired cameras. |
| 133 | logging.info('Restart ARC++ container with camera test config') |
Kuo Jen Wei | 7f00bb3 | 2018-11-01 15:35:24 +0800 | [diff] [blame] | 134 | self.host.run('restart ui') |
| 135 | |
Kuo Jen Wei | 6f854a0 | 2020-05-20 12:01:33 +0800 | [diff] [blame] | 136 | @contextlib.contextmanager |
| 137 | def _stop_camera_service(self): |
Kuo Jen Wei | 50ef6e8 | 2021-03-29 12:04:47 +0800 | [diff] [blame] | 138 | # Ensure camera service is running or the |
| 139 | # upstart_stop()/upstart_restart() may failed due to in |
| 140 | # "start|post-stop" sleep for respawning state. See b/183904344 for |
| 141 | # detail. |
| 142 | logging.info('Wait for presence of camera service') |
| 143 | self.host.wait_for_service('cros-camera') |
| 144 | |
Kuo Jen Wei | 9d68af8 | 2020-06-23 10:43:21 +0800 | [diff] [blame] | 145 | self.host.upstart_stop('cros-camera') |
Kuo Jen Wei | 6f854a0 | 2020-05-20 12:01:33 +0800 | [diff] [blame] | 146 | yield |
Kuo Jen Wei | 9d68af8 | 2020-06-23 10:43:21 +0800 | [diff] [blame] | 147 | self.host.upstart_restart('cros-camera') |
Kuo Jen Wei | 6f854a0 | 2020-05-20 12:01:33 +0800 | [diff] [blame] | 148 | |
| 149 | def log_camera_scene(self): |
| 150 | """Capture an image from camera as the log for debugging scene related |
| 151 | problem.""" |
| 152 | |
| 153 | gtest_filter = ( |
| 154 | 'Camera3StillCaptureTest/' |
| 155 | 'Camera3DumpSimpleStillCaptureTest.DumpCaptureResult/0') |
| 156 | with self._stop_camera_service(): |
| 157 | self.host.run( |
| 158 | 'sudo', |
| 159 | args=('--user=arc-camera', 'cros_camera_test', |
| 160 | '--gtest_filter=' + gtest_filter, |
| 161 | '--camera_facing=' + self.facing, |
| 162 | '--dump_still_capture_path=' + |
| 163 | self.CAMERA_SCENE_LOG)) |
| 164 | |
| 165 | self.host.get_file(self.CAMERA_SCENE_LOG, '.') |
| 166 | |
Kuo Jen Wei | 7f00bb3 | 2018-11-01 15:35:24 +0800 | [diff] [blame] | 167 | def cleanup(self): |
| 168 | """Cleanup camera filter.""" |
| 169 | logging.info('Remove filter option and restore camera service') |
Kuo Jen Wei | 50ef6e8 | 2021-03-29 12:04:47 +0800 | [diff] [blame] | 170 | with self._stop_camera_service(): |
| 171 | self.host.run('rm', args=('-f', self.TEST_CONFIG_PATH)) |
Kuo Jen Wei | 7f00bb3 | 2018-11-01 15:35:24 +0800 | [diff] [blame] | 172 | |
Kuo Jen Wei | 7f00bb3 | 2018-11-01 15:35:24 +0800 | [diff] [blame] | 173 | logging.info('Restore camera profile in ARC++ container') |
Kuo Jen Wei | 7f00bb3 | 2018-11-01 15:35:24 +0800 | [diff] [blame] | 174 | self.host.run('restart ui') |