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
17import logging
18
19from xml.etree import ElementTree
20
21_ARCH = "arch"
22_HWBINDER = "hwbinder"
23_NAME = "name"
24_PASSTHROUGH = "passthrough"
25_TRANSPORT = "transport"
26_VERSION = "version"
27_INTERFACE = "interface"
28_INSTANCE = "instance"
29
30
31class HalInterfaceDescription(object):
32    """Class to store the information of a running hal service interface.
33
34    Attributes:
35        hal_interface_name: interface name within the hal e.g. INfc.
36        hal_instance_instances: a list of instance name of the registered hal service e.g. default. nfc
37    """
38
39    def __init__(self, hal_interface_name, hal_interface_instances):
40        self.hal_interface_name = hal_interface_name
41        self.hal_interface_instances = hal_interface_instances
42
43
44class HalDescription(object):
45    """Class to store the information of a running hal service.
46
47    Attributes:
48        hal_name: hal name e.g. android.hardware.nfc.
49        hal_version: hal version e.g. 1.0.
50        hal_interfaces: a list of HalInterfaceDescription within the hal.
51        hal_archs: a list of strings where each string indicates the supported
52                   client bitness (e.g,. ["32", "64"]).
53    """
54
55    def __init__(self, hal_name, hal_version, hal_interfaces, hal_archs):
56        self.hal_name = hal_name
57        self.hal_version = hal_version
58        self.hal_interfaces = hal_interfaces
59        self.hal_archs = hal_archs
60
61
62def GetHalDescriptions(vintf_xml):
63    """Parses a vintf xml string.
64
65    Args:
66        vintf_xml: string, containing a vintf.xml file content.
67
68    Returns:
69        a dictionary containing the information of hwbinder HALs,
70        a dictionary containing the information of passthrough HALs.
71    """
72    try:
73        xml_root = ElementTree.fromstring(vintf_xml)
74    except ElementTree.ParseError as e:
75        logging.exception(e)
76        logging.error('This vintf xml could not be parsed:\n%s' % vintf_xml)
77        return None, None
78
79    hwbinder_hals = dict()
80    passthrough_hals = dict()
81
82    for xml_hal in xml_root:
83        hal_name = None
84        hal_transport = None
85        hal_version = None
86        hal_interfaces = []
87        hal_archs = ["32", "64"]
88        for xml_hal_item in xml_hal:
89            tag = str(xml_hal_item.tag)
90            if tag == _NAME:
91                hal_name = str(xml_hal_item.text)
92            elif tag == _TRANSPORT:
93                hal_transport = str(xml_hal_item.text)
94                if _ARCH in xml_hal_item.attrib:
95                    hal_archs = xml_hal_item.attrib[_ARCH].split("+")
96            elif tag == _VERSION:
97                hal_version = str(xml_hal_item.text)
98            elif tag == _INTERFACE:
99                hal_interface_name = None
100                hal_interface_instances = []
101                for interface_item in xml_hal_item:
102                    tag = str(interface_item.tag)
103                    if tag == _NAME:
104                        hal_interface_name = str(interface_item.text)
105                    elif tag == _INSTANCE:
106                        hal_interface_instances.append(
107                            str(interface_item.text))
108                hal_interfaces.append(
109                    HalInterfaceDescription(hal_interface_name,
110                                            hal_interface_instances))
111        hal_info = HalDescription(hal_name, hal_version, hal_interfaces,
112                                  hal_archs)
113        hal_key = "%s@%s" % (hal_name, hal_version)
114        if hal_transport == _HWBINDER:
115            hwbinder_hals[hal_key] = hal_info
116        elif hal_transport == _PASSTHROUGH:
117            passthrough_hals[hal_key] = hal_info
118        else:
119            logging.error("Unknown transport type %s", hal_transport)
120    return hwbinder_hals, passthrough_hals
121