def GetAttribute(self, attribute_name): """Returns the Message. """ logging.debug("GetAttribute %s for %s", attribute_name, self._if_spec_msg) if self._if_spec_msg.attribute: for attribute in self._if_spec_msg.attribute: if attribute.name == attribute_name: func_msg = CompSpecMsg.FunctionSpecificationMessage() func_msg.name = attribute.name func_msg.return_type.type = attribute.type if func_msg.return_type.type == CompSpecMsg.TYPE_SCALAR: func_msg.return_type.scalar_type = attribute.scalar_type else: func_msg.return_type.predefined_type = attribute.predefined_type logging.info("GetAttribute attribute: %s", attribute) logging.info("GetAttribute request: %s", func_msg) return copy.copy(func_msg) if (self._if_spec_msg.interface and self._if_spec_msg.interface.attribute): for attribute in self._if_spec_msg.interface.attribute: if attribute.name == attribute_name: func_msg = CompSpecMsg.FunctionSpecificationMessage() func_msg.name = attribute.name func_msg.return_type.type = attribute.type if func_msg.return_type.type == CompSpecMsg.TYPE_SCALAR: func_msg.return_type.scalar_type = attribute.scalar_type else: func_msg.return_type.predefined_type = attribute.predefined_type logging.info("GetAttribute attribute: %s", attribute) logging.info("GetAttribute request: %s", func_msg) return copy.copy(func_msg) return None
def GetHidlCallbackInterface(self, interface_name, **kwargs): var_msg = CompSpecMsg.VariableSpecificationMessage() var_msg.name = interface_name var_msg.type = CompSpecMsg.TYPE_FUNCTION_POINTER var_msg.is_callback = True msg = self._if_spec_msg specification = self._client.ReadSpecification( interface_name, msg.component_class, msg.component_type, msg.component_type_version, msg.package) logging.info("specification: %s", specification) interface = getattr(specification, INTERFACE, None) apis = getattr(interface, API, []) for api in apis: function_pointer = None if api.name in kwargs: function_pointer = kwargs[api.name] else: def dummy(*args): """Dummy implementation for any callback function.""" logging.info( "Entering dummy implementation" " for callback function: %s", api.name) for arg_index in range(len(args)): logging.info("arg%s: %s", arg_index, args[arg_index]) function_pointer = dummy func_pt_msg = var_msg.function_pointer.add() func_pt_msg.function_name = api.name func_pt_msg.id = self.GetFunctionPointerID(function_pointer) return var_msg
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 GetApi(self, api_name): """Gets the ProtoBuf message for given api. Args: api_name: string, the name of the target function API. Returns: FunctionSpecificationMessage if found, None otherwise """ logging.debug("GetAPI %s for %s", api_name, self._if_spec_msg) # handle reserved methods first. if api_name == "notifySyspropsChanged": func_msg = CompSpecMsg.FunctionSpecificationMessage() func_msg.name = api_name return func_msg if isinstance(self._if_spec_msg, CompSpecMsg.ComponentSpecificationMessage): if len(self._if_spec_msg.interface.api) > 0: for api in self._if_spec_msg.interface.api: if api.name == api_name: return copy.copy(api) else: logging.error("unknown spec type %s", type(self._if_spec_msg)) sys.exit(1) return None
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 OpenConventionalHal(self, module_name=None): """Opens the target conventional HAL component. This is only needed for conventional HAL. Args: module_name: string, the name of a module to load. """ call_msg = CompSpecMsg.FunctionCallMessage() if self._hal_driver_id is not None: call_msg.hal_driver_id = self._hal_driver_id call_msg.component_class = CompSpecMsg.HAL_CONVENTIONAL call_msg.api.name = "#Open" if module_name: arg = call_msg.api.arg.add() arg.type = CompSpecMsg.TYPE_STRING arg.string_value.message = module_name call_msg.api.return_type.type == CompSpecMsg.TYPE_SCALAR call_msg.api.return_type.scalar_type = "int32_t" logging.debug("final msg %s", call_msg) result = self._client.CallApi(text_format.MessageToString(call_msg), self.__caller_uid) logging.debug(result) return result
def Convert(pb_spec, py_value): """Converts Python native data structure to VTS VariableSecificationMessage. Args: pb_spec: VariableSpecificationMessage which captures the specification of a target attribute. py_value: Python value provided by a test case. Returns: Converted VariableSpecificationMessage if found, None otherwise """ if not pb_spec: logging.error("py2pb.Convert: ProtoBuf spec is None", pb_spec) return None message = CompSpecMsg.VariableSpecificationMessage() message.name = pb_spec.name if isinstance(py_value, CompSpecMsg.VariableSpecificationMessage): message.CopyFrom(py_value) elif pb_spec.type == CompSpecMsg.TYPE_STRUCT: PyDict2PbStruct(message, pb_spec, py_value) elif pb_spec.type == CompSpecMsg.TYPE_ENUM: PyValue2PbEnum(message, pb_spec, py_value) elif pb_spec.type == CompSpecMsg.TYPE_SCALAR: PyValue2PbScalar(message, pb_spec, py_value) elif pb_spec.type == CompSpecMsg.TYPE_STRING: PyString2PbString(message, pb_spec, py_value) elif pb_spec.type == CompSpecMsg.TYPE_VECTOR: PyList2PbVector(message, pb_spec, py_value) else: logging.error("py2pb.Convert: unsupported type %s", pb_spec.type) sys.exit(-1) return message
def GetAttribute(self, arg): """RPC to VTS_AGENT_COMMAND_GET_ATTRIBUTE.""" self.SendCommand(SysMsg_pb2.VTS_AGENT_COMMAND_GET_ATTRIBUTE, arg=arg) resp = self.RecvResponse() resp_code = resp.response_code if (resp_code == SysMsg_pb2.SUCCESS): result = CompSpecMsg_pb2.FunctionSpecificationMessage() if resp.result == "error": raise errors.VtsTcpCommunicationError( "Get attribute request failed on target.") 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 result.return_type.type == CompSpecMsg_pb2.TYPE_SUBMODULE: logging.debug("returned a submodule spec") logging.debug("spec: %s", result.return_type_submodule_spec) return mirror_object.MirrorObject( self, result.return_type_submodule_spec, None) elif result.return_type.type == CompSpecMsg_pb2.TYPE_SCALAR: return getattr(result.return_type.scalar_value, result.return_type.scalar_type) return result logging.error("NOTICE - Likely a crash discovery!") logging.error("SysMsg_pb2.SUCCESS is %s", SysMsg_pb2.SUCCESS) raise errors.VtsTcpCommunicationError( "RPC Error, response code for %s is %s" % (arg, resp_code))
def RemoteCall(*args, **kwargs): """Dynamically calls a remote API and returns the result value.""" func_msg = self.GetApi(api_name) if not func_msg: raise MirrorObjectError("api %s unknown", func_msg) logging.info("remote call %s%s", api_name, args) if args: for arg_msg, value_msg in zip(func_msg.arg, args): logging.debug("arg msg %s", arg_msg) logging.debug("value %s", value_msg) if value_msg is not None: converted_msg = py2pb.Convert(arg_msg, value_msg) logging.debug("converted_message: %s", converted_msg) arg_msg.CopyFrom(converted_msg) else: # TODO: use kwargs for arg in func_msg.arg: # TODO: handle other if (arg.type == CompSpecMsg.TYPE_SCALAR and arg.scalar_type == "pointer"): arg.scalar_value.pointer = 0 logging.debug(func_msg) call_msg = CompSpecMsg.FunctionCallMessage() if self._if_spec_msg.component_class: call_msg.component_class = self._if_spec_msg.component_class call_msg.hal_driver_id = self._driver_id call_msg.api.CopyFrom(func_msg) logging.info("final msg %s", call_msg) results = self._client.CallApi( text_format.MessageToString(call_msg), self._caller_uid) if (isinstance(results, tuple) and len(results) == 2 and isinstance(results[1], dict) and "coverage" in results[1]): self._last_raw_code_coverage_data = results[1]["coverage"] results = results[0] if isinstance(results, list): # Non-HIDL HAL does not return list. # Translate TYPE_HIDL_INTERFACE to halMirror. for i, _ in enumerate(results): result = results[i] if (result and isinstance(result, CompSpecMsg.VariableSpecificationMessage) and result.type == CompSpecMsg.TYPE_HIDL_INTERFACE): if result.hidl_interface_id <= -1: results[i] = None driver_id = result.hidl_interface_id nested_interface_name = result.predefined_type.split("::")[-1] logging.debug("Nested interface name: %s", nested_interface_name) nested_interface = self.GetHalMirrorForInterface( nested_interface_name, driver_id) results[i] = nested_interface if len(results) == 1: # singe return result, return the value direcly. return results[0] return results
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 CallApi(self, arg, caller_uid=None): """RPC to CALL_API.""" self.SendCommand(SysMsg_pb2.CALL_API, arg=arg, caller_uid=caller_uid) resp = self.RecvResponse() resp_code = resp.response_code if (resp_code == SysMsg_pb2.SUCCESS): result = CompSpecMsg_pb2.FunctionSpecificationMessage() 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 result.return_type.type == CompSpecMsg_pb2.TYPE_SUBMODULE: logging.info("returned a submodule spec") logging.info("spec: %s", result.return_type_submodule_spec) return mirror_object.MirrorObject( self, result.return_type_submodule_spec, None) logging.info("result: %s", result.return_type_hidl) if len(result.return_type_hidl) == 1: result_value = self.GetPythonDataOfVariableSpecMsg( result.return_type_hidl[0]) elif len(result.return_type_hidl) > 1: result_value = [] for return_type_hidl in result.return_type_hidl: result_value.append( self.GetPythonDataOfVariableSpecMsg(return_type_hidl)) else: # For non-HIDL return value if hasattr(result, "return_type"): result_value = result else: result_value = None if hasattr(result, "raw_coverage_data"): return result_value, {"coverage": result.raw_coverage_data} else: return result_value logging.error("NOTICE - Likely a crash discovery!") logging.error("SysMsg_pb2.SUCCESS is %s", SysMsg_pb2.SUCCESS) raise errors.VtsTcpCommunicationError( "RPC Error, response code for %s is %s" % (arg, resp_code))
def GetHidlCallbackInterface(self, interface_name, **kwargs): """Gets the ProtoBuf message for a callback interface based on args. Args: interface_name: string, the callback interface name. **kwargs: a dict for the arg name and value pairs Returns: VariableSpecificationMessage that contains the callback interface description. """ var_msg = CompSpecMsg.VariableSpecificationMessage() var_msg.name = interface_name var_msg.type = CompSpecMsg.TYPE_FUNCTION_POINTER var_msg.is_callback = True msg = self._if_spec_msg specification = self._client.ReadSpecification( interface_name, msg.component_class, msg.component_type, msg.component_type_version_major, msg.component_type_version_minor, msg.package) logging.debug("specification: %s", specification) interface = getattr(specification, INTERFACE, None) apis = getattr(interface, API, []) for api in apis: function_pointer = None if api.name in kwargs: function_pointer = kwargs[api.name] else: def dummy(*args): """Dummy implementation for any callback function.""" logging.debug( "Entering dummy implementation" " for callback function: %s", api.name) for arg_index in range(len(args)): logging.debug("arg%s: %s", arg_index, args[arg_index]) function_pointer = dummy func_pt_msg = var_msg.function_pointer.add() func_pt_msg.function_name = api.name func_pt_msg.id = self.GetCallbackFunctionID(function_pointer) return var_msg
def testHidlHandleArgument(self): """Test calling APIs in dumpstate HAL server. Host side specifies a handle object in resource_manager, ans pass it to dumpstate HAL server to write debug message into it. Host side then reads part of the debug message. """ # Prepare a VariableSpecificationMessage to specify the handle object # that will be passed into the HAL service. var_msg = CompSpecMsg.VariableSpecificationMessage() var_msg.type = CompSpecMsg.TYPE_HANDLE var_msg.handle_value.handle_id = self._writer.handleId self._dumpstate.dumpstateBoard(var_msg) # Read 1000 bytes to retrieve part of debug message. debug_msg = self._reader.readFile(1000) logging.info("Below are part of result from dumpstate: ") logging.info(debug_msg) asserts.assertNotEqual(debug_msg, "")
def setUp(self): # Initialize a FMQ on the target-side driver. self._sync_client = self.dut.resource.InitFmq( data_type="uint16_t", sync=True, queue_size=self.MAX_NUM_MSG, blocking=True, client=self.dut.hal.GetTcpClient("tests_msgq")) asserts.assertNotEqual(self._sync_client.queueId, -1) # Prepare a VariableSpecificationMessage to specify the FMQ that will be # passed into the HAL service. var_msg = CompSpecMsg.VariableSpecificationMessage() var_msg.type = CompSpecMsg.TYPE_FMQ_SYNC fmq_val = var_msg.fmq_value.add() fmq_val.fmq_id = self._sync_client.queueId fmq_val.scalar_type = "uint16_t" fmq_val.type = CompSpecMsg.TYPE_SCALAR # Call API in the HAL server. sync_init_result = self._tests_msgq.configureFmqSyncReadWrite(var_msg) asserts.assertTrue( sync_init_result, "Hal should configure a synchronized queue without error.") # Initialize an unsynchronized queue on the server. [success, self._unsync_client1] = self._tests_msgq.getFmqUnsyncWrite(True) asserts.assertTrue( success, "Hal should configure an unsynchronized queue without error.") # An unsynchronized queue is registered successfully on the target driver. asserts.assertNotEqual(self._unsync_client1, None) asserts.assertNotEqual(self._unsync_client1.queueId, -1) # Register another reader. self._unsync_client2 = self.dut.resource.InitFmq( existing_queue=self._unsync_client1, client=self.dut.hal.GetTcpClient("tests_msgq")) asserts.assertNotEqual(self._unsync_client2.queueId, -1)
def OpenConventionalHal(self, module_name=None): """Opens the target conventional HAL component. This is only needed for conventional HAL. Args: module_name: string, the name of a module to load. """ func_msg = CompSpecMsg.FunctionSpecificationMessage() func_msg.name = "#Open" logging.debug("remote call %s", func_msg.name) if module_name: arg = func_msg.arg.add() arg.type = CompSpecMsg.TYPE_STRING arg.string_value.message = module_name func_msg.return_type.type == CompSpecMsg.TYPE_SCALAR func_msg.return_type.scalar_type = "int32_t" logging.debug("final msg %s", func_msg) result = self._client.CallApi(text_format.MessageToString(func_msg), self.__caller_uid) logging.debug(result) return result
def RemoteCall(*args, **kwargs): """Dynamically calls a remote API and returns the result value.""" func_msg = self.GetApi(api_name) if not func_msg: raise MirrorObjectError("api %s unknown", func_msg) logging.debug("remote call %s.%s", self._parent_path, api_name) logging.info("remote call %s%s", api_name, args) if args: for arg_msg, value_msg in zip(func_msg.arg, args): logging.debug("arg msg %s", arg_msg) logging.debug("value %s", value_msg) if value_msg is not None: self.ArgToPb(arg_msg, value_msg) logging.debug("final msg %s", func_msg) else: # TODO: use kwargs for arg in func_msg.arg: # TODO: handle other if (arg.type == CompSpecMsg.TYPE_SCALAR and arg.scalar_type == "pointer"): arg.scalar_value.pointer = 0 logging.debug(func_msg) if self._parent_path: func_msg.parent_path = self._parent_path call_msg = CompSpecMsg.FunctionCallMessage() if isinstance(self._if_spec_msg, CompSpecMsg.ComponentSpecificationMessage): if self._if_spec_msg.component_class: logging.info("component_class %s", self._if_spec_msg.component_class) call_msg.component_class = self._if_spec_msg.component_class if self._if_spec_msg.component_class == CompSpecMsg.HAL_CONVENTIONAL_SUBMODULE: submodule_name = self._if_spec_msg.original_data_structure_name if submodule_name.endswith("*"): submodule_name = submodule_name[:-1] func_msg.submodule_name = submodule_name if self._hal_driver_id is not None: call_msg.hal_driver_id = self._hal_driver_id call_msg.api.CopyFrom(func_msg) result = self._client.CallApi( text_format.MessageToString(call_msg), self.__caller_uid) logging.debug(result) if (isinstance(result, tuple) and len(result) == 2 and isinstance(result[1], dict) and "coverage" in result[1]): self._last_raw_code_coverage_data = result[1]["coverage"] result = result[0] if (result and isinstance(result, CompSpecMsg.VariableSpecificationMessage) and result.type == CompSpecMsg.TYPE_HIDL_INTERFACE): if result.hidl_interface_id <= -1: return None hal_driver_id = result.hidl_interface_id nested_interface_name = result.predefined_type.split("::")[-1] logging.debug("Nested interface name: %s", nested_interface_name) nested_interface = self.GetHidlNestedInterface( nested_interface_name, hal_driver_id) return nested_interface return result
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
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 RemoteCall(*args, **kwargs): """Dynamically calls a remote API and returns the result value.""" func_msg = self.GetApi(api_name) if not func_msg: raise MirrorObjectError("api %s unknown", func_msg) logging.debug("remote call %s%s", api_name, args) if args: for arg_msg, value_msg in zip(func_msg.arg, args): logging.debug("arg msg %s", arg_msg) logging.debug("value %s", value_msg) if value_msg is not None: converted_msg = py2pb.Convert(arg_msg, value_msg) if converted_msg is None: raise MirrorObjectError("Failed to convert arg %s", value_msg) logging.debug("converted_message: %s", converted_msg) arg_msg.CopyFrom(converted_msg) else: # TODO: use kwargs for arg in func_msg.arg: # TODO: handle other if (arg.type == CompSpecMsg.TYPE_SCALAR and arg.scalar_type == "pointer"): arg.scalar_value.pointer = 0 logging.debug(func_msg) call_msg = CompSpecMsg.FunctionCallMessage() if self._if_spec_msg.component_class: call_msg.component_class = self._if_spec_msg.component_class call_msg.hal_driver_id = self._driver_id call_msg.api.CopyFrom(func_msg) logging.debug("final msg %s", call_msg) results = self._client.CallApi( text_format.MessageToString(call_msg), self._caller_uid) if (isinstance(results, tuple) and len(results) == 2 and isinstance(results[1], dict) and "coverage" in results[1]): self._last_raw_code_coverage_data = results[1]["coverage"] results = results[0] if isinstance(results, list): # Non-HIDL HAL does not return list. # Translate TYPE_HIDL_INTERFACE to halMirror. for i, _ in enumerate(results): result = results[i] if (not result or not isinstance( result, CompSpecMsg.VariableSpecificationMessage)): # no need to process the return values. continue if result.type == CompSpecMsg.TYPE_HIDL_INTERFACE: if result.hidl_interface_id <= -1: results[i] = None driver_id = result.hidl_interface_id nested_interface_name = \ result.predefined_type.split("::")[-1] logging.debug("Nested interface name: %s", nested_interface_name) nested_interface = self.GetHalMirrorForInterface( nested_interface_name, driver_id) results[i] = nested_interface elif (result.type == CompSpecMsg.TYPE_FMQ_SYNC or result.type == CompSpecMsg.TYPE_FMQ_UNSYNC): if (result.fmq_value[0].fmq_id == -1): logging.error("Invalid new queue_id.") results[i] = None else: # Retrieve type of data in this FMQ. data_type = None # For scalar, read scalar_type field. if result.fmq_value[0].type == \ CompSpecMsg.TYPE_SCALAR: data_type = result.fmq_value[0].scalar_type # For enum, struct, and union, read predefined_type # field. elif (result.fmq_value[0].type == CompSpecMsg.TYPE_ENUM or result.fmq_value[0].type == CompSpecMsg.TYPE_STRUCT or result.fmq_value[0].type == CompSpecMsg.TYPE_UNION): data_type = result.fmq_value[0].predefined_type # Encounter an unknown type in FMQ. if data_type == None: logging.error( "Unknown type %d in the new FMQ.", result.fmq_value[0].type) results[i] = None continue sync = result.type == CompSpecMsg.TYPE_FMQ_SYNC fmq_mirror = resource_mirror.ResourceFmqMirror( data_type, sync, self._client, result.fmq_value[0].fmq_id) results[i] = fmq_mirror elif result.type == CompSpecMsg.TYPE_HIDL_MEMORY: if result.hidl_memory_value.mem_id == -1: logging.error("Invalid new mem_id.") results[i] = None else: mem_mirror = resource_mirror.ResourceHidlMemoryMirror( self._client, result.hidl_memory_value.mem_id) results[i] = mem_mirror elif result.type == CompSpecMsg.TYPE_HANDLE: if result.handle_value.handle_id == -1: logging.error("Invalid new handle_id.") results[i] = None else: handle_mirror = resource_mirror.ResourceHidlHandleMirror( self._client, result.handle_value.handle_id) results[i] = handle_mirror if len(results) == 1: # single return result, return the value directly. return results[0] return results
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