# # Copyright (C) 2017 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 logging from vts.runners.host import const from vts.runners.host import keys from vts.utils.python.common import vintf_utils def FindHalDescription(hal_desc, hal_package_name): """Find a HAL description whose name is hal_package_name from hal_desc.""" for hal_full_name in hal_desc: if hal_desc[hal_full_name].hal_name == hal_package_name: return hal_desc[hal_full_name] return None def IsHalRegisteredInVintfXml(hal, vintf_xml, bitness): """Checks whether a HAL is registered in a VINTF XML. If the given hal is an earlier minor version of what is specified in vintf_xml, it returns True. Args: hal: string, the full name of a HAL (e.g., package@version) vintf_xml: string, the VINTF XML content. bitness, string, currently tested ABI bitness (e.g., 32 or 64). Returns: True if found or vintf_xml is malformed, False otherwise. """ result = True if "@" not in hal: logging.error("HAL full name is invalid, %s", hal) return False hal_package, hal_version = hal.split("@") logging.info("HAL package, version = %s, %s", hal_package, hal_version) hal_version_major, hal_version_minor = vintf_utils.ParseHalVersion( hal_version) hwbinder_hals, passthrough_hals = vintf_utils.GetHalDescriptions( vintf_xml) hwbinder_hal_desc = FindHalDescription(hwbinder_hals, hal_package) passthrough_hal_desc = FindHalDescription(passthrough_hals, hal_package) if not hwbinder_hals or not passthrough_hals: logging.error("can't check precondition due to a " "VINTF XML format error.") # Assume it's satisfied. return True elif (hwbinder_hal_desc is None and passthrough_hal_desc is None): logging.warn( "The required HAL %s not found in VINTF XML.", hal) return False elif (hwbinder_hal_desc is None and passthrough_hal_desc is not None): if bitness: if (bitness not in passthrough_hal_desc.hal_archs): logging.warn( "The required feature %s found as a " "passthrough HAL but the client bitness %s " "unsupported", hal, bitness) result = False hal_desc = passthrough_hal_desc else: hal_desc = hwbinder_hal_desc logging.info( "The feature %s found in VINTF XML", hal) found_version_major = hal_desc.hal_version_major found_version_minor = hal_desc.hal_version_minor if (hal_version_major != found_version_major or hal_version_minor > found_version_minor): logging.warn( "The found HAL version %s@%s is not relevant for %s", found_version_major, found_version_minor, hal_version) result = False return result def CanRunHidlHalTest(test_instance, dut, shell=None): """Checks HAL precondition of a test instance. Args: test_instance: the test instance which inherits BaseTestClass. dut: the AndroidDevice under test. shell: the ShellMirrorObject to execute command on the device. If not specified, the function creates one from dut. Returns: True if the precondition is satisfied; False otherwise. """ if shell is None: dut.shell.InvokeTerminal("check_hal_preconditions") shell = dut.shell.check_hal_preconditions opt_params = [ keys.ConfigKeys.IKEY_ABI_BITNESS, keys.ConfigKeys.IKEY_PRECONDITION_HWBINDER_SERVICE, keys.ConfigKeys.IKEY_PRECONDITION_FEATURE, keys.ConfigKeys.IKEY_PRECONDITION_FILE_PATH_PREFIX, keys.ConfigKeys.IKEY_PRECONDITION_LSHAL, keys.ConfigKeys.IKEY_PRECONDITION_VINTF, ] test_instance.getUserParams(opt_param_names=opt_params) hwbinder_service_name = str(getattr(test_instance, keys.ConfigKeys.IKEY_PRECONDITION_HWBINDER_SERVICE, "")) if hwbinder_service_name: if not hwbinder_service_name.startswith("android.hardware."): logging.error("The given hwbinder service name %s is invalid.", hwbinder_service_name) else: cmd_results = shell.Execute("ps -A") hwbinder_service_name += "@" if (any(cmd_results[const.EXIT_CODE]) or hwbinder_service_name not in cmd_results[const.STDOUT][0]): logging.warn("The required hwbinder service %s not found.", hwbinder_service_name) return False feature = str(getattr(test_instance, keys.ConfigKeys.IKEY_PRECONDITION_FEATURE, "")) if feature: if not feature.startswith("android.hardware."): logging.error( "The given feature name %s is invalid for HIDL HAL.", feature) else: cmd_results = shell.Execute("pm list features") if (any(cmd_results[const.EXIT_CODE]) or feature not in cmd_results[const.STDOUT][0]): logging.warn("The required feature %s not found.", feature) return False file_path_prefix = str(getattr(test_instance, keys.ConfigKeys.IKEY_PRECONDITION_FILE_PATH_PREFIX, "")) if file_path_prefix: cmd_results = shell.Execute("ls %s*" % file_path_prefix) if any(cmd_results[const.EXIT_CODE]): logging.warn("The required file (prefix: %s) not found.", file_path_prefix) return False hal = str(getattr(test_instance, keys.ConfigKeys.IKEY_PRECONDITION_VINTF, "")) vintf_xml = None if hal: use_lshal = False vintf_xml = dut.getVintfXml(use_lshal=use_lshal) logging.debug("precondition-vintf used to retrieve VINTF xml.") else: use_lshal = True hal = str(getattr(test_instance, keys.ConfigKeys.IKEY_PRECONDITION_LSHAL, "")) if hal: vintf_xml = dut.getVintfXml(use_lshal=use_lshal) logging.debug("precondition-lshal used to retrieve VINTF xml.") if vintf_xml: result = IsHalRegisteredInVintfXml(hal, vintf_xml, test_instance.abi_bitness) if not result and use_lshal: # this is for when a test is configured to use the runtime HAL # service availability (the default mode for HIDL tests). # if a HAL is in vendor/manifest.xml, test is supposed to fail # even though a respective HIDL HAL service is not running. vintf_xml = dut.getVintfXml(use_lshal=False) return IsHalRegisteredInVintfXml(hal, vintf_xml, test_instance.abi_bitness) return result return True