mirror of
https://github.com/ARM-software/workload-automation.git
synced 2025-01-18 20:11:20 +00:00
AndroidWorkload: Modified workload to properly check for an apks abi
Previously when retrieving apks only it's name would be used to choose an apk. Now the native code reported by the apk is used to determine the correct version to run for the specific device. It tries to match the primary abi of device with native code before falling back to using a compatible apk. When using the check_abi parameter it no longer relies on naming convention and only allows apks with native code supporting a devices primary abi to be used. Updated the relevant documentation.
This commit is contained in:
parent
f467f6f991
commit
a8a8d21de6
@ -18,10 +18,10 @@ All ApkWorkloads have parameters that affect the way in which APK files are reso
|
||||
|
||||
.. confval:: check_abi
|
||||
|
||||
If this setting is enabled WA's resource resolvers will look for the devices ABI within the file name
|
||||
e.g. ``calculator_arm65.apk``. By default this setting is disabled since most apks will work across all
|
||||
If this setting is enabled WA's resource resolvers will look for the devices ABI with any native
|
||||
code present in the apk. By default this setting is disabled since most apks will work across all
|
||||
devices. You may wish to enable this feature when working with devices that support multiple ABI's (like
|
||||
64-bit devices that can run 32-bit APK files) and are specifically trying to test one or the other.
|
||||
64-bit devices that can run 32-bit APK files) and are specifically trying to test one or the other.
|
||||
|
||||
.. confval:: force_install
|
||||
|
||||
|
@ -30,7 +30,7 @@ from wlauto.common.resources import Executable
|
||||
from wlauto.core.resource import NO_ONE
|
||||
from wlauto.common.linux.device import BaseLinuxDevice, PsEntry
|
||||
from wlauto.exceptions import DeviceError, WorkerThreadError, TimeoutError, DeviceNotRespondingError
|
||||
from wlauto.utils.misc import convert_new_lines
|
||||
from wlauto.utils.misc import convert_new_lines, ABI_MAP
|
||||
from wlauto.utils.types import boolean, regex
|
||||
from wlauto.utils.android import (adb_shell, adb_background_shell, adb_list_devices,
|
||||
adb_command, AndroidProperties, ANDROID_VERSION_MAP)
|
||||
@ -108,7 +108,11 @@ class AndroidDevice(BaseLinuxDevice): # pylint: disable=W0223
|
||||
|
||||
@property
|
||||
def abi(self):
|
||||
return self.getprop()['ro.product.cpu.abi'].split('-')[0]
|
||||
val = self.getprop()['ro.product.cpu.abi'].split('-')[0]
|
||||
for abi, architectures in ABI_MAP.iteritems():
|
||||
if val in architectures:
|
||||
return abi
|
||||
return val
|
||||
|
||||
@property
|
||||
def supported_eabi(self):
|
||||
@ -120,7 +124,18 @@ class AndroidDevice(BaseLinuxDevice): # pylint: disable=W0223
|
||||
for eabi in props['ro.product.cpu.abilist'].split(','):
|
||||
if eabi not in result:
|
||||
result.append(eabi)
|
||||
return result
|
||||
|
||||
mapped_result = []
|
||||
for supported_eabi in result:
|
||||
for abi, architectures in ABI_MAP.iteritems():
|
||||
found = False
|
||||
if supported_eabi in architectures and abi not in mapped_result:
|
||||
mapped_result.append(abi)
|
||||
found = True
|
||||
break
|
||||
if not found and supported_eabi not in mapped_result:
|
||||
mapped_result.append(supported_eabi)
|
||||
return mapped_result
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
super(AndroidDevice, self).__init__(**kwargs)
|
||||
|
@ -200,8 +200,9 @@ class ApkWorkload(Workload):
|
||||
self.apk_version = None
|
||||
self.logcat_log = None
|
||||
self.exact_apk_version = None
|
||||
self.check_abi = kwargs.get('check_abi')
|
||||
|
||||
def setup(self, context):
|
||||
def setup(self, context): # pylint: disable=too-many-branches
|
||||
Workload.setup(self, context)
|
||||
|
||||
# Get target version
|
||||
@ -213,9 +214,25 @@ class ApkWorkload(Workload):
|
||||
# Get host version
|
||||
self.apk_file = context.resolver.get(ApkFile(self, self.device.abi),
|
||||
version=getattr(self, 'version', None),
|
||||
check_abi=getattr(self, 'check_abi', False),
|
||||
variant_name=getattr(self, 'variant_name', None),
|
||||
strict=False)
|
||||
|
||||
# Get target abi
|
||||
target_abi = self.device.get_installed_package_abi(self.package)
|
||||
if target_abi:
|
||||
self.logger.debug("Found apk with primary abi '{}' on target device".format(target_abi))
|
||||
|
||||
# Get host version, primary abi is first, and then try to find supported.
|
||||
for abi in self.device.supported_eabi:
|
||||
self.apk_file = context.resolver.get(ApkFile(self, abi),
|
||||
version=getattr(self, 'version', None),
|
||||
variant_name=getattr(self, 'variant_name', None),
|
||||
strict=False)
|
||||
|
||||
# Stop if apk found, or if check_abi is set only look for primary abi.
|
||||
if self.apk_file or self.check_abi:
|
||||
break
|
||||
|
||||
host_version = None
|
||||
if self.apk_file is not None:
|
||||
host_version = ApkInfo(self.apk_file).version_name
|
||||
@ -233,6 +250,12 @@ class ApkWorkload(Workload):
|
||||
msg = "APK version '{}' not found on the host '{}' or target '{}'"
|
||||
raise ResourceError(msg.format(self.exact_apk_version, host_version, target_version))
|
||||
|
||||
# Error if check_abi and suitable apk not found on host and incorrect version on device
|
||||
if self.check_abi and host_version is None:
|
||||
if target_abi != self.device.abi:
|
||||
msg = "APK abi '{}' not found on the host and target is '{}'"
|
||||
raise ResourceError(msg.format(self.device.abi, target_abi))
|
||||
|
||||
# Ensure the apk is setup on the device
|
||||
if self.force_install:
|
||||
self.force_install_apk(context, host_version)
|
||||
|
@ -112,19 +112,13 @@ class PackageApkGetter(PackageFileGetter):
|
||||
extension = 'apk'
|
||||
|
||||
description = """
|
||||
Uses the same dependency resolution mechanism as ``PackageFileGetter`` with one addition.
|
||||
If an ABI is specified in the resource request, then the getter will try to locate the file in
|
||||
the ABI-specific folder in the form ``<root>/apk/<abi>/<apk_name>``. Where ``root`` is the base
|
||||
resource location e.g. ``~/.workload_automation/dependencies/<extension_name>`` and ``<abi>``
|
||||
is the ABI for which the APK has been compiled, as returned by ``resource.platform``.
|
||||
Uses the same dependency resolution mechanism as ``PackageFileGetter``.
|
||||
"""
|
||||
|
||||
def get(self, resource, **kwargs):
|
||||
resource_dir = os.path.dirname(sys.modules[resource.owner.__module__].__file__)
|
||||
version = kwargs.get('version')
|
||||
variant = kwargs.get('variant_name')
|
||||
if kwargs.get('check_abi', False):
|
||||
resource_dir = os.path.join(resource_dir, self.extension, resource.platform)
|
||||
return get_from_location_by_extension(resource, resource_dir, self.extension, version, variant=variant)
|
||||
|
||||
|
||||
@ -146,19 +140,13 @@ class EnvironmentApkGetter(EnvironmentFileGetter):
|
||||
extension = 'apk'
|
||||
|
||||
description = """
|
||||
Uses the same dependency resolution mechanism as ``EnvironmentFileGetter`` with one addition.
|
||||
If an ABI is specified in the resource request, then the getter will try to locate the file in
|
||||
the ABI-specific folder in the form ``<root>/apk/<abi>/<apk_name>``. Where ``root`` is the base
|
||||
resource location e.g. ``~/.workload_automation/dependencies/<extension_name>`` and ``<abi>``
|
||||
is the ABI for which the APK has been compiled, as returned by ``resource.platform``.
|
||||
Uses the same dependency resolution mechanism as ``EnvironmentFileGetter``.
|
||||
"""
|
||||
|
||||
def get(self, resource, **kwargs):
|
||||
resource_dir = resource.owner.dependencies_directory
|
||||
version = kwargs.get('version')
|
||||
variant = kwargs.get('variant_name')
|
||||
if kwargs.get('check_abi', False):
|
||||
resource_dir = os.path.join(resource_dir, self.extension, resource.platform)
|
||||
return get_from_location_by_extension(resource, resource_dir, self.extension, version, variant=variant)
|
||||
|
||||
|
||||
@ -478,8 +466,6 @@ class RemoteFilerGetter(ResourceGetter):
|
||||
if resource.owner:
|
||||
remote_path = os.path.join(self.remote_path, resource.owner.name)
|
||||
local_path = os.path.join(settings.environment_root, '__filer', resource.owner.dependencies_directory)
|
||||
if resource.name == 'apk' and kwargs.get('check_abi', False):
|
||||
local_path = os.path.join(local_path, 'apk', resource.platform)
|
||||
message = 'resource={}, version={}, remote_path={}, local_path={}'
|
||||
self.logger.debug(message.format(resource, version, remote_path, local_path))
|
||||
return self.try_get_resource(resource, version, remote_path, local_path)
|
||||
@ -574,6 +560,8 @@ def get_from_list_by_extension(resource, filelist, extension, version=None, vari
|
||||
filelist = [ff for ff in filelist if version.lower() in ApkInfo(ff).version_name.lower()]
|
||||
else:
|
||||
filelist = [ff for ff in filelist if version.lower() in os.path.basename(ff).lower()]
|
||||
if extension == 'apk':
|
||||
filelist = [ff for ff in filelist if not ApkInfo(ff).native_code or resource.platform in ApkInfo(ff).native_code]
|
||||
if len(filelist) == 1:
|
||||
return filelist[0]
|
||||
elif not filelist:
|
||||
|
Loading…
x
Reference in New Issue
Block a user