Home | History | Annotate | Download | only in common
      1 #
      2 # Copyright (C) 2017 The Android Open Source Project
      3 #
      4 # Licensed under the Apache License, Version 2.0 (the "License");
      5 # you may not use this file except in compliance with the License.
      6 # You may obtain a copy of the License at
      7 #
      8 #      http://www.apache.org/licenses/LICENSE-2.0
      9 #
     10 # Unless required by applicable law or agreed to in writing, software
     11 # distributed under the License is distributed on an "AS IS" BASIS,
     12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13 # See the License for the specific language governing permissions and
     14 # limitations under the License.
     15 #
     16 
     17 import logging
     18 import os
     19 
     20 from google.protobuf import text_format
     21 from vts.proto import ComponentSpecificationMessage_pb2 as CompSpecMsg
     22 
     23 
     24 def HalPackageToNameAndVersion(hal_package):
     25     """Returns hal name and version given hal package name.
     26 
     27     Args:
     28         hal_package: string, e.g. 'android.hardware.vibrator (at] 1.0'
     29 
     30     Return:
     31         tuple, hal name and version e.g. ('vibrator', '1.0')
     32     """
     33     # TODO(trong): check if proper package name.
     34     prefix = 'android.hardware.'
     35     if not hal_package.startswith(prefix):
     36         logging.error("Invalid hal package name: %s" % hal_package)
     37     [hal_name, hal_version] = hal_package[len(prefix):].split('@')
     38     return (hal_name, hal_version)
     39 
     40 
     41 def HalNameDir(hal_name):
     42     """Returns directory name corresponding to hal name."""
     43     return hal_name.replace('.', '/')
     44 
     45 
     46 def HalVerDir(hal_version):
     47     """Returns directory name corresponding to hal version."""
     48     return "V" + hal_version.replace('.', '_')
     49 
     50 
     51 class VtsSpecParser(object):
     52     """Provides an API to parse .vts spec files.
     53 
     54     Attributes:
     55         data_file_path: string, path to vts data directory on target.
     56     """
     57 
     58     def __init__(self, data_file_path):
     59         """VtsSpecParser constructor.
     60 
     61         Args:
     62             data_file_path: string, path to vts data directory on target.
     63         """
     64         self._data_file_path = data_file_path
     65 
     66     def _VtsSpecDir(self, hal_name, hal_version):
     67         """Returns directory path to .vts spec files.
     68 
     69         Args:
     70             hal_name: string, name of the hal, e.g. 'vibrator'.
     71             hal_version: string, version of the hal, e.g '7.4'
     72 
     73         Returns:
     74             string, directory path to .vts spec files.
     75         """
     76         return os.path.join(
     77             self._data_file_path, 'spec', 'hardware', 'interfaces',
     78             hal_name.replace('.', '/'), hal_version, 'vts')
     79 
     80     def IndirectImportedHals(self, hal_name, hal_version):
     81         """Returns a list of imported HALs.
     82 
     83         Includes indirectly imported ones and excludes the given one.
     84 
     85         Args:
     86           hal_name: string, name of the hal, e.g. 'vibrator'.
     87           hal_version: string, version of the hal, e.g '7.4'
     88 
     89         Returns:
     90           list of string tuples. For example,
     91               [('vibrator', '1.3'), ('sensors', '3.2')]
     92         """
     93 
     94         this_hal = (hal_name, hal_version)
     95         imported_hals = [this_hal]
     96 
     97         for hal_name, hal_version in imported_hals:
     98             for discovery in self.ImportedHals(hal_name, hal_version):
     99                 if discovery not in imported_hals:
    100                     imported_hals.append(discovery)
    101 
    102         imported_hals.remove(this_hal)
    103         return sorted(imported_hals)
    104 
    105     def ImportedHals(self, hal_name, hal_version):
    106         """Returns a list of imported HALs.
    107 
    108         Args:
    109           hal_name: string, name of the hal, e.g. 'vibrator'.
    110           hal_version: string, version of the hal, e.g '7.4'
    111 
    112         Returns:
    113           list of string tuples. For example,
    114               [('vibrator', '1.3'), ('sensors', '3.2')]
    115         """
    116 
    117         vts_spec_protos = self.VtsSpecProto(hal_name, hal_version)
    118         imported_hals = set()
    119         for vts_spec in vts_spec_protos:
    120             for package in getattr(vts_spec, 'import', []):
    121                 if package.startswith('android.hardware.'):
    122                     package = package.split('::')[0]
    123                     imported_hals.add(HalPackageToNameAndVersion(package))
    124 
    125         this_hal = (hal_name, hal_version)
    126         if this_hal in imported_hals:
    127             imported_hals.remove(this_hal)
    128         return sorted(imported_hals)
    129 
    130     def VtsSpecNames(self, hal_name, hal_version):
    131         """Returns list of .vts file names for given hal name and version.
    132 
    133         Args:
    134             hal_name: string, name of the hal, e.g. 'vibrator'.
    135             hal_version: string, version of the hal, e.g '7.4'
    136 
    137         Returns:
    138             list of string, .vts files for given hal name and version,
    139               e.g. ['Vibrator.vts', 'types.vts']
    140         """
    141         vts_spec_names = filter(
    142             lambda x: x.endswith('.vts'),
    143             os.listdir(self._VtsSpecDir(hal_name, hal_version)))
    144         return sorted(vts_spec_names)
    145 
    146     def VtsSpecProto(self, hal_name, hal_version, vts_spec_name=''):
    147         """Returns list of .vts protos for given hal name and version.
    148 
    149         Args:
    150             hal_name: string, name of the hal, e.g. 'vibrator'.
    151             hal_version: string, version of the hal, e.g '7.4'
    152             vts_spec:
    153 
    154         Returns:
    155             list with all vts spec protos for a given hal and version if
    156             vts_spec_name is not given. If vts_spec_name is not empty, then
    157             returns ComponentSpecificationMessage matching vts_spec_name.
    158             If no such vts_spec_name, return None.
    159         """
    160         if not vts_spec_name:
    161             vts_spec_protos = []
    162             for vts_spec in self.VtsSpecNames(hal_name, hal_version):
    163                 vts_spec_proto = self.VtsSpecProto(hal_name, hal_version,
    164                                                    vts_spec)
    165                 vts_spec_protos.append(vts_spec_proto)
    166             return vts_spec_protos
    167         else:
    168             if vts_spec_name in self.VtsSpecNames(hal_name, hal_version):
    169                 vts_spec_proto = CompSpecMsg.ComponentSpecificationMessage()
    170                 vts_spec_path = os.path.join(
    171                     self._VtsSpecDir(hal_name, hal_version), vts_spec_name)
    172                 with open(vts_spec_path, 'r') as vts_spec_file:
    173                     vts_spec_string = vts_spec_file.read()
    174                     text_format.Merge(vts_spec_string, vts_spec_proto)
    175                 return vts_spec_proto
    176