def VtsSpecProto(self, hal_name, hal_version, vts_spec_name=''): """Returns list of .vts protos for given hal name and version. Args: hal_name: string, name of the hal, e.g. 'vibrator'. hal_version: string, version of the hal, e.g '7.4' vts_spec: Returns: list with all vts spec protos for a given hal and version if vts_spec_name is not given. If vts_spec_name is not empty, then returns ComponentSpecificationMessage matching vts_spec_name. If no such vts_spec_name, return None. """ if not vts_spec_name: vts_spec_protos = [] for vts_spec in self.VtsSpecNames(hal_name, hal_version): vts_spec_proto = self.VtsSpecProto(hal_name, hal_version, vts_spec) vts_spec_protos.append(vts_spec_proto) return vts_spec_protos else: if vts_spec_name in self.VtsSpecNames(hal_name, hal_version): vts_spec_proto = CompSpecMsg.ComponentSpecificationMessage() vts_spec_path = os.path.join( self._VtsSpecDir(hal_name, hal_version), vts_spec_name) with open(vts_spec_path, 'r') as vts_spec_file: vts_spec_string = vts_spec_file.read() text_format.Merge(vts_spec_string, vts_spec_proto) return vts_spec_proto
def _GetTotalApis(self, package_name, version, interface_name): """Parse the specified vts spec and get all APIs defined in the spec. Args: package_name: string, HAL package name. version: string, HAL version. interface_name: string, HAL interface name. Returns: A set of strings, each string represents an API defined in the spec. """ total_apis = set() spec_proto = CompSpecMsg.ComponentSpecificationMessage() # TODO: support general package that does not start with android.hardware. if not package_name.startswith(DEFAULT_HAL_ROOT): logging.warning("Unsupported hal package: %s", package_name) return total_apis hal_package_path = package_name[len(DEFAULT_HAL_ROOT):].replace( ".", "/") vts_spec_path = os.path.join( self.data_file_path, "spec/hardware/interfaces", hal_package_path, version, "vts", interface_name[1:] + ".vts") logging.debug("vts_spec_path: %s", vts_spec_path) with open(vts_spec_path, 'r') as spec_file: spec_string = spec_file.read() text_format.Merge(spec_string, spec_proto) for api in spec_proto.interface.api: if not api.is_inherited: total_apis.add(api.name) return total_apis
def ReadSpecification(self, interface_name, target_class, target_type, target_version, target_package, recursive=False): """RPC to VTS_AGENT_COMMAND_READ_SPECIFICATION. Args: other args: see SendCommand recursive: boolean, set to recursively read the imported specification(s) and return the merged one. """ self.SendCommand(SysMsg_pb2.VTS_AGENT_COMMAND_READ_SPECIFICATION, service_name=interface_name, target_class=target_class, target_type=target_type, target_version=target_version, target_package=target_package) resp = self.RecvResponse(retries=2) logging.info("resp for VTS_AGENT_COMMAND_EXECUTE_READ_INTERFACE: %s", resp) logging.info("proto: %s", resp.result) result = CompSpecMsg_pb2.ComponentSpecificationMessage() if resp.result == "error": raise errors.VtsTcpCommunicationError( "API call error by the VTS driver.") try: text_format.Merge(resp.result, result) except text_format.ParseError as e: logging.exception(e) logging.error("Paring error\n%s", resp.result) if recursive and hasattr(result, "import"): for imported_interface in getattr(result, "import"): if imported_interface == "[email protected]::types": logging.warn("import [email protected]::types skipped") continue imported_result = self.ReadSpecification( imported_interface.split("::")[1], # TODO(yim): derive target_class and # target_type from package path or remove them msg.component_class if target_class is None else target_class, msg.component_type if target_type is None else target_type, float(imported_interface.split("@")[1].split("::")[0]), imported_interface.split("@")[0]) # Merge the attributes from imported interface. for attribute in imported_result.attribute: imported_attribute = result.attribute.add() imported_attribute.CopyFrom(attribute) return result
def InitHalDriver(self, target_type, target_version_major, target_version_minor, target_package, target_component_name, hw_binder_service_name, handler_name, bits, is_test_hal): """Initiates the driver for a HIDL HAL on the target device and loads the interface specification message. Args: target_type: string, the target type name (e.g., light, camera). target_version_major: int, the target component major version (e.g., 1.0 -> 1). target_version_minor: int, the target component minor version (e.g., 1.0 -> 0). target_package: . separated string (e.g., a.b.c) to denote the package name of target component. target_component_name: string, the target componet name (e.g., INfc). hw_binder_service_name: string, name of the HAL service instance (e.g. default) handler_name: string, the name of the handler. target_type is used by default. bits: integer, processor architecture indicator: 32 or 64. is_test_hal: bool, whether the HAL service is a test HAL (e.g. msgq). Raises: errors.ComponentLoadingError is raised when error occurs trying to create a MirrorObject. """ driver_id = self.LaunchMirrorDriver( ASysCtrlMsg.VTS_DRIVER_TYPE_HAL_HIDL, "hal_hidl", target_type, target_version_major, target_version_minor, target_package=target_package, target_component_name=target_component_name, handler_name=handler_name, hw_binder_service_name=hw_binder_service_name, bits=bits, is_test_hal=is_test_hal) self._driver_id = driver_id #TODO: ListApis assumes only one HAL is loaded at a time, need to # figure out a way to get the api_spec when we want to test # multiple HALs together. found_api_spec = self._client.ListApis() if not found_api_spec: raise errors.ComponentLoadingError( "No API found for %s" % target_type) if_spec_msg = CompSpecMsg.ComponentSpecificationMessage() text_format.Merge(found_api_spec, if_spec_msg) self._if_spec_msg = if_spec_msg
def GetHidlNestedInterface(self, interface_name, interface_id, target_class=None, target_type=None, version=None, package=None): """Gets HIDL type interface's host-side mirror. Args: interface_name: string, the name of a target interface to read. interface_id: integer, the ID of a target interface to control. target_class: integer, optional used to override the loaded HAL's component_class. target_type: integer, optional used to override the loaded HAL's component_type. version: integer, optional used to override the loaded HAL's component_type_version. package: integer, optional used to override the loaded HAL's package. Returns: a host-side mirror of a HIDL interface """ msg = self._if_spec_msg found_api_spec = self._client.ReadSpecification( interface_name, msg.component_class if target_class is None else target_class, msg.component_type if target_type is None else target_type, msg.component_type_version if version is None else version, msg.package if package is None else package, recursive=True) found_api_spec = str(found_api_spec) logging.debug("found_api_spec %s", found_api_spec) if_spec_msg = CompSpecMsg.ComponentSpecificationMessage() text_format.Merge(found_api_spec, if_spec_msg) # Instantiate a MirrorObject and return it. hal_mirror = MirrorObject(self._client, if_spec_msg, None, interface_id=interface_id) return hal_mirror
def InitLibDriver(self, target_type, target_version, target_package, target_filename, target_basepaths, handler_name, bits): """Initiates the driver for a lib on the target device and loads the interface specification message. Args: target_type: string, the target type name (e.g., light, camera). target_version: float, the target component version (e.g., 1.0). target_package: . separated string (e.g., a.b.c) to denote the package name of target component. target_filename: string, the target file name (e.g., libm.so). target_basepaths: list of strings, the paths to look for target files in. handler_name: string, the name of the handler. target_type is used by default. bits: integer, processor architecture indicator: 32 or 64. """ # Get all the libs available on the target. lib_list = self._client.ListHals(target_basepaths) if not lib_list: raise errors.ComponentLoadingError( "Could not find any lib under path %s" % target_basepaths) logging.debug(lib_list) # Find the corresponding filename for Lib target type. if target_filename is not None: for name in lib_list: if name.endswith(target_filename): target_filename = name break else: for name in lib_list: if target_type in name: # TODO: check more exactly (e.g., multiple hits). target_filename = name if not target_filename: raise errors.ComponentLoadingError( "No file found for target type %s." % target_type) driver_id = self.LaunchMirrorDriver( ASysCtrlMsg.VTS_DRIVER_TYPE_HAL_CONVENTIONAL, "lib_shared", target_type, target_version, target_package=target_package, target_filename=target_filename, handler_name=handler_name, bits=bits) self._driver_id = driver_id #TODO: ListApis assumes only one lib is loaded at a time, need to # figure out a way to get the api_spec when we want to test # multiple libs together. found_api_spec = self._client.ListApis() if not found_api_spec: raise errors.ComponentLoadingError("No API found for %s" % target_type) if_spec_msg = CompSpecMsg.ComponentSpecificationMessage() text_format.Merge(found_api_spec, if_spec_msg) self._if_spec_msg = if_spec_msg
def _CreateMirrorObject(self, target_class, target_type, target_version, target_package=None, target_component_name=None, target_basepaths=_DEFAULT_TARGET_BASE_PATHS, handler_name=None, hw_binder_service_name=None, bits=64): """Initiates the driver for a HAL on the target device and creates a top level MirroObject for it. Also starts the callback server to listen for callback invocations. Args: target_class: string, the target class name (e.g., hal). target_type: string, the target type name (e.g., light, camera). target_version: float, the target component version (e.g., 1.0). target_package: string, the package name of a HIDL HAL. target_component_name: string, the name of a target component. target_basepaths: list of strings, the paths to look for target files in. Default is _DEFAULT_TARGET_BASE_PATHS. handler_name: string, the name of the handler. target_type is used by default. hw_binder_service_name: string, the name of a HW binder service. bits: integer, processor architecture indicator: 32 or 64. Raises: errors.ComponentLoadingError is raised when error occurs trying to create a MirrorObject. """ if bits not in [32, 64]: raise error.ComponentLoadingError("Invalid value for bits: %s" % bits) self._StartCallbackServer() self._client = vts_tcp_client.VtsTcpClient() self._client.Connect(command_port=self._host_command_port, callback_port=self._host_callback_port) if not handler_name: handler_name = target_type service_name = "vts_driver_%s" % handler_name target_filename = None if target_class == "hal_conventional" or target_class == "hal_legacy": # Get all the HALs available on the target. hal_list = self._client.ListHals(target_basepaths) if not hal_list: raise errors.ComponentLoadingError( "Could not find any HAL under path %s" % target_basepaths) logging.debug(hal_list) # Find the corresponding filename for HAL target type. for name in hal_list: if target_type in name: # TODO: check more exactly (e.g., multiple hits). target_filename = name if not target_filename: raise errors.ComponentLoadingError( "No file found for HAL target type %s." % target_type) # Check whether the requested binder service is already running. # if client.CheckDriverService(service_name=service_name): # raise errors.ComponentLoadingError("A driver for %s already exists" % # service_name) elif target_class == "hal_hidl": # TODO: either user the default hw-binder service or start a new # service (e.g., if an instrumented binary is used). pass # Launch the corresponding driver of the requested HAL on the target. logging.info("Init the driver service for %s", target_type) target_class_id = COMPONENT_CLASS_DICT[target_class.lower()] target_type_id = COMPONENT_TYPE_DICT[target_type.lower()] driver_type = { "hal_conventional": ASysCtrlMsg.VTS_DRIVER_TYPE_HAL_CONVENTIONAL, "hal_legacy": ASysCtrlMsg.VTS_DRIVER_TYPE_HAL_LEGACY, "hal_hidl": ASysCtrlMsg.VTS_DRIVER_TYPE_HAL_HIDL }.get(target_class) launched = self._client.LaunchDriverService( driver_type=driver_type, service_name=service_name, bits=bits, file_path=target_filename, target_class=target_class_id, target_type=target_type_id, target_version=target_version, target_package=target_package, target_component_name=target_component_name, hw_binder_service_name=hw_binder_service_name) if not launched: raise errors.ComponentLoadingError( "Failed to launch driver service %s from file path %s" % (target_type, target_filename)) # Create API spec message. found_api_spec = self._client.ListApis() if not found_api_spec: raise errors.ComponentLoadingError("No API found for %s" % service_name) logging.debug("Found %d APIs for %s:\n%s", len(found_api_spec), service_name, found_api_spec) if_spec_msg = CompSpecMsg.ComponentSpecificationMessage() text_format.Merge(found_api_spec, if_spec_msg) # Instantiate a MirrorObject and return it. hal_mirror = mirror_object.MirrorObject(self._client, if_spec_msg, self._callback_server) self._hal_level_mirrors[handler_name] = hal_mirror
def _CreateMirrorObject(self, target_class, target_type, target_version, target_basepaths=_DEFAULT_TARGET_BASE_PATHS, target_package="", target_filename=None, handler_name=None, bits=64): """Initiates the driver for a lib on the target device and creates a top level MirroObject for it. Args: target_class: string, the target class name (e.g., lib). target_type: string, the target type name (e.g., light, camera). target_version: float, the target component version (e.g., 1.0). target_basepaths: list of strings, the paths to look for target files in. Default is _DEFAULT_TARGET_BASE_PATHS. target_package: . separated string (e.g., a.b.c) to denote the package name of target component. target_filename: string, the target file name (e.g., libm.so). handler_name: string, the name of the handler. target_type is used by default. bits: integer, processor architecture indicator: 32 or 64. Raises: errors.ComponentLoadingError is raised when error occurs trying to create a MirrorObject. """ if bits not in [32, 64]: raise error.ComponentLoadingError("Invalid value for bits: %s" % bits) client = vts_tcp_client.VtsTcpClient() client.Connect(command_port=self._host_command_port) if not handler_name: handler_name = target_type service_name = "vts_driver_%s" % handler_name # Get all the libs available on the target. lib_list = client.ListHals(target_basepaths) if not lib_list: raise errors.ComponentLoadingError( "Could not find any lib under path %s" % target_basepaths) logging.debug(lib_list) # Find the corresponding filename for Lib target type. if target_filename is not None: for name in lib_list: if name.endswith(target_filename): target_filename = name break else: for name in lib_list: if target_type in name: # TODO: check more exactly (e.g., multiple hits). target_filename = name if not target_filename: raise errors.ComponentLoadingError( "No file found for target type %s." % target_type) # Check whether the requested binder service is already running. # if client.CheckDriverService(service_name=service_name): # raise errors.ComponentLoadingError("A driver for %s already exists" % # service_name) # Launch the corresponding driver of the requested Lib on the target. logging.info("Init the driver service for %s", target_type) target_class_id = hal_mirror.COMPONENT_CLASS_DICT[target_class.lower()] target_type_id = hal_mirror.COMPONENT_TYPE_DICT[target_type.lower()] launched = client.LaunchDriverService( driver_type=ASysCtrlMsg.VTS_DRIVER_TYPE_HAL_CONVENTIONAL, service_name=service_name, bits=bits, file_path=target_filename, target_class=target_class_id, target_type=target_type_id, target_version=target_version, target_package=target_package) if not launched: raise errors.ComponentLoadingError( "Failed to launch driver service %s from file path %s" % (target_type, target_filename)) # Create API spec message. found_api_spec = client.ListApis() if not found_api_spec: raise errors.ComponentLoadingError("No API found for %s" % service_name) logging.debug("Found %d APIs for %s:\n%s", len(found_api_spec), service_name, found_api_spec) if_spec_msg = CompSpecMsg.ComponentSpecificationMessage() text_format.Merge(found_api_spec, if_spec_msg) # Instantiate a MirrorObject and return it. lib_mirror = mirror_object.MirrorObject(client, if_spec_msg, None) self._lib_level_mirrors[handler_name] = lib_mirror