From 1a23bd03a228d2604f09015d2d66bbbe92d9a224 Mon Sep 17 00:00:00 2001 From: Sebastian Goscik Date: Mon, 19 Sep 2016 13:41:22 +0100 Subject: [PATCH 1/4] runner: Some types of exceptions will no longer take screenshots or dump UI hiarchy For resource or Host errors (error which are not caused by the target). the runner will no longer take screenshots ect as these are meaningless. --- wlauto/core/execution.py | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/wlauto/core/execution.py b/wlauto/core/execution.py index 0f3d9cd8..bc1e1acd 100644 --- a/wlauto/core/execution.py +++ b/wlauto/core/execution.py @@ -56,7 +56,8 @@ from wlauto.core.extension_loader import ExtensionLoader from wlauto.core.resolver import ResourceResolver from wlauto.core.result import ResultManager, IterationResult, RunResult from wlauto.exceptions import (WAError, ConfigError, TimeoutError, InstrumentError, - DeviceError, DeviceNotRespondingError) + DeviceError, DeviceNotRespondingError, ResourceError, + HostError) from wlauto.utils.misc import ensure_directory_exists as _d, get_traceback, merge_dicts, format_duration @@ -756,17 +757,21 @@ class Runner(object): if self.current_job: self.current_job.result.status = on_error_status self.current_job.result.add_event(str(we)) - try: - self._take_screenshot('error.png') - if self.device.platform == 'android': - self._take_uiautomator_dump('error.xml') - except Exception, e: # pylint: disable=W0703 - # We're already in error state, so the fact that taking a - # screenshot failed is not surprising... - pass + + # There is no point in taking a screenshot ect if the issue is not + # with the device but with the host or a missing resource + if not (isinstance(we, ResourceError) or isinstance(we, HostError)): + try: + self._take_screenshot('error.png') + if self.device.platform == 'android': + self._take_uiautomator_dump('error.xml') + except Exception, e: # pylint: disable=W0703 + # We're already in error state, so the fact that taking a + # screenshot failed is not surprising... + pass if action: action = action[0].lower() + action[1:] - self.logger.error('Error while {}:\n\t{}'.format(action, we)) + self.logger.error('Error while {}:\n\t{}'.format(action, str(we).replace("\n", "\n\t"))) except Exception, e: # pylint: disable=W0703 error_text = '{}("{}")'.format(e.__class__.__name__, e) if self.current_job: From 486ade64996cb92220113329cc49f39a68a1cfb7 Mon Sep 17 00:00:00 2001 From: Sebastian Goscik Date: Wed, 7 Sep 2016 15:26:33 +0100 Subject: [PATCH 2/4] ApkWorkload: Reworked APK Resolution. APK Resolution is now handled a bit differently to try maximise the likelyhood of a workload running. Like before `force_install` will always try to install the host version, if it is not present or is not a correct version, it will error. `check_apk` has changed so that when it is `True` it will prefer to use the host side APK. If it is not there, or not a suitable version and/or abi and the target already has a correct version of the app, the target app will be used. When it is to `False` WA will prefer the target version of the app so long as it is a valid version, if it is not then it will fallback to the host side APK. --- doc/source/apk_workloads.rst | 57 ++++++++ doc/source/index.rst | 1 + wlauto/common/android/workload.py | 210 +++++++++++++++++++----------- 3 files changed, 195 insertions(+), 73 deletions(-) create mode 100644 doc/source/apk_workloads.rst diff --git a/doc/source/apk_workloads.rst b/doc/source/apk_workloads.rst new file mode 100644 index 00000000..5f5c8fab --- /dev/null +++ b/doc/source/apk_workloads.rst @@ -0,0 +1,57 @@ +.. _apk_workload_settings: + +APK Workloads +============= + +APK resolution +-------------- + +WA has various resource getters that can be configured to locate APK files but for most people APK files +should be kept in the ``$WA_HOME/dependencies/SOME_WORKLOAD/`` directory. (by default +``~/.workload_automation/dependencies/SOME_WORKLOAD/``). The ``WA_HOME`` enviroment variable can be used +to chnage the location of this folder. The APK files need to be put into the corresponding directories +for the workload they belong to. The name of the file can be anything but as explained below may need +to contain certain peices of information. + +All ApkWorkloads have parameters that affect the way in which APK files are resolved, ``check_abi``, +``force_install`` and ``check_apk``. Their exact behaviours are outlined below. + +.. 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 + 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. + +.. confval:: force_install + + If this setting is enabled WA will *always* use the APK file on the host, and re-install it on every + iteration. If there is no APK on the host that is a suitable version and/or ABI for the workload WA + will error when ``force_install`` is enabled. + +.. confval:: check_apk + + This parameter is used to specify a preference over host or target versions of the app. When set to + ``True`` WA will prefer the host side version of the APK. It will check if the host has the APK and + if the host APK meets the version requirements of the workload. If does and the target already has + same version nothing will be done, other wise it will overwrite the targets app with the host version. + If the hosts is missing the APK or it does not meet version requirements WA will fall back to the app + on the target if it has the app and it is of a suitable version. When this parameter is set to + ``false`` WA will prefer to use the version already on the target if it meets the workloads version + requirements. If it does not it will fall back to search the host for the correct version. In both modes + if neither the host nor target have a suitable version, WA will error and not run the workload. + +Some workloads will also feature the follow parameters which will alter the way their APK files are resolved. + +.. confval:: version + + This parameter is used to specify which version of uiautomation for the workload is used. In some workloads + e.g. ``geekbench`` multiple versions with drastically different UI's are supported. When a workload uses a + version it is required for the APK file to contain the uiautomation version in the file name. In the case + of antutu the file names could be: ``geekbench_2.apk`` or ``geekbench_3.apk``. + +.. confval:: variant_name + + Some workloads use variants of APK files, this is usually the case with web browser APK files, these work + in exactly the same way as the version, the variant of the apk + diff --git a/doc/source/index.rst b/doc/source/index.rst index 46095f5d..4a50454b 100644 --- a/doc/source/index.rst +++ b/doc/source/index.rst @@ -118,6 +118,7 @@ and detailed descriptions of how WA functions under the hood. additional_topics daq_device_setup revent + apk_workloads contributing API Reference diff --git a/wlauto/common/android/workload.py b/wlauto/common/android/workload.py index 9483eafd..8af9d1b5 100644 --- a/wlauto/common/android/workload.py +++ b/wlauto/common/android/workload.py @@ -25,7 +25,7 @@ from wlauto.core.workload import Workload from wlauto.core.resource import NO_ONE from wlauto.common.android.resources import ApkFile from wlauto.common.resources import ExtensionAsset, Executable, File -from wlauto.exceptions import WorkloadError, ResourceError, ConfigError, DeviceError +from wlauto.exceptions import WorkloadError, ResourceError, DeviceError from wlauto.utils.android import ApkInfo, ANDROID_NORMAL_PERMISSIONS, UNSUPPORTED_PACKAGES from wlauto.utils.types import boolean from wlauto.utils.revent import ReventParser @@ -35,12 +35,12 @@ import wlauto.common.android.resources DELAY = 5 - # Due to the way `super` works you have to call it at every level but WA executes some -# methods conditionally and so has to do them directly via the class, this breaks super +# methods conditionally and so has to call them directly via the class, this breaks super # and causes it to run things mutiple times ect. As a work around for this untill workloads # are reworked everything that subclasses workload calls parent methods explicitly + class UiAutomatorWorkload(Workload): """ Base class for all workloads that rely on a UI Automator JAR file. @@ -173,13 +173,16 @@ class ApkWorkload(Workload): description='Timeout for the installation of the apk.'), Parameter('check_apk', kind=boolean, default=True, description=''' - Discover the APK for this workload on the host, and check that - the version matches the one on device (if already installed). + When set to True the APK file on the host will be prefered if + it is a valid version and ABI, if not it will fall back to the + version on the targer. When set to False the target version is + prefered. '''), Parameter('force_install', kind=boolean, default=False, description=''' Always re-install the APK, even if matching version is found already installed - on the device. Runs ``adb install -r`` to ensure existing APK is replaced. + on the device. Runs ``adb install -r`` to ensure existing APK is replaced. When + this is set, check_apk is ignored. '''), Parameter('uninstall_apk', kind=boolean, default=False, description='If ``True``, will uninstall workload\'s APK as part of teardown.'), @@ -199,88 +202,149 @@ class ApkWorkload(Workload): def setup(self, context): Workload.setup(self, context) - # Get APK for the correct version and device ABI + + # Get target version + target_version = self.device.get_installed_package_version(self.package) + if target_version: + target_version = LooseVersion(target_version) + self.logger.debug("Found version '{}' on target device".format(target_version)) + + # 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=self.check_apk) - # Validate the APK - if self.check_apk: - if not self.apk_file: - raise WorkloadError('No APK file found for workload {}.'.format(self.name)) + strict=False) + host_version = None + if self.apk_file is not None: + host_version = ApkInfo(self.apk_file).version_name + if host_version: + host_version = LooseVersion(host_version) + self.logger.debug("Found version '{}' on host".format(host_version)) + + # Error if apk was not found anywhere + if target_version is None and host_version is None: + msg = "Could not find APK for '{}' on the host or target device" + raise ResourceError(msg.format(self.name)) + + # Ensure the apk is setup on the device + if self.force_install: + self.force_install_apk(context, host_version, target_version) + elif self.check_apk: + self.prefer_host_apk(context, host_version, target_version) else: - if self.force_install: - raise ConfigError('force_install cannot be "True" when check_apk is set to "False".') + self.prefer_target_apk(context, host_version, target_version) - self.initialize_package(context) - - # Check the APK version against the min and max versions compatible - # with the workload before launching the package. Note: must be called - # after initialize_package() to get self.apk_version. - if self.check_apk: - self.check_apk_version() + self.reset(context) + self.apk_version = self.device.get_installed_package_version(self.package) + context.add_classifiers(apk_version=self.apk_version) if self.launch_main: - self.launch_package() # launch default activity without intent data + self.launch_package() # launch default activity without intent data self.device.execute('am kill-all') # kill all *background* activities self.device.clear_logcat() - def initialize_package(self, context): - installed_version = self.device.get_installed_package_version(self.package) - if self.check_apk: - self.initialize_with_host_apk(context, installed_version) - else: - if not installed_version: - message = '''{} not found on the device and check_apk is set to "False" - so host version was not checked.''' - raise WorkloadError(message.format(self.package)) - message = 'Version {} installed on device; skipping host APK check.' - self.logger.debug(message.format(installed_version)) - self.reset(context) - self.apk_version = installed_version - context.add_classifiers(apk_version=self.apk_version) + def force_install_apk(self, context, host_version, target_version): + if host_version is None: + raise ResourceError("force_install is 'True' but could not find APK on the host") + try: + self.validate_version(host_version) + except ResourceError as e: + msg = "force_install is 'True' but the host version is invalid:\n\t{}" + raise ResourceError(msg.format(str(e))) + self.install_apk(context, replace=(target_version is not None)) - def initialize_with_host_apk(self, context, installed_version): - host_version = ApkInfo(self.apk_file).version_name - if installed_version != host_version: - if installed_version: - message = '{} host version: {}, device version: {}; re-installing...' - self.logger.debug(message.format(os.path.basename(self.apk_file), - host_version, installed_version)) + def prefer_host_apk(self, context, host_version, target_version): + msg = "check_apk is 'True' " + if host_version is None: + try: + self.validate_version(target_version) + except ResourceError as e: + msg += "but the APK was not found on the host and the target version is invalid:\n\t{}" + raise ResourceError(msg.format(str(e))) else: - message = '{} host version: {}, not found on device; installing...' - self.logger.debug(message.format(os.path.basename(self.apk_file), - host_version)) - self.force_install = True # pylint: disable=attribute-defined-outside-init - else: - message = '{} version {} found on both device and host.' - self.logger.debug(message.format(os.path.basename(self.apk_file), - host_version)) - if self.force_install: - if installed_version: - self.device.uninstall(self.package) - # It's possible that the uninstall above fails, which might result in a warning - # and/or failure during installation. However execution should proceed, so need - # to make sure that the right apk_vesion is reported in the end. - if self.install_apk(context): - self.apk_version = host_version + msg += "but the APK was not found on the host, using target version" + self.logger.debug(msg) + return + try: + self.validate_version(host_version) + except ResourceError as e1: + msg += "but the host APK version is invalid:\n\t{}\n" + if target_version is None: + msg += "The target does not have the app either" + raise ResourceError(msg.format(str(e1))) + try: + self.validate_version(target_version) + except ResourceError as e2: + msg += "The target version is also invalid:\n\t{}" + raise ResourceError(msg.format(str(e1), str(e2))) else: - self.apk_version = installed_version + msg += "using the target version instead" + self.logger.debug(msg.format(str(e1))) + else: # Host version is valid + if target_version is not None and target_version == host_version: + msg += " and a matching version is alread on the device, doing nothing" + self.logger.debug(msg) + return + msg += " and the host version is not on the target, installing APK" + self.logger.debug(msg) + self.install_apk(context, replace=(target_version is not None)) + + def prefer_target_apk(self, context, host_version, target_version): + msg = "check_apk is 'False' " + if target_version is None: + try: + self.validate_version(host_version) + except ResourceError as e: + msg += "but the app was not found on the target and the host version is invalid:\n\t{}" + raise ResourceError(msg.format(str(e))) + else: + msg += "and the app was not found on the target, using host version" + self.logger.debug(msg) + self.install_apk(context) + return + try: + self.validate_version(target_version) + except ResourceError as e1: + msg += "but the target app version is invalid:\n\t{}\n" + if host_version is None: + msg += "The host does not have the APK either" + raise ResourceError(msg.format(str(e1))) + try: + self.validate_version(host_version) + except ResourceError as e2: + msg += "The host version is also invalid:\n\t{}" + raise ResourceError(msg.format(str(e1), str(e2))) + else: + msg += "Using the host APK instead" + self.logger.debug(msg.format(str(e1))) + self.install_apk(context, replace=True) else: - self.apk_version = installed_version - self.reset(context) + msg += "and a valid version of the app is already on the target, using target app" + self.logger.debug(msg) - def check_apk_version(self): - if self.min_apk_version: - if LooseVersion(self.apk_version) < LooseVersion(self.min_apk_version): - message = "APK version not supported. Minimum version required: {}" - raise WorkloadError(message.format(self.min_apk_version)) + def validate_version(self, version): + min_apk_version = getattr(self, 'min_apk_version', None) + max_apk_version = getattr(self, 'max_apk_version', None) - if self.max_apk_version: - if LooseVersion(self.apk_version) > LooseVersion(self.max_apk_version): - message = "APK version not supported. Maximum version supported: {}" - raise WorkloadError(message.format(self.max_apk_version)) + if min_apk_version is not None and max_apk_version is not None: + if version < LooseVersion(min_apk_version) or \ + version > LooseVersion(max_apk_version): + msg = "version '{}' not supported. " \ + "Minimum version required: '{}', Maximum version known to work: '{}'" + raise ResourceError(msg.format(version, min_apk_version)) + + elif min_apk_version is not None: + if version < LooseVersion(min_apk_version): + msg = "version '{}' not supported. " \ + "Minimum version required: '{}'" + raise ResourceError(msg.format(version, min_apk_version)) + + elif max_apk_version is not None: + if version > LooseVersion(max_apk_version): + msg = "version '{}' not supported. " \ + "Maximum version known to work: '{}'" + raise ResourceError(msg.format(version, min_apk_version)) def launch_package(self): if not self.activity: @@ -302,9 +366,9 @@ class ApkWorkload(Workload): if self.device.get_sdk_version() >= 23: self._grant_requested_permissions() - def install_apk(self, context): + def install_apk(self, context, replace=False): success = False - output = self.device.install(self.apk_file, self.install_timeout, replace=self.force_install) + output = self.device.install(self.apk_file, self.install_timeout, replace=replace) if 'Failure' in output: if 'ALREADY_EXISTS' in output: self.logger.warn('Using already installed APK (did not unistall properly?)') From 1bbd3ef87a8716817f074bd0e8d51647c13406df Mon Sep 17 00:00:00 2001 From: Sebastian Goscik Date: Mon, 19 Sep 2016 13:56:11 +0100 Subject: [PATCH 3/4] Revert "workloads: Fixed versions to be backward compatible" This reverts commit 8608c3b747fb544f95c3eefa45191b47efe53994. --- wlauto/workloads/antutu/__init__.py | 4 +--- wlauto/workloads/geekbench/__init__.py | 7 +------ wlauto/workloads/glbenchmark/__init__.py | 6 +----- 3 files changed, 3 insertions(+), 14 deletions(-) diff --git a/wlauto/workloads/antutu/__init__.py b/wlauto/workloads/antutu/__init__.py index ecac06ad..13cffa73 100644 --- a/wlauto/workloads/antutu/__init__.py +++ b/wlauto/workloads/antutu/__init__.py @@ -48,7 +48,7 @@ class Antutu(AndroidUiAutoBenchmark): activity = ".ABenchMarkStart" summary_metrics = ['score', 'Overall_Score'] - valid_versions = ['3.3.2', '4.0.3', '5.3', '5.3.0', '6.0.1'] + valid_versions = ['3.3.2', '4.0.3', '5.3', '6.0.1'] device_prefs_directory = '/data/data/com.antutu.ABenchMark/shared_prefs' device_prefs_file = '/'.join([device_prefs_directory, 'com.antutu.ABenchMark_preferences.xml']) @@ -70,8 +70,6 @@ class Antutu(AndroidUiAutoBenchmark): def __init__(self, device, **kwargs): # pylint: disable=W0613 super(Antutu, self).__init__(device, **kwargs) - if self.version == '5.3.0': - self.version = '5.3' self.run_timeout = 10 * 60 * self.times self.uiauto_params['version'] = self.version self.uiauto_params['times'] = self.times diff --git a/wlauto/workloads/geekbench/__init__.py b/wlauto/workloads/geekbench/__init__.py index b4c80c0c..b7dc7a9f 100644 --- a/wlauto/workloads/geekbench/__init__.py +++ b/wlauto/workloads/geekbench/__init__.py @@ -73,8 +73,7 @@ class Geekbench(AndroidUiAutoBenchmark): replace_regex = re.compile(r'<[^>]*>') parameters = [ - Parameter('version', default=sorted(versions.keys())[-1], allowed_values=sorted(versions.keys() + - ['2', '3']), + Parameter('version', default=sorted(versions.keys())[-1], allowed_values=sorted(versions.keys()), description='Specifies which version of the workload should be run.'), Parameter('times', kind=int, default=1, description=('Specfies the number of times the benchmark will be run in a "tight ' @@ -91,10 +90,6 @@ class Geekbench(AndroidUiAutoBenchmark): def __init__(self, device, **kwargs): super(Geekbench, self).__init__(device, **kwargs) - if self.version == '3': - self.version = '3.0.0' - elif self.version == '2': - self.version = '2.2.7' self.uiauto_params['version'] = self.version self.uiauto_params['times'] = self.times self.run_timeout = 5 * 60 * self.times diff --git a/wlauto/workloads/glbenchmark/__init__.py b/wlauto/workloads/glbenchmark/__init__.py index 1c240ca5..0e54e149 100644 --- a/wlauto/workloads/glbenchmark/__init__.py +++ b/wlauto/workloads/glbenchmark/__init__.py @@ -73,7 +73,7 @@ class Glb(AndroidUiAutoBenchmark): regex = re.compile(r'GLBenchmark (metric|FPS): (.*)') parameters = [ - Parameter('version', default='2.7', allowed_values=['2.7', '2.7.0', '2.5', '2.5.1'], + Parameter('version', default='2.7', allowed_values=['2.7', '2.5'], description=('Specifies which version of the benchmark to run (different versions ' 'support different use cases).')), Parameter('use_case', default=None, @@ -111,10 +111,6 @@ class Glb(AndroidUiAutoBenchmark): def __init__(self, device, **kwargs): super(Glb, self).__init__(device, **kwargs) - if self.version == '2.7.0': - self.version = '2.7' - elif self.version == '2.5.1': - self.version = '2.5' self.uiauto_params['version'] = self.version if self.use_case is None: From f9ec869c7b7ea85452f5020b778488ab55c42bd3 Mon Sep 17 00:00:00 2001 From: Sebastian Goscik Date: Mon, 19 Sep 2016 13:56:22 +0100 Subject: [PATCH 4/4] Revert "Updated workload versions to match APK files" This reverts commit b426e00f2fd98bc602b40bec815847c6287b610a. --- wlauto/workloads/antutu/__init__.py | 2 +- .../antutu/com.arm.wlauto.uiauto.antutu.jar | Bin 10254 -> 6139 bytes .../com/arm/wlauto/uiauto/UiAutomation.java | 4 ++-- wlauto/workloads/geekbench/__init__.py | 16 +++++++--------- .../com.arm.wlauto.uiauto.geekbench.jar | Bin 7822 -> 3523 bytes .../com/arm/wlauto/uiauto/UiAutomation.java | 10 +++++----- wlauto/workloads/glbenchmark/__init__.py | 14 +++++++------- .../glbenchmark/com.arm.wlauto.uiauto.glb.jar | Bin 8786 -> 4629 bytes .../com/arm/wlauto/uiauto/UiAutomation.java | 14 +++++++------- 9 files changed, 29 insertions(+), 31 deletions(-) diff --git a/wlauto/workloads/antutu/__init__.py b/wlauto/workloads/antutu/__init__.py index 13cffa73..398ac008 100644 --- a/wlauto/workloads/antutu/__init__.py +++ b/wlauto/workloads/antutu/__init__.py @@ -48,7 +48,7 @@ class Antutu(AndroidUiAutoBenchmark): activity = ".ABenchMarkStart" summary_metrics = ['score', 'Overall_Score'] - valid_versions = ['3.3.2', '4.0.3', '5.3', '6.0.1'] + valid_versions = ['3.3.2', '4.0.3', '5.3.0', '6.0.1'] device_prefs_directory = '/data/data/com.antutu.ABenchMark/shared_prefs' device_prefs_file = '/'.join([device_prefs_directory, 'com.antutu.ABenchMark_preferences.xml']) diff --git a/wlauto/workloads/antutu/com.arm.wlauto.uiauto.antutu.jar b/wlauto/workloads/antutu/com.arm.wlauto.uiauto.antutu.jar index 7c83ec3b8b7a33c186b71bc7c205bd063e98e272..4aecde1da3e8bc38c92f2c4d5cd50675ae34b59e 100644 GIT binary patch delta 5953 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 j001a0000XB0000000000005+cx0C889tJNL00000?Ny@& delta 10101 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 QgPW7)Dd;g|SpO6L4~TN(4FCWD diff --git a/wlauto/workloads/antutu/uiauto/src/com/arm/wlauto/uiauto/UiAutomation.java b/wlauto/workloads/antutu/uiauto/src/com/arm/wlauto/uiauto/UiAutomation.java index fc44e9a3..4d7a08d1 100644 --- a/wlauto/workloads/antutu/uiauto/src/com/arm/wlauto/uiauto/UiAutomation.java +++ b/wlauto/workloads/antutu/uiauto/src/com/arm/wlauto/uiauto/UiAutomation.java @@ -66,7 +66,7 @@ public class UiAutomation extends BaseUiAutomation { while (true) { if(version.equals("6.0.1")) hitTestButtonVersion5(TestButton6); - else if (version.equals("5.3")) { + else if (version.equals("5.3.0")) { hitTestButton(); hitTestButtonVersion5(TestButton5); } @@ -308,7 +308,7 @@ public class UiAutomation extends BaseUiAutomation { public void returnToTestScreen(String version) throws Exception { getUiDevice().pressBack(); - if (version.equals("5.3")) + if (version.equals("5.3.0")) { UiSelector selector = new UiSelector(); UiObject detailsButton = new UiObject(new UiSelector().className("android.widget.Button") diff --git a/wlauto/workloads/geekbench/__init__.py b/wlauto/workloads/geekbench/__init__.py index b7dc7a9f..8d484cc2 100644 --- a/wlauto/workloads/geekbench/__init__.py +++ b/wlauto/workloads/geekbench/__init__.py @@ -59,11 +59,11 @@ class Geekbench(AndroidUiAutoBenchmark): """ summary_metrics = ['score', 'multicore_score'] versions = { - '3.0.0': { + '3': { 'package': 'com.primatelabs.geekbench3', 'activity': '.HomeActivity', }, - '2.2.7': { + '2': { 'package': 'ca.primatelabs.geekbench2', 'activity': '.HomeActivity', }, @@ -95,7 +95,7 @@ class Geekbench(AndroidUiAutoBenchmark): self.run_timeout = 5 * 60 * self.times def initialize(self, context): - if self.version == '3.0.0' and not self.device.is_rooted: + if self.version == '3' and not self.device.is_rooted: raise WorkloadError('Geekbench workload only works on rooted devices.') def init_resources(self, context): @@ -108,14 +108,12 @@ class Geekbench(AndroidUiAutoBenchmark): def update_result(self, context): super(Geekbench, self).update_result(context) - if self.version == "2.2.7": - self.update_result_2(context) - else: - self.update_result_3(context) + update_method = getattr(self, 'update_result_{}'.format(self.version)) + update_method(context) def validate(self): - if (self.times > 1) and (self.version == '2.2.7'): - raise ConfigError('times parameter is not supported for version 2.2.7 of Geekbench.') + if (self.times > 1) and (self.version == '2'): + raise ConfigError('times parameter is not supported for version 2 of Geekbench.') def update_result_2(self, context): score_calculator = GBScoreCalculator() diff --git a/wlauto/workloads/geekbench/com.arm.wlauto.uiauto.geekbench.jar b/wlauto/workloads/geekbench/com.arm.wlauto.uiauto.geekbench.jar index deec40bd9f0d345673b91d98b81978a87862afff..5359cc30c8eb8f8c36d947edd340367d949f11e6 100644 GIT binary patch delta 3333 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 PyOU}j9tQUe00000hU`}> delta 7674 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 diff --git a/wlauto/workloads/geekbench/uiauto/src/com/arm/wlauto/uiauto/UiAutomation.java b/wlauto/workloads/geekbench/uiauto/src/com/arm/wlauto/uiauto/UiAutomation.java index 2ef4b9ea..968d2abc 100644 --- a/wlauto/workloads/geekbench/uiauto/src/com/arm/wlauto/uiauto/UiAutomation.java +++ b/wlauto/workloads/geekbench/uiauto/src/com/arm/wlauto/uiauto/UiAutomation.java @@ -32,26 +32,26 @@ import com.android.uiautomator.testrunner.UiAutomatorTestCase; import com.arm.wlauto.uiauto.BaseUiAutomation; -public class UiAutomation extends BaseUiAutomation { +public class UiAutomation extends BaseUiAutomation { public static String TAG = "geekbench"; public void runUiAutomation() throws Exception { Bundle params = getParams(); - String version = params.getString("version"); + int version = Integer.parseInt(params.getString("version")); int times = Integer.parseInt(params.getString("times")); for (int i = 0; i < times; i++) { runBenchmarks(); - if(version.equals("2.2.7")) { + switch(version) { + case 2: // In version 2, we scroll through the results WebView to make sure // all results appear on the screen, which causes them to be dumped into // logcat by the Linaro hacks. waitForResultsv2(); scrollThroughResults(); break; - } - else if(version.equals("3.0.0")) { + case 3: // Attempting to share the results will generate the .gb3 file with // results that can then be pulled from the device. This is not possible // in verison 2 of Geekbench (Share option was added later). diff --git a/wlauto/workloads/glbenchmark/__init__.py b/wlauto/workloads/glbenchmark/__init__.py index 0e54e149..d8206cc2 100644 --- a/wlauto/workloads/glbenchmark/__init__.py +++ b/wlauto/workloads/glbenchmark/__init__.py @@ -57,14 +57,14 @@ class Glb(AndroidUiAutoBenchmark): view = 'com.glbenchmark.glbenchmark27/com.glbenchmark.activities.GLBRender' packages = { - '2.7': 'com.glbenchmark.glbenchmark27', - '2.5': 'com.glbenchmark.glbenchmark25', + '2.7.0': 'com.glbenchmark.glbenchmark27', + '2.5.1': 'com.glbenchmark.glbenchmark25', } # If usecase is not specified the default usecase is the first supported usecase alias # for the specified version. supported_usecase_aliases = { - '2.7': ['t-rex', 'egypt'], - '2.5': ['egypt-classic', 'egypt'], + '2.7.0': ['t-rex', 'egypt'], + '2.5.1': ['egypt-classic', 'egypt'], } default_iterations = 1 @@ -73,15 +73,15 @@ class Glb(AndroidUiAutoBenchmark): regex = re.compile(r'GLBenchmark (metric|FPS): (.*)') parameters = [ - Parameter('version', default='2.7', allowed_values=['2.7', '2.5'], + Parameter('version', default='2.7.0', allowed_values=['2.7.0', '2.5.1'], description=('Specifies which version of the benchmark to run (different versions ' 'support different use cases).')), Parameter('use_case', default=None, description="""Specifies which usecase to run, as listed in the benchmark menu; e.g. ``'GLBenchmark 2.5 Egypt HD'``. For convenience, two aliases are provided for the most common use cases: ``'egypt'`` and ``'t-rex'``. These could - be use instead of the full use case title. For version ``'2.7'`` it defaults - to ``'t-rex'``, for version ``'2.5'`` it defaults to ``'egypt-classic'``. + be use instead of the full use case title. For version ``'2.7.0'`` it defaults + to ``'t-rex'``, for version ``'2.5.1'`` it defaults to ``'egypt-classic'``. """), Parameter('variant', default='onscreen', description="""Specifies which variant of the use case to run, as listed in the benchmarks diff --git a/wlauto/workloads/glbenchmark/com.arm.wlauto.uiauto.glb.jar b/wlauto/workloads/glbenchmark/com.arm.wlauto.uiauto.glb.jar index 71773c9ba72895f7a8f4aac43a193fead3c0b872..57d0fb1e843c52d88d0035312d37857bc561d0d1 100644 GIT binary patch delta 4456 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 O#49W^_z=qfwEqRi|I