1# Copyright 2017 The Chromium 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
5"""A test which verifies the camera function with HAL3 interface."""
6
7import contextlib
8import json
9import logging
10import os
11import xml.etree.ElementTree
12from autotest_lib.client.bin import test, utils
13from autotest_lib.client.common_lib import error
14from autotest_lib.client.cros import service_stopper
15from autotest_lib.client.cros.camera import camera_utils
16from autotest_lib.client.cros.video import device_capability
17from sets import Set
18
19
20class camera_HAL3(test.test):
21    """
22    This test is a wrapper of the test binary cros_camera_test.
23    """
24
25    version = 1
26    test_binary = 'cros_camera_test'
27    dep = 'camera_hal3'
28    cros_camera_service = 'cros-camera'
29    media_profiles_path = os.path.join('vendor', 'etc', 'media_profiles.xml')
30    tablet_board_list = ['scarlet', 'nocturne']
31    test_config_path = '/var/cache/camera/test_config.json'
32
33    def setup(self):
34        """
35        Run common setup steps.
36        """
37        self.dep_dir = os.path.join(self.autodir, 'deps', self.dep)
38        self.job.setup_dep([self.dep])
39        logging.debug('mydep is at %s', self.dep_dir)
40
41    @contextlib.contextmanager
42    def set_test_config(self, test_config):
43        with open(self.test_config_path, 'w') as fp:
44            json.dump(test_config, fp)
45        yield
46        os.remove(self.test_config_path)
47
48    def get_recording_params(self):
49        """
50        Get recording parameters from media profiles
51        """
52        xml_content = utils.system_output([
53            'android-sh', '-c',
54            'cat "%s"' % utils.sh_escape(self.media_profiles_path)
55        ])
56        root = xml.etree.ElementTree.fromstring(xml_content)
57        recording_params = Set()
58        for camcorder_profiles in root.findall('CamcorderProfiles'):
59            for encoder_profile in camcorder_profiles.findall('EncoderProfile'):
60                video = encoder_profile.find('Video')
61                recording_params.add('%s:%s:%s:%s' % (
62                    camcorder_profiles.get('cameraId'), video.get('width'),
63                    video.get('height'), video.get('frameRate')))
64        return '--recording_params=' + ','.join(recording_params)
65
66    def run_once(self,
67                 cmd_timeout=600,
68                 camera_hals=None,
69                 options=None,
70                 capability=None,
71                 test_config=None):
72        """
73        Entry point of this test.
74
75        @param cmd_timeout: Seconds. Timeout for running the test command.
76        @param camera_hals: The camera HALs to be tested. e.g. ['usb.so']
77        @param options: Option strings passed to test command. e.g. ['--v=1']
78        @param capability: Capability required for executing this test.
79        """
80        if options is None:
81            options = []
82
83        if test_config is None:
84            test_config = {}
85
86        if capability:
87            device_capability.DeviceCapability().ensure_capability(capability)
88
89        self.job.install_pkg(self.dep, 'dep', self.dep_dir)
90
91        camera_hal_paths = camera_utils.get_camera_hal_paths_for_test()
92        if camera_hals is not None:
93            name_map = dict((os.path.basename(path), path)
94                            for path in camera_hal_paths)
95            camera_hal_paths = []
96            for name in camera_hals:
97                path = name_map.get(name)
98                if path is None:
99                    msg = 'HAL %r is not available for test' % name
100                    raise error.TestNAError(msg)
101                camera_hal_paths.append(path)
102
103        binary_path = os.path.join(self.dep_dir, 'bin', self.test_binary)
104
105        with service_stopper.ServiceStopper([self.cros_camera_service]), \
106                self.set_test_config(test_config):
107            has_facing_option = False
108            cmd = ['sudo', '--user=arc-camera', binary_path]
109            for option in options:
110                if 'gtest_filter' in option:
111                    filters = option.split('=')[1]
112                    if 'Camera3DeviceTest' in filters.split('-')[0]:
113                        if utils.get_current_board() in self.tablet_board_list:
114                            option += (':' if '-' in filters else '-')
115                            option += '*SensorOrientationTest/*'
116                    if any(name in filters.split('-')[0] for name in
117                           ('Camera3ModuleFixture', 'Camera3RecordingFixture')):
118                        cmd.append(self.get_recording_params())
119                elif 'camera_facing' in option:
120                    has_facing_option = True
121                cmd.append(option)
122
123            if has_facing_option:
124                utils.system(cmd, timeout=cmd_timeout)
125            else:
126                for camera_hal_path in camera_hal_paths:
127                    logging.info('Run test with %r', camera_hal_path)
128                    cmd.append('--camera_hal_path=%s' % camera_hal_path)
129                    utils.system(cmd, timeout=cmd_timeout)
130                    cmd.pop()
131