214 lines
8.1 KiB
Python
214 lines
8.1 KiB
Python
#
|
|
# Copyright (C) 2016 The Android Open Source Project
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
# you may not use this file except in compliance with the License.
|
|
# You may obtain a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
# See the License for the specific language governing permissions and
|
|
# limitations under the License.
|
|
#
|
|
|
|
import copy
|
|
import logging
|
|
import random
|
|
import sys
|
|
|
|
from google.protobuf import text_format
|
|
|
|
from vts.proto import AndroidSystemControlMessage_pb2 as ASysCtrlMsg
|
|
from vts.proto import ComponentSpecificationMessage_pb2 as CompSpecMsg
|
|
from vts.utils.python.fuzzer import FuzzerUtils
|
|
from vts.utils.python.mirror import native_entity_mirror
|
|
from vts.utils.python.mirror import py2pb
|
|
|
|
_DEFAULT_TARGET_BASE_PATHS = ["/system/lib64/hw"]
|
|
_DEFAULT_HWBINDER_SERVICE = "default"
|
|
|
|
INTERFACE = "interface"
|
|
API = "api"
|
|
|
|
|
|
class MirrorObjectError(Exception):
|
|
"""Raised when there is a general error in manipulating a mirror object."""
|
|
pass
|
|
|
|
|
|
class HalMirror(native_entity_mirror.NativeEntityMirror):
|
|
"""The class that acts as the mirror to an Android device's HAL layer.
|
|
|
|
This class exists on the host and can be used to communicate to a
|
|
particular HIDL HAL on the target side.
|
|
|
|
Attributes:
|
|
_callback_server: the instance of a callback server.
|
|
"""
|
|
|
|
def __init__(self,
|
|
client,
|
|
callback_server,
|
|
hal_driver_id=None,
|
|
if_spec_message=None,
|
|
caller_uid=None):
|
|
super(HalMirror, self).__init__(client, hal_driver_id, if_spec_message,
|
|
caller_uid)
|
|
self._callback_server = callback_server
|
|
|
|
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 GetCallbackFunctionID(self, function_pointer):
|
|
"""Gets registsred callback function id for the given function_pointer.
|
|
|
|
Args:
|
|
function_pointer: the callback function pointer.
|
|
|
|
Returns:
|
|
Id for the call back function registered with callback server.
|
|
"""
|
|
if self._callback_server:
|
|
id = self._callback_server.GetCallbackId(function_pointer)
|
|
if id is None:
|
|
id = self._callback_server.RegisterCallback(function_pointer)
|
|
return str(id)
|
|
else:
|
|
raise MirrorObjectError("callback server is not started.")
|
|
|
|
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 stub(*args):
|
|
"""Stub implementation for any callback function."""
|
|
logging.debug(
|
|
"Entering stub 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 = stub
|
|
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 GetHidlTypeInterface(self, interface_name):
|
|
"""Gets a HalMirror for HIDL HAL types specification.
|
|
|
|
Args:
|
|
interface_name: string, the name of a target interface to read.
|
|
"""
|
|
return self.GetHalMirrorForInterface(interface_name)
|
|
|
|
def GetHalMirrorForInterface(self, interface_name, driver_id=None):
|
|
"""Gets a HalMirror for a HIDL HAL interface.
|
|
|
|
Args:
|
|
interface_name: string, the name of a target interface to read.
|
|
driver_id: int, driver is of the corresponding HIDL HAL interface.
|
|
|
|
Returns:
|
|
a host-side mirror of a HIDL HAL interface.
|
|
"""
|
|
if not self._if_spec_msg:
|
|
raise MirrorObjectError("specification is not loaded")
|
|
msg = self._if_spec_msg
|
|
found_api_spec = self._client.ReadSpecification(
|
|
interface_name,
|
|
msg.component_class,
|
|
msg.component_type,
|
|
msg.component_type_version_major,
|
|
msg.component_type_version_minor,
|
|
msg.package,
|
|
recursive=True)
|
|
|
|
logging.debug("found_api_spec %s", found_api_spec)
|
|
if not driver_id:
|
|
driver_id = self._driver_id
|
|
# Instantiate a MirrorObject and return it.
|
|
return HalMirror(self._client, self._callback_server, driver_id,
|
|
found_api_spec)
|