1# 2# Copyright (C) 2016 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 google.protobuf import text_format 20 21from vts.runners.host import errors 22from vts.proto import AndroidSystemControlMessage_pb2 as ASysCtrlMsg 23from vts.proto import ComponentSpecificationMessage_pb2 as CompSpecMsg 24from vts.runners.host.tcp_client import vts_tcp_client 25from vts.runners.host.tcp_server import callback_server 26from vts.utils.python.mirror import mirror_object 27 28COMPONENT_CLASS_DICT = {"hal_conventional": 1, 29 "hal_conventional_submodule": 2, 30 "hal_legacy": 3, 31 "hal_hidl": 4, 32 "hal_hidl_wrapped_conventional": 5, 33 "lib_shared": 11} 34 35COMPONENT_TYPE_DICT = {"audio": 1, 36 "camera": 2, 37 "gps": 3, 38 "light": 4, 39 "wifi": 5, 40 "mobile": 6, 41 "bluetooth": 7, 42 "nfc": 8, 43 "vibrator": 12, 44 "thermal": 13, 45 "tv_input": 14, 46 "tv_cec": 15, 47 "sensors": 16, 48 "vehicle": 17, 49 "vr": 18, 50 "graphics_allocator": 19, 51 "graphics_mapper": 20, 52 "radio": 21, 53 "contexthub": 22, 54 "graphics_composer": 23, 55 "media_omx": 24, 56 "bionic_libm": 1001, 57 "bionic_libc": 1002, 58 "vndk_libcutils": 1101} 59 60VTS_CALLBACK_SERVER_TARGET_SIDE_PORT = 5010 61 62_DEFAULT_TARGET_BASE_PATHS = ["/system/lib64/hw"] 63_DEFAULT_HWBINDER_SERVICE = "default" 64 65class HalMirror(object): 66 """The class that acts as the mirror to an Android device's HAL layer. 67 68 This class holds and manages the life cycle of multiple mirror objects that 69 map to different HAL components. 70 71 One can use this class to create and destroy a HAL mirror object. 72 73 Attributes: 74 _hal_level_mirrors: dict, key is HAL handler name, value is HAL 75 mirror object. 76 _callback_server: VtsTcpServer, the server that receives and handles 77 callback messages from target side. 78 _host_command_port: int, the host-side port for command-response 79 sessions. 80 _host_callback_port: int, the host-side port for callback sessions. 81 _client: VtsTcpClient, the client instance that can be used to send 82 commands to the target-side's agent. 83 """ 84 85 def __init__(self, host_command_port, host_callback_port): 86 self._hal_level_mirrors = {} 87 self._host_command_port = host_command_port 88 self._host_callback_port = host_callback_port 89 self._callback_server = None 90 91 def __del__(self): 92 self.CleanUp() 93 94 def CleanUp(self): 95 """Shutdown services and release resources held by the HalMirror. 96 """ 97 for hal_mirror_name in self._hal_level_mirrors.values(): 98 hal_mirror_name.CleanUp() 99 self._hal_level_mirrors = {} 100 if self._callback_server: 101 self._callback_server.Stop() 102 self._callback_server = None 103 104 def InitConventionalHal(self, 105 target_type, 106 target_version, 107 target_package="", 108 target_basepaths=_DEFAULT_TARGET_BASE_PATHS, 109 handler_name=None, 110 bits=64): 111 """Initiates a handler for a particular conventional HAL. 112 113 This will initiate a driver service for a HAL on the target side, create 114 the top level mirror object for a HAL, and register it in the manager. 115 116 Args: 117 target_type: string, the target type name (e.g., light, camera). 118 target_version: float, the target component version (e.g., 1.0). 119 target_basepaths: list of strings, the paths to look for target 120 files in. Default is _DEFAULT_TARGET_BASE_PATHS. 121 target_package: . separated string (e.g., a.b.c) to denote the 122 package name of target component. 123 handler_name: string, the name of the handler. target_type is used 124 by default. 125 bits: integer, processor architecture indicator: 32 or 64. 126 """ 127 self._CreateMirrorObject("hal_conventional", 128 target_type, 129 target_version, 130 target_package=target_package, 131 target_basepaths=target_basepaths, 132 handler_name=handler_name, 133 bits=bits) 134 135 def InitLegacyHal(self, 136 target_type, 137 target_version, 138 target_basepaths=_DEFAULT_TARGET_BASE_PATHS, 139 handler_name=None, 140 bits=64): 141 """Initiates a handler for a particular legacy HAL. 142 143 This will initiate a driver service for a HAL on the target side, create 144 the top level mirror object for a HAL, and register it in the manager. 145 146 Args: 147 target_type: string, the target type name (e.g., light, camera). 148 target_version: float, the target component version (e.g., 1.0). 149 target_basepaths: list of strings, the paths to look for target 150 files in. Default is _DEFAULT_TARGET_BASE_PATHS. 151 handler_name: string, the name of the handler. target_type is used 152 by default. 153 bits: integer, processor architecture indicator: 32 or 64. 154 """ 155 self._CreateMirrorObject("hal_legacy", 156 target_type, 157 target_version, 158 target_basepaths=target_basepaths, 159 handler_name=handler_name, 160 bits=bits) 161 162 def InitHidlHal(self, 163 target_type, 164 target_version, 165 target_package=None, 166 target_component_name=None, 167 target_basepaths=_DEFAULT_TARGET_BASE_PATHS, 168 handler_name=None, 169 hw_binder_service_name=_DEFAULT_HWBINDER_SERVICE, 170 bits=64): 171 """Initiates a handler for a particular HIDL HAL. 172 173 This will initiate a driver service for a HAL on the target side, create 174 the top level mirror object for a HAL, and register it in the manager. 175 176 Args: 177 target_type: string, the target type name (e.g., light, camera). 178 target_version: float, the target component version (e.g., 1.0). 179 target_package: string, the package name of a target HIDL HAL. 180 target_basepaths: list of strings, the paths to look for target 181 files in. Default is _DEFAULT_TARGET_BASE_PATHS. 182 handler_name: string, the name of the handler. target_type is used 183 by default. 184 hw_binder_service_name: string, the name of a HW binder service. 185 bits: integer, processor architecture indicator: 32 or 64. 186 """ 187 self._CreateMirrorObject("hal_hidl", 188 target_type, 189 target_version, 190 target_package=target_package, 191 target_component_name=target_component_name, 192 target_basepaths=target_basepaths, 193 handler_name=handler_name, 194 hw_binder_service_name=hw_binder_service_name, 195 bits=bits) 196 197 def RemoveHal(self, handler_name): 198 self._hal_level_mirrors[handler_name].CleanUp() 199 self._hal_level_mirrors.pop(handler_name) 200 201 def _StartCallbackServer(self): 202 """Starts the callback server. 203 204 Raises: 205 errors.ComponentLoadingError is raised if the callback server fails 206 to start. 207 """ 208 self._callback_server = callback_server.CallbackServer() 209 _, port = self._callback_server.Start(self._host_callback_port) 210 if port != self._host_callback_port: 211 raise errors.ComponentLoadingError( 212 "Failed to start a callback TcpServer at port %s" % 213 self._host_callback_port) 214 215 def _CreateMirrorObject(self, 216 target_class, 217 target_type, 218 target_version, 219 target_package=None, 220 target_component_name=None, 221 target_basepaths=_DEFAULT_TARGET_BASE_PATHS, 222 handler_name=None, 223 hw_binder_service_name=None, 224 bits=64): 225 """Initiates the driver for a HAL on the target device and creates a top 226 level MirroObject for it. 227 228 Also starts the callback server to listen for callback invocations. 229 230 Args: 231 target_class: string, the target class name (e.g., hal). 232 target_type: string, the target type name (e.g., light, camera). 233 target_version: float, the target component version (e.g., 1.0). 234 target_package: string, the package name of a HIDL HAL. 235 target_component_name: string, the name of a target component. 236 target_basepaths: list of strings, the paths to look for target 237 files in. Default is _DEFAULT_TARGET_BASE_PATHS. 238 handler_name: string, the name of the handler. target_type is used 239 by default. 240 hw_binder_service_name: string, the name of a HW binder service. 241 bits: integer, processor architecture indicator: 32 or 64. 242 243 Raises: 244 errors.ComponentLoadingError is raised when error occurs trying to 245 create a MirrorObject. 246 """ 247 if bits not in [32, 64]: 248 raise error.ComponentLoadingError("Invalid value for bits: %s" % 249 bits) 250 self._StartCallbackServer() 251 self._client = vts_tcp_client.VtsTcpClient() 252 self._client.Connect(command_port=self._host_command_port, 253 callback_port=self._host_callback_port) 254 if not handler_name: 255 handler_name = target_type 256 service_name = "vts_driver_%s" % handler_name 257 258 target_filename = None 259 if target_class == "hal_conventional" or target_class == "hal_legacy": 260 # Get all the HALs available on the target. 261 hal_list = self._client.ListHals(target_basepaths) 262 if not hal_list: 263 raise errors.ComponentLoadingError( 264 "Could not find any HAL under path %s" % target_basepaths) 265 logging.debug(hal_list) 266 267 # Find the corresponding filename for HAL target type. 268 for name in hal_list: 269 if target_type in name: 270 # TODO: check more exactly (e.g., multiple hits). 271 target_filename = name 272 if not target_filename: 273 raise errors.ComponentLoadingError( 274 "No file found for HAL target type %s." % target_type) 275 276 # Check whether the requested binder service is already running. 277 # if client.CheckDriverService(service_name=service_name): 278 # raise errors.ComponentLoadingError("A driver for %s already exists" % 279 # service_name) 280 elif target_class == "hal_hidl": 281 # TODO: either user the default hw-binder service or start a new 282 # service (e.g., if an instrumented binary is used). 283 pass 284 285 # Launch the corresponding driver of the requested HAL on the target. 286 logging.info("Init the driver service for %s", target_type) 287 target_class_id = COMPONENT_CLASS_DICT[target_class.lower()] 288 target_type_id = COMPONENT_TYPE_DICT[target_type.lower()] 289 driver_type = { 290 "hal_conventional": ASysCtrlMsg.VTS_DRIVER_TYPE_HAL_CONVENTIONAL, 291 "hal_legacy": ASysCtrlMsg.VTS_DRIVER_TYPE_HAL_LEGACY, 292 "hal_hidl": ASysCtrlMsg.VTS_DRIVER_TYPE_HAL_HIDL 293 }.get(target_class) 294 295 launched = self._client.LaunchDriverService( 296 driver_type=driver_type, 297 service_name=service_name, 298 bits=bits, 299 file_path=target_filename, 300 target_class=target_class_id, 301 target_type=target_type_id, 302 target_version=target_version, 303 target_package=target_package, 304 target_component_name=target_component_name, 305 hw_binder_service_name=hw_binder_service_name) 306 307 if not launched: 308 raise errors.ComponentLoadingError( 309 "Failed to launch driver service %s from file path %s" % 310 (target_type, target_filename)) 311 312 # Create API spec message. 313 found_api_spec = self._client.ListApis() 314 if not found_api_spec: 315 raise errors.ComponentLoadingError("No API found for %s" % 316 service_name) 317 logging.debug("Found %d APIs for %s:\n%s", len(found_api_spec), 318 service_name, found_api_spec) 319 if_spec_msg = CompSpecMsg.ComponentSpecificationMessage() 320 text_format.Merge(found_api_spec, if_spec_msg) 321 322 # Instantiate a MirrorObject and return it. 323 hal_mirror = mirror_object.MirrorObject(self._client, if_spec_msg, 324 self._callback_server) 325 self._hal_level_mirrors[handler_name] = hal_mirror 326 327 def __getattr__(self, name): 328 return self._hal_level_mirrors[name] 329 330 def Ping(self): 331 """Returns true iff pinging the agent is successful, False otherwise.""" 332 return self._client.Ping() 333