mirror of
https://github.com/ARM-software/workload-automation.git
synced 2025-04-15 07:10:56 +01:00
Merge pull request #190 from jimboatarm/upstream-apk-check
Apk version check
This commit is contained in:
commit
662033399f
@ -349,18 +349,24 @@ class AndroidDevice(BaseLinuxDevice): # pylint: disable=W0223
|
|||||||
timeout=self.default_timeout)
|
timeout=self.default_timeout)
|
||||||
return bool(int(output))
|
return bool(int(output))
|
||||||
|
|
||||||
def install(self, filepath, timeout=default_timeout, with_name=None): # pylint: disable=W0221
|
def install(self, filepath, timeout=default_timeout, with_name=None, replace=False): # pylint: disable=W0221
|
||||||
ext = os.path.splitext(filepath)[1].lower()
|
ext = os.path.splitext(filepath)[1].lower()
|
||||||
if ext == '.apk':
|
if ext == '.apk':
|
||||||
return self.install_apk(filepath, timeout)
|
return self.install_apk(filepath, timeout, replace)
|
||||||
else:
|
else:
|
||||||
return self.install_executable(filepath, with_name)
|
return self.install_executable(filepath, with_name)
|
||||||
|
|
||||||
def install_apk(self, filepath, timeout=default_timeout): # pylint: disable=W0221
|
def install_apk(self, filepath, timeout=default_timeout, replace=False): # pylint: disable=W0221
|
||||||
self._check_ready()
|
self._check_ready()
|
||||||
ext = os.path.splitext(filepath)[1].lower()
|
ext = os.path.splitext(filepath)[1].lower()
|
||||||
if ext == '.apk':
|
if ext == '.apk':
|
||||||
return adb_command(self.adb_name, "install '{}'".format(filepath), timeout=timeout)
|
flags = []
|
||||||
|
if replace:
|
||||||
|
flags.append('-r') # Replace existing APK
|
||||||
|
if self.get_sdk_version() >= 23:
|
||||||
|
flags.append('-g') # Grant all runtime permissions
|
||||||
|
self.logger.debug("Replace APK = {}, ADB flags = '{}'".format(replace, ' '.join(flags)))
|
||||||
|
return adb_command(self.adb_name, "install {} '{}'".format(' '.join(flags), filepath), timeout=timeout)
|
||||||
else:
|
else:
|
||||||
raise DeviceError('Can\'t install {}: unsupported format.'.format(filepath))
|
raise DeviceError('Can\'t install {}: unsupported format.'.format(filepath))
|
||||||
|
|
||||||
|
@ -34,3 +34,10 @@ class JarFile(FileResource):
|
|||||||
class ApkFile(FileResource):
|
class ApkFile(FileResource):
|
||||||
|
|
||||||
name = 'apk'
|
name = 'apk'
|
||||||
|
|
||||||
|
def __init__(self, owner, platform=None):
|
||||||
|
super(ApkFile, self).__init__(owner)
|
||||||
|
self.platform = platform
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return '<{}\'s {} APK>'.format(self.owner, self.platform)
|
||||||
|
@ -20,6 +20,7 @@ import time
|
|||||||
from wlauto.core.extension import Parameter
|
from wlauto.core.extension import Parameter
|
||||||
from wlauto.core.workload import Workload
|
from wlauto.core.workload import Workload
|
||||||
from wlauto.core.resource import NO_ONE
|
from wlauto.core.resource import NO_ONE
|
||||||
|
from wlauto.common.android.resources import ApkFile
|
||||||
from wlauto.common.resources import ExtensionAsset, Executable
|
from wlauto.common.resources import ExtensionAsset, Executable
|
||||||
from wlauto.exceptions import WorkloadError, ResourceError, ConfigError
|
from wlauto.exceptions import WorkloadError, ResourceError, ConfigError
|
||||||
from wlauto.utils.android import ApkInfo, ANDROID_NORMAL_PERMISSIONS
|
from wlauto.utils.android import ApkInfo, ANDROID_NORMAL_PERMISSIONS
|
||||||
@ -155,11 +156,16 @@ class ApkWorkload(Workload):
|
|||||||
'''),
|
'''),
|
||||||
Parameter('force_install', kind=boolean, default=False,
|
Parameter('force_install', kind=boolean, default=False,
|
||||||
description='''
|
description='''
|
||||||
Always re-install the APK, even if matching version is found
|
Always re-install the APK, even if matching version is found already installed
|
||||||
on already installed on the device.
|
on the device. Runs ``adb install -r`` to ensure existing APK is replaced.
|
||||||
'''),
|
'''),
|
||||||
Parameter('uninstall_apk', kind=boolean, default=False,
|
Parameter('uninstall_apk', kind=boolean, default=False,
|
||||||
description='If ``True``, will uninstall workload\'s APK as part of teardown.'),
|
description='If ``True``, will uninstall workload\'s APK as part of teardown.'),
|
||||||
|
Parameter('check_abi', kind=bool, default=False,
|
||||||
|
description='''
|
||||||
|
If ``True``, workload will check that the APK matches the target
|
||||||
|
device ABI, otherwise any APK found will be used.
|
||||||
|
'''),
|
||||||
]
|
]
|
||||||
|
|
||||||
def __init__(self, device, _call_super=True, **kwargs):
|
def __init__(self, device, _call_super=True, **kwargs):
|
||||||
@ -169,12 +175,14 @@ class ApkWorkload(Workload):
|
|||||||
self.apk_version = None
|
self.apk_version = None
|
||||||
self.logcat_log = None
|
self.logcat_log = None
|
||||||
|
|
||||||
def init_resources(self, context):
|
def initialize(self, context):
|
||||||
self.apk_file = context.resolver.get(wlauto.common.android.resources.ApkFile(self),
|
# Get APK for the correct version and device ABI
|
||||||
|
self.apk_file = context.resolver.get(ApkFile(self, self.device.abi),
|
||||||
version=getattr(self, 'version', None),
|
version=getattr(self, 'version', None),
|
||||||
|
check_abi=getattr(self, 'check_abi', False),
|
||||||
|
variant_name=getattr(self, 'variant_name', None),
|
||||||
strict=self.check_apk)
|
strict=self.check_apk)
|
||||||
|
# Validate the APK
|
||||||
def validate(self):
|
|
||||||
if self.check_apk:
|
if self.check_apk:
|
||||||
if not self.apk_file:
|
if not self.apk_file:
|
||||||
raise WorkloadError('No APK file found for workload {}.'.format(self.name))
|
raise WorkloadError('No APK file found for workload {}.'.format(self.name))
|
||||||
@ -194,7 +202,7 @@ class ApkWorkload(Workload):
|
|||||||
self.initialize_with_host_apk(context, installed_version)
|
self.initialize_with_host_apk(context, installed_version)
|
||||||
else:
|
else:
|
||||||
if not installed_version:
|
if not installed_version:
|
||||||
message = '''{} not found found on the device and check_apk is set to "False"
|
message = '''{} not found on the device and check_apk is set to "False"
|
||||||
so host version was not checked.'''
|
so host version was not checked.'''
|
||||||
raise WorkloadError(message.format(self.package))
|
raise WorkloadError(message.format(self.package))
|
||||||
message = 'Version {} installed on device; skipping host APK check.'
|
message = 'Version {} installed on device; skipping host APK check.'
|
||||||
@ -222,8 +230,8 @@ class ApkWorkload(Workload):
|
|||||||
if self.force_install:
|
if self.force_install:
|
||||||
if installed_version:
|
if installed_version:
|
||||||
self.device.uninstall(self.package)
|
self.device.uninstall(self.package)
|
||||||
# It's possible that that the uninstall above fails, which will result in
|
# It's possible that the uninstall above fails, which might result in a warning
|
||||||
# install failing and a warning, hower execution would the proceed, so need
|
# and/or failure during installation. However execution should proceed, so need
|
||||||
# to make sure that the right apk_vesion is reported in the end.
|
# to make sure that the right apk_vesion is reported in the end.
|
||||||
if self.install_apk(context):
|
if self.install_apk(context):
|
||||||
self.apk_version = host_version
|
self.apk_version = host_version
|
||||||
@ -249,12 +257,13 @@ class ApkWorkload(Workload):
|
|||||||
|
|
||||||
# As of android API level 23, apps can request permissions at runtime,
|
# As of android API level 23, apps can request permissions at runtime,
|
||||||
# this will grant all of them so requests do not pop up when running the app
|
# this will grant all of them so requests do not pop up when running the app
|
||||||
|
# This can also be done less "manually" during adb install using the -g flag
|
||||||
if self.device.get_sdk_version() >= 23:
|
if self.device.get_sdk_version() >= 23:
|
||||||
self._grant_requested_permissions()
|
self._grant_requested_permissions()
|
||||||
|
|
||||||
def install_apk(self, context):
|
def install_apk(self, context):
|
||||||
success = False
|
success = False
|
||||||
output = self.device.install(self.apk_file, self.install_timeout)
|
output = self.device.install(self.apk_file, self.install_timeout, replace=self.force_install)
|
||||||
if 'Failure' in output:
|
if 'Failure' in output:
|
||||||
if 'ALREADY_EXISTS' in output:
|
if 'ALREADY_EXISTS' in output:
|
||||||
self.logger.warn('Using already installed APK (did not unistall properly?)')
|
self.logger.warn('Using already installed APK (did not unistall properly?)')
|
||||||
@ -288,7 +297,7 @@ class ApkWorkload(Workload):
|
|||||||
self.device.execute("pm grant {} {}".format(self.package, permission))
|
self.device.execute("pm grant {} {}".format(self.package, permission))
|
||||||
|
|
||||||
def do_post_install(self, context):
|
def do_post_install(self, context):
|
||||||
""" May be overwritten by dervied classes."""
|
""" May be overwritten by derived classes."""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def run(self, context):
|
def run(self, context):
|
||||||
|
@ -30,6 +30,7 @@ import requests
|
|||||||
|
|
||||||
from wlauto import ResourceGetter, GetterPriority, Parameter, NO_ONE, settings, __file__ as __base_filepath
|
from wlauto import ResourceGetter, GetterPriority, Parameter, NO_ONE, settings, __file__ as __base_filepath
|
||||||
from wlauto.exceptions import ResourceError
|
from wlauto.exceptions import ResourceError
|
||||||
|
from wlauto.utils.android import ApkInfo
|
||||||
from wlauto.utils.misc import ensure_directory_exists as _d, ensure_file_directory_exists as _f, sha256, urljoin
|
from wlauto.utils.misc import ensure_directory_exists as _d, ensure_file_directory_exists as _f, sha256, urljoin
|
||||||
from wlauto.utils.types import boolean
|
from wlauto.utils.types import boolean
|
||||||
|
|
||||||
@ -61,9 +62,11 @@ class PackageFileGetter(ResourceGetter):
|
|||||||
class EnvironmentFileGetter(ResourceGetter):
|
class EnvironmentFileGetter(ResourceGetter):
|
||||||
|
|
||||||
name = 'environment_file'
|
name = 'environment_file'
|
||||||
description = """Looks for exactly one file with the specified extension in the owner's directory. If a version
|
description = """
|
||||||
|
Looks for exactly one file with the specified extension in the owner's directory. If a version
|
||||||
is specified on invocation of get, it will filter the discovered file based on that version.
|
is specified on invocation of get, it will filter the discovered file based on that version.
|
||||||
Versions are treated as case-insensitive."""
|
Versions are treated as case-insensitive.
|
||||||
|
"""
|
||||||
|
|
||||||
extension = None
|
extension = None
|
||||||
|
|
||||||
@ -102,6 +105,22 @@ class PackageApkGetter(PackageFileGetter):
|
|||||||
name = 'package_apk'
|
name = 'package_apk'
|
||||||
extension = 'apk'
|
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``.
|
||||||
|
"""
|
||||||
|
|
||||||
|
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)
|
||||||
|
|
||||||
|
|
||||||
class PackageJarGetter(PackageFileGetter):
|
class PackageJarGetter(PackageFileGetter):
|
||||||
name = 'package_jar'
|
name = 'package_jar'
|
||||||
@ -120,6 +139,22 @@ class EnvironmentApkGetter(EnvironmentFileGetter):
|
|||||||
name = 'environment_apk'
|
name = 'environment_apk'
|
||||||
extension = 'apk'
|
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``.
|
||||||
|
"""
|
||||||
|
|
||||||
|
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)
|
||||||
|
|
||||||
|
|
||||||
class EnvironmentJarGetter(EnvironmentFileGetter):
|
class EnvironmentJarGetter(EnvironmentFileGetter):
|
||||||
name = 'environment_jar'
|
name = 'environment_jar'
|
||||||
@ -427,6 +462,10 @@ class RemoteFilerGetter(ResourceGetter):
|
|||||||
if resource.owner:
|
if resource.owner:
|
||||||
remote_path = os.path.join(self.remote_path, resource.owner.name)
|
remote_path = os.path.join(self.remote_path, resource.owner.name)
|
||||||
local_path = os.path.join(settings.environment_root, '__filer', resource.owner.dependencies_directory)
|
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)
|
return self.try_get_resource(resource, version, remote_path, local_path)
|
||||||
else:
|
else:
|
||||||
result = None
|
result = None
|
||||||
@ -489,24 +528,28 @@ class RemoteFilerGetter(ResourceGetter):
|
|||||||
|
|
||||||
# Utility functions
|
# Utility functions
|
||||||
|
|
||||||
def get_from_location_by_extension(resource, location, extension, version=None):
|
def get_from_location_by_extension(resource, location, extension, version=None, variant=None):
|
||||||
try:
|
try:
|
||||||
found_files = [os.path.join(location, f) for f in os.listdir(location)]
|
found_files = [os.path.join(location, f) for f in os.listdir(location)]
|
||||||
except OSError:
|
except OSError:
|
||||||
return None
|
return None
|
||||||
try:
|
try:
|
||||||
return get_from_list_by_extension(resource, found_files, extension, version)
|
return get_from_list_by_extension(resource, found_files, extension, version, variant=variant)
|
||||||
except ResourceError:
|
except ResourceError:
|
||||||
raise ResourceError('More than one .{} found in {} for {}.'.format(extension,
|
raise ResourceError('More than one .{} found in {} for {}.'.format(extension,
|
||||||
location,
|
location,
|
||||||
resource.owner.name))
|
resource.owner.name))
|
||||||
|
|
||||||
|
|
||||||
def get_from_list_by_extension(resource, filelist, extension, version=None):
|
def get_from_list_by_extension(resource, filelist, extension, version=None, variant=None):
|
||||||
filelist = [ff for ff in filelist
|
filelist = [ff for ff in filelist if os.path.splitext(ff)[1].lower().endswith(extension)]
|
||||||
if os.path.splitext(ff)[1].lower().endswith(extension)]
|
if variant:
|
||||||
|
filelist = [ff for ff in filelist if variant.lower() in os.path.basename(ff).lower()]
|
||||||
if version:
|
if version:
|
||||||
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 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 len(filelist) == 1:
|
if len(filelist) == 1:
|
||||||
return filelist[0]
|
return filelist[0]
|
||||||
elif not filelist:
|
elif not filelist:
|
||||||
|
@ -53,7 +53,8 @@ class Dex2oatBenchmark(Workload):
|
|||||||
def init_resources(self, context):
|
def init_resources(self, context):
|
||||||
# TODO: find a better APK to use for this.
|
# TODO: find a better APK to use for this.
|
||||||
peacekeeper = ExtensionLoader().get_workload('peacekeeper', self.device)
|
peacekeeper = ExtensionLoader().get_workload('peacekeeper', self.device)
|
||||||
self.apk_file = context.resolver.get(wlauto.common.android.resources.ApkFile(peacekeeper), version='chrome')
|
self.apk_file = context.resolver.get(wlauto.common.android.resources.ApkFile(peacekeeper),
|
||||||
|
variant_name='chrome')
|
||||||
self.package = ApkInfo(self.apk_file).package
|
self.package = ApkInfo(self.apk_file).package
|
||||||
|
|
||||||
def setup(self, context):
|
def setup(self, context):
|
||||||
@ -119,4 +120,3 @@ class Dex2oatBenchmark(Workload):
|
|||||||
|
|
||||||
def teardown(self, context):
|
def teardown(self, context):
|
||||||
self.device.delete_file(self.on_device_oat)
|
self.device.delete_file(self.on_device_oat)
|
||||||
|
|
||||||
|
@ -63,7 +63,7 @@ class Peacekeeper(AndroidUiAutoBenchmark):
|
|||||||
|
|
||||||
def __init__(self, device, **kwargs):
|
def __init__(self, device, **kwargs):
|
||||||
super(Peacekeeper, self).__init__(device, **kwargs)
|
super(Peacekeeper, self).__init__(device, **kwargs)
|
||||||
self.version = self.browser
|
self.variant_name = self.browser
|
||||||
|
|
||||||
def update_result(self, context):
|
def update_result(self, context):
|
||||||
super(Peacekeeper, self).update_result(context)
|
super(Peacekeeper, self).update_result(context)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user