• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/env python3.4
2#
3# Copyright (C) 2017 The Android Open Source Project
4#
5# Licensed under the Apache License, Version 2.0 (the 'License');
6# you may not use this file except in compliance with the License.
7# You may obtain a copy of the License at
8#
9#      http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an 'AS IS' BASIS,
13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14# See the License for the specific language governing permissions and
15# limitations under the License.
16#
17
18import fnmatch
19import os
20import shutil
21import subprocess
22import sys
23import tempfile
24
25ANDROID_BUILD_TOP = os.environ.get('ANDROID_BUILD_TOP')
26if not ANDROID_BUILD_TOP:
27    print 'Run "lunch" command first.'
28    sys.exit(1)
29
30# TODO(trong): use proper packaging without referencing modules from source.
31TEST_VTS_DIR = os.path.join(ANDROID_BUILD_TOP, 'test', 'vts')
32sys.path.append(TEST_VTS_DIR)
33from proto import ComponentSpecificationMessage_pb2 as CompSpecMsg
34from google.protobuf import text_format
35import build_rule_gen_utils as utils
36
37
38class VtsSpecParser(object):
39    """Provides an API to generate a parse .vts spec files."""
40    HW_IFACE_DIR = os.path.join(ANDROID_BUILD_TOP, 'hardware', 'interfaces')
41
42    def __init__(self):
43        """VtsSpecParser constructor.
44
45        For every unique pair of (hal name, hal version) available under
46        hardware/interfaces, generates .vts files using hidl-gen.
47
48        Args:
49            tmp_dir: string, temporary directory to which to write .vts files.
50        """
51        self._cache = set()
52        self._tmp_dir = tempfile.mkdtemp()
53        hal_list = self.HalNamesAndVersions()
54
55    def __del__(self):
56        """VtsSpecParser destructor.
57
58        Removes all temporary files that were generated.
59        """
60        print "Removing temp files."
61        if os.path.exists(self._tmp_dir):
62            shutil.rmtree(self._tmp_dir)
63
64    def ImportedPackagesList(self, hal_name, hal_version):
65        """Returns a list of imported packages.
66
67        Args:
68          hal_name: string, name of the hal, e.g. 'vibrator'.
69          hal_version: string, version of the hal, e.g '7.4'
70
71        Returns:
72          list of strings. For example,
73              ['android.hardware.vibrator@1.3', 'android.hidl.base@1.7']
74        """
75        self.GenerateVtsSpecs(hal_name, hal_version)
76        vts_spec_protos = self.VtsSpecProtos(hal_name, hal_version)
77
78        imported_packages = set()
79        for vts_spec in vts_spec_protos:
80            for package in getattr(vts_spec, 'import', []):
81                package = package.split('::')[0]
82                imported_packages.add(package)
83
84        this_package = 'android.hardware.%s@%s' % (hal_name, hal_version)
85        if this_package in imported_packages:
86            imported_packages.remove(this_package)
87
88        return sorted(imported_packages)
89
90    def GenerateVtsSpecs(self, hal_name, hal_version):
91        """Generates VTS specs.
92
93        Uses hidl-gen to generate .vts files under a tmp directory.
94
95        Args:
96          hal_name: string, name of the hal, e.g. 'vibrator'.
97          hal_version: string, version of the hal, e.g '7.4'
98          tmp_dir: string, location to which to write tmp files.
99        """
100        if (hal_name, hal_version) in self._cache:
101            return
102        hidl_gen_cmd = (
103            'hidl-gen -o {TEMP_DIR} -L vts '
104            '-r android.hardware:{HW_IFACE_DIR} '
105            '-r android.hidl:{ANDROID_BUILD_TOP}/system/libhidl/transport '
106            'android.hardware.{HAL_NAME}@{HAL_VERSION}').format(
107                TEMP_DIR=self._tmp_dir,
108                HW_IFACE_DIR=self.HW_IFACE_DIR,
109                ANDROID_BUILD_TOP=ANDROID_BUILD_TOP,
110                HAL_NAME=hal_name,
111                HAL_VERSION=hal_version)
112        subprocess.call(hidl_gen_cmd, shell=True)
113        self._cache.add((hal_name, hal_version))
114
115    def HalNamesAndVersions(self):
116        """Returns a list of hals and version present under hardware/interfaces.
117
118        Returns:
119          List of tuples of strings containing hal names and hal versions.
120          For example, [('vibrator', '1.3'), ('sensors', '1.7')]
121        """
122        result = []
123        for base, dirs, files in os.walk(self.HW_IFACE_DIR):
124            pattern = self.HW_IFACE_DIR + '*/[0-9].[0-9]'
125            if fnmatch.fnmatch(base, pattern) and 'example' not in base:
126                hal_dir = os.path.relpath(base, self.HW_IFACE_DIR)
127                (hal_name, hal_version) = os.path.split(hal_dir)
128                hal_name = hal_name.replace('/', '.')
129                result.append((hal_name, hal_version))
130        return sorted(result)
131
132    def VtsSpecNames(self, hal_name, hal_version):
133        """Returns list of .vts file names for given hal name and version.
134
135        hal_name: string, name of the hal, e.g. 'vibrator'.
136        hal_version: string, version of the hal, e.g '7.4'
137
138        Returns:
139          list of string, .vts files for given hal name and version,
140              e.g. ['Vibrator.vts', 'types.vts']
141        """
142        self.GenerateVtsSpecs(hal_name, hal_version)
143        vts_spec_dir = os.path.join(self._tmp_dir, 'android', 'hardware',
144                                    utils.HalNameDir(hal_name), hal_version)
145        vts_spec_names = filter(lambda x: x.endswith('.vts'),
146                                os.listdir(vts_spec_dir))
147        return sorted(vts_spec_names)
148
149    def VtsSpecProtos(self, hal_name, hal_version):
150        """Returns list of .vts protos for given hal name and version.
151
152        hal_name: string, name of the hal, e.g. 'vibrator'.
153        hal_version: string, version of the hal, e.g '7.4'
154
155        Returns:
156          list of ComponentSpecificationMessages
157        """
158        self.GenerateVtsSpecs(hal_name, hal_version)
159        vts_spec_dir = os.path.join(self._tmp_dir, 'android', 'hardware',
160                                    utils.HalNameDir(hal_name), hal_version)
161        vts_spec_protos = []
162        for vts_spec in self.VtsSpecNames(hal_name, hal_version):
163            spec_proto = CompSpecMsg.ComponentSpecificationMessage()
164            vts_spec_path = os.path.join(vts_spec_dir, vts_spec)
165            with open(vts_spec_path, 'r') as spec_file:
166                spec_string = spec_file.read()
167                text_format.Merge(spec_string, spec_proto)
168
169            vts_spec_protos.append(spec_proto)
170        return vts_spec_protos
171