From 64b5df9ccb9e9c3a124481aef95c6e8af57e4848 Mon Sep 17 00:00:00 2001 From: Bob Clary Date: Fri, 17 Jul 2020 20:48:55 +0000 Subject: [PATCH] Bug 1486004 - Part 14 - Update raptor to support unrooted android devices using mozdevice 4.0.0, ? r=perftest-reviewers,sparky Depends on D82756 Differential Revision: https://phabricator.services.mozilla.com/D82757 --- testing/raptor/mach_commands.py | 5 +++ testing/raptor/raptor/browsertime/android.py | 20 +++++++---- testing/raptor/raptor/performance_tuning.py | 33 ++++++++++++------- testing/raptor/raptor/perftest.py | 11 +++---- testing/raptor/raptor/power.py | 7 ++-- testing/raptor/raptor/webextension/android.py | 18 +++++----- testing/raptor/requirements.txt | 2 +- 7 files changed, 58 insertions(+), 38 deletions(-) diff --git a/testing/raptor/mach_commands.py b/testing/raptor/mach_commands.py index e1e1f98f1668..1cb0b493d820 100644 --- a/testing/raptor/mach_commands.py +++ b/testing/raptor/mach_commands.py @@ -234,8 +234,13 @@ class MachRaptor(MachCommandBase): from mozrunner.devices.android_device import (verify_android_device, InstallIntent) from mozdevice import ADBAndroid install = InstallIntent.NO if kwargs.pop('noinstall', False) else InstallIntent.YES + verbose = False + if kwargs.get('log_mach_verbose') or kwargs.get('log_tbpl_level') == 'debug' or \ + kwargs.get('log_mach_level') == 'debug' or kwargs.get('log_raw_level') == 'debug': + verbose = True if not verify_android_device(build_obj, install=install, app=kwargs['binary'], + verbose=verbose, xre=True): # Equivalent to 'run_local' = True. return 1 diff --git a/testing/raptor/raptor/browsertime/android.py b/testing/raptor/raptor/browsertime/android.py index 3aa826966568..3f3bbd9ad04c 100644 --- a/testing/raptor/raptor/browsertime/android.py +++ b/testing/raptor/raptor/browsertime/android.py @@ -8,7 +8,7 @@ from __future__ import absolute_import import os -from mozdevice import ADBDevice +from mozdevice import ADBDeviceFactory from logger.logger import RaptorLogger from performance_tuning import tune_performance @@ -34,16 +34,21 @@ class BrowsertimeAndroid(PerftestAndroid, Browsertime): file ourselves. Also note when using playback, the nss certificate db is created as usual when mitmproxy is started (and saved in the profile) so it is already included in the profile that browsertime/geckodriver copies onto the device. + XXX: bc: This doesn't work with scoped storage in Android 10 since the shell owns the profile + directory that is pushed to the device and the profile can no longer be on the sdcard. But when + geckodriver's android.rs defines the profile to be located on internal storage, it will be + owned by shell but if we are attempting to eliminate root, then when we run shell commands + as the app, they will fail due to the app being unable to write to the shell owned profile + directory. """ def __init__(self, app, binary, activity=None, intent=None, **kwargs): super(BrowsertimeAndroid, self).__init__( app, binary, profile_class="firefox", **kwargs ) - self.config.update({"activity": activity, "intent": intent}) - self.remote_test_root = "/data/local/tmp/tests/raptor" - self.remote_profile = os.path.join(self.remote_test_root, "profile") + self.remote_test_root = None + self.remote_profile = None @property def browsertime_args(self): @@ -117,12 +122,15 @@ class BrowsertimeAndroid(PerftestAndroid, Browsertime): def setup_adb_device(self): if self.device is None: - self.device = ADBDevice(verbose=True) + self.device = ADBDeviceFactory(verbose=True) if not self.config.get("disable_perf_tuning", False): tune_performance(self.device, log=LOG) self.clear_app_data() self.set_debug_app_flag() + self.device.run_as_package = self.config['binary'] + self.remote_test_root = os.path.join(self.device.test_root, "raptor") + self.remote_profile = os.path.join(self.remote_test_root, "profile") def run_test_setup(self, test): super(BrowsertimeAndroid, self).run_test_setup(test) @@ -138,7 +146,7 @@ class BrowsertimeAndroid(PerftestAndroid, Browsertime): if self.config['app'] == "chrome-m": # Make sure that chrome is enabled on the device - self.device.shell_output("pm enable com.android.chrome", root=True) + self.device.shell_output("pm enable com.android.chrome") return super(BrowsertimeAndroid, self).run_tests(tests, test_names) diff --git a/testing/raptor/raptor/performance_tuning.py b/testing/raptor/raptor/performance_tuning.py index 80218bcd4011..3e14ceb99053 100644 --- a/testing/raptor/raptor/performance_tuning.py +++ b/testing/raptor/raptor/performance_tuning.py @@ -4,6 +4,8 @@ from __future__ import absolute_import +from mozdevice import ADBError + def tune_performance(device, log=None, timeout=None): """Set various performance-oriented parameters, to reduce jitter. @@ -24,7 +26,7 @@ class PerformanceTuner(object): def tune_performance(self): self.log.info("tuning android device performance") self.set_svc_power_stayon() - if self.device._have_su or self.device._have_android_su: + if self.device.is_rooted: device_name = self.device.shell_output('getprop ro.product.model', timeout=self.timeout) # all commands require root shell from here on @@ -37,13 +39,15 @@ class PerformanceTuner(object): self.device.clear_logcat(timeout=self.timeout) self.log.info("android device performance tuning complete") - def _set_value_and_check_exitcode(self, file_name, value, root=False): + def _set_value_and_check_exitcode(self, file_name, value): self.log.info('setting {} to {}'.format(file_name, value)) - if self.device.shell_bool(' '.join(['echo', str(value), '>', str(file_name)]), - root=root, timeout=self.timeout): + try: + self.device.shell_output(' '.join(['echo', str(value), '>', str(file_name)]), + timeout=self.timeout) self.log.info('successfully set {} to {}'.format(file_name, value)) - else: - self.log.warning('command failed') + except ADBError as e: + self.log.info("Ignoring failure to set value {} to {}. {}".format( + file_name, value, e)) def set_svc_power_stayon(self): self.log.info('set device to stay awake on usb') @@ -62,8 +66,13 @@ class PerformanceTuner(object): 'thermald', ] for service in services: - self.log.info(' '.join(['turning off service:', service])) - self.device.shell_bool(' '.join(['stop', service]), root=True, timeout=self.timeout) + try: + self.log.info(' '.join(['turning off service:', service])) + self.device.shell_bool(' '.join(['stop', service]), + timeout=self.timeout) + except ADBError as e: + self.log.info("Ignoring failure to stop service {}. Error: {}: {}".format( + service, e.__class__.__name__, e)) services_list_output = self.device.shell_output('service list', timeout=self.timeout) for service in services: @@ -107,7 +116,7 @@ class PerformanceTuner(object): } for key, value in commands.items(): - self._set_value_and_check_exitcode(key, value, root=True) + self._set_value_and_check_exitcode(key, value) def set_cpu_performance_parameters(self, device_name=None): self.log.info('setting cpu performance parameters') @@ -144,7 +153,7 @@ class PerformanceTuner(object): .format(device_name)) for key, value in commands.items(): - self._set_value_and_check_exitcode(key, value, root=True) + self._set_value_and_check_exitcode(key, value) def set_gpu_performance_parameters(self, device_name=None): self.log.info('setting gpu performance parameters') @@ -186,7 +195,7 @@ class PerformanceTuner(object): .format(device_name)) for key, value in commands.items(): - self._set_value_and_check_exitcode(key, value, root=True) + self._set_value_and_check_exitcode(key, value) def set_kernel_performance_parameters(self): self.log.info('setting kernel performance parameters') @@ -197,4 +206,4 @@ class PerformanceTuner(object): '/sys/kernel/debug/msm-bus-dbg/shell-client/slv': '512', } for key, value in commands.items(): - self._set_value_and_check_exitcode(key, value, root=True) + self._set_value_and_check_exitcode(key, value) diff --git a/testing/raptor/raptor/perftest.py b/testing/raptor/raptor/perftest.py index c76cae2806e5..e9b1e455b32e 100644 --- a/testing/raptor/raptor/perftest.py +++ b/testing/raptor/raptor/perftest.py @@ -579,8 +579,8 @@ class PerftestAndroid(Perftest): # We absolutely need to determine the chrome # version here so that we can select the correct # chromedriver for browsertime - from mozdevice import ADBDevice - device = ADBDevice(verbose=True) + from mozdevice import ADBDeviceFactory + device = ADBDeviceFactory(verbose=True) binary = "com.android.chrome" pkg_info = device.shell_output("dumpsys package %s" % binary) @@ -658,12 +658,9 @@ class PerftestAndroid(Perftest): try: LOG.info("copying profile to device: %s" % self.remote_profile) - # We must use root=True since the remote profile has been - # modified by gecko and has content which is only - # accessible to the gecko user. - self.device.rm(self.remote_profile, force=True, recursive=True, root=True) + self.device.rm(self.remote_profile, force=True, recursive=True) self.device.push(self.profile.profile, self.remote_profile) - self.device.chmod(self.remote_profile, recursive=True, root=True) + self.device.chmod(self.remote_profile, recursive=True) except Exception: LOG.error("Unable to copy profile to device.") diff --git a/testing/raptor/raptor/power.py b/testing/raptor/raptor/power.py index d996a939908d..8c1162661831 100644 --- a/testing/raptor/raptor/power.py +++ b/testing/raptor/raptor/power.py @@ -41,12 +41,12 @@ def change_charging_state(device, device_type, enable=True, timeout=10): if device_type == "Pixel 2": status = 0 if enable else 1 device.shell_bool( - "echo %s > %s" % (status, P2_PATH), root=True, timeout=timeout + "echo %s > %s" % (status, P2_PATH), timeout=timeout ) elif device_type == "Moto G (5)": status = 1 if enable else 0 device.shell_bool( - "echo %s > %s" % (status, G5_PATH), root=True, timeout=timeout + "echo %s > %s" % (status, G5_PATH), timeout=timeout ) except (ADBTimeoutError, ADBError) as e: raise Exception( @@ -360,6 +360,9 @@ def finish_android_power_test(raptor, test_name, os_baseline=False): LOG.info("Approximate power test time %s" % str(test_time)) def calculate_pc(power_measure, baseline_measure): + if not baseline_measure: + LOG.error("Power test baseline_measure is Zero.") + return 0 return (100 * ( (power_measure + baseline_measure) / baseline_measure diff --git a/testing/raptor/raptor/webextension/android.py b/testing/raptor/raptor/webextension/android.py index 2df9495c80a7..7bbbb114102c 100644 --- a/testing/raptor/raptor/webextension/android.py +++ b/testing/raptor/raptor/webextension/android.py @@ -15,7 +15,7 @@ import time import mozcrash from cpu import start_android_cpu_profiler from logger.logger import RaptorLogger -from mozdevice import ADBDevice, ADBProcessError +from mozdevice import ADBDeviceFactory, ADBProcessError from performance_tuning import tune_performance from perftest import PerftestAndroid from power import ( @@ -39,8 +39,6 @@ class WebExtensionAndroid(PerftestAndroid, WebExtension): self.config.update({"activity": activity, "intent": intent}) - self.remote_test_root = "/data/local/tmp/tests/raptor" - self.remote_profile = os.path.join(self.remote_test_root, "profile") self.os_baseline_data = None self.power_test_time = None self.screen_off_timeout = 0 @@ -49,17 +47,19 @@ class WebExtensionAndroid(PerftestAndroid, WebExtension): def setup_adb_device(self): if self.device is None: - self.device = ADBDevice(verbose=True) + self.device = ADBDeviceFactory(verbose=True) if not self.config.get("disable_perf_tuning", False): tune_performance(self.device, log=LOG) + self.device.run_as_package = self.config['binary'] + self.remote_test_root = os.path.join(self.device.test_root, "raptor") + self.remote_profile = os.path.join(self.remote_test_root, "profile") if self.config['power_test']: disable_charging(self.device) LOG.info("creating remote root folder for raptor: %s" % self.remote_test_root) - self.device.rm(self.remote_test_root, force=True, recursive=True, root=True) - self.device.mkdir(self.remote_test_root, parents=True, root=True) - self.device.chmod(self.remote_test_root, recursive=True, root=True) + self.device.rm(self.remote_test_root, force=True, recursive=True) + self.device.mkdir(self.remote_test_root, parents=True) self.clear_app_data() self.set_debug_app_flag() @@ -415,9 +415,7 @@ class WebExtensionAndroid(PerftestAndroid, WebExtension): def clean_up(self): LOG.info("removing test folder for raptor: %s" % self.remote_test_root) - # We must use root=True since the browser will have created files in - # the profile. - self.device.rm(self.remote_test_root, force=True, recursive=True, root=True) + self.device.rm(self.remote_test_root, force=True, recursive=True) if self.config['power_test']: enable_charging(self.device) diff --git a/testing/raptor/requirements.txt b/testing/raptor/requirements.txt index 9f90c01b4787..f4aa6c268386 100644 --- a/testing/raptor/requirements.txt +++ b/testing/raptor/requirements.txt @@ -3,7 +3,7 @@ mozrunner ~= 7.0 mozprofile ~= 2.1 manifestparser >= 1.1 wptserve ~= 2.0 -mozdevice >= 3.0.1,<4 +mozdevice >= 4.0.0 mozproxy >= 1.0 pyyaml ~= 3.1 mozpower >= 1.0.0