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
This commit is contained in:
Bob Clary 2020-07-16 21:32:55 +00:00
parent fe2f5c00e6
commit d88869442f
7 changed files with 58 additions and 38 deletions

View File

@ -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

View File

@ -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)

View File

@ -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)

View File

@ -577,8 +577,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)
@ -656,12 +656,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.")

View File

@ -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

View File

@ -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)

View File

@ -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