mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-08 10:44:56 +00:00
Bug 1473997 - find a way to measure the battery usage of geckoview (:bc's initial patch); r=jmaher
Differential Revision: https://phabricator.services.mozilla.com/D14997 --HG-- extra : moz-landing-system : lando
This commit is contained in:
parent
b180b8986c
commit
c2349ad0f8
@ -127,6 +127,11 @@ class Raptor(TestingMixin, MercurialScript, CodeCoverageMixin, AndroidMixin):
|
||||
"dest": "host",
|
||||
"help": "Hostname from which to serve urls (default: 127.0.0.1).",
|
||||
}],
|
||||
[["--power-test"], {
|
||||
"dest": "power_test",
|
||||
"help": "Use Raptor to measure power usage. Currently supported only when "
|
||||
"--host specified for geckoview.",
|
||||
}],
|
||||
[["--debug-mode"], {
|
||||
"dest": "debug_mode",
|
||||
"action": "store_true",
|
||||
@ -196,6 +201,7 @@ class Raptor(TestingMixin, MercurialScript, CodeCoverageMixin, AndroidMixin):
|
||||
self.gecko_profile_entries = self.config.get('gecko_profile_entries')
|
||||
self.test_packages_url = self.config.get('test_packages_url')
|
||||
self.host = self.config.get('host')
|
||||
self.power_test = self.config.get('power_test')
|
||||
self.is_release_build = self.config.get('is_release_build')
|
||||
self.debug_mode = self.config.get('debug_mode', False)
|
||||
|
||||
@ -352,6 +358,8 @@ class Raptor(TestingMixin, MercurialScript, CodeCoverageMixin, AndroidMixin):
|
||||
options.extend(['--code-coverage'])
|
||||
if self.config.get('is_release_build', False):
|
||||
options.extend(['--is-release-build'])
|
||||
if self.config.get('power_test', False):
|
||||
options.extend(['--power-test'])
|
||||
for key, value in kw_options.items():
|
||||
options.extend(['--%s' % key, value])
|
||||
|
||||
|
@ -56,6 +56,7 @@ class RaptorRunner(MozbuildObject):
|
||||
self.python_interp = sys.executable
|
||||
self.raptor_args = raptor_args
|
||||
self.host = kwargs['host']
|
||||
self.power_test = kwargs['power_test']
|
||||
self.is_release_build = kwargs['is_release_build']
|
||||
|
||||
def setup_benchmarks(self):
|
||||
@ -133,6 +134,7 @@ class RaptorRunner(MozbuildObject):
|
||||
'win64': 'python3_x64.manifest',
|
||||
},
|
||||
'host': self.host,
|
||||
'power_test': self.power_test,
|
||||
'is_release_build': self.is_release_build,
|
||||
}
|
||||
|
||||
@ -177,6 +179,7 @@ class MachRaptor(MachCommandBase):
|
||||
|
||||
if conditions.is_android(build_obj) or kwargs['app'] == 'geckoview':
|
||||
from mozrunner.devices.android_device import verify_android_device
|
||||
from mozdevice import ADBAndroid, ADBHost
|
||||
if not verify_android_device(build_obj, install=True, app=kwargs['binary']):
|
||||
return 1
|
||||
|
||||
@ -187,7 +190,28 @@ class MachRaptor(MachCommandBase):
|
||||
raptor = self._spawn(RaptorRunner)
|
||||
|
||||
try:
|
||||
if kwargs['app'] == 'geckoview' and kwargs['power_test']:
|
||||
device = ADBAndroid(verbose=True)
|
||||
adbhost = ADBHost(verbose=True)
|
||||
device_serial = "%s:5555" % device.get_ip_address()
|
||||
device.command_output(["tcpip", "5555"])
|
||||
raw_input("Please disconnect your device from USB then press ENTER...")
|
||||
adbhost.command_output(["connect", device_serial])
|
||||
while len(adbhost.devices()) > 1:
|
||||
raw_input("You must disconnect your device from USB before continuing.")
|
||||
# must reset the environment DEVICE_SERIAL which was set during
|
||||
# verify_android_device to match our new tcpip value.
|
||||
os.environ["DEVICE_SERIAL"] = device_serial
|
||||
return raptor.run_test(sys.argv[2:], kwargs)
|
||||
except Exception as e:
|
||||
print(str(e))
|
||||
return 1
|
||||
finally:
|
||||
try:
|
||||
if kwargs['app'] == 'geckoview' and kwargs['power_test']:
|
||||
raw_input("Connect device via usb and press ENTER...")
|
||||
device = ADBAndroid(device=device_serial, verbose=True)
|
||||
device.command_output(["usb"])
|
||||
adbhost.command_output(["disconnect", device_serial])
|
||||
except Exception:
|
||||
adbhost.command_output(["kill-server"])
|
||||
|
@ -23,6 +23,9 @@ def create_parser(mach_interface=False):
|
||||
add_arg('--host', dest='host',
|
||||
help="Hostname from which to serve urls, defaults to 127.0.0.1.",
|
||||
default='127.0.0.1')
|
||||
add_arg('--power-test', dest="power_test", action="store_true",
|
||||
help="Use Raptor to measure power usage. Currently supported only when "
|
||||
"--host specified for geckoview.")
|
||||
add_arg('--is-release-build', dest="is_release_build", default=False,
|
||||
action='store_true',
|
||||
help="Whether the build is a release build which requires work arounds "
|
||||
@ -78,6 +81,12 @@ def verify_options(parser, args):
|
||||
if args.gecko_profile is True and args.app != "firefox":
|
||||
parser.error("Gecko profiling is only supported when running raptor on Firefox!")
|
||||
|
||||
# if --power-test specified, must be on geckview with --host specified.
|
||||
if args.power_test:
|
||||
if args.app != "geckoview" or args.host in ('localhost', '127.0.0.1'):
|
||||
parser.error("Power test is only supported when running raptor on Geckoview "
|
||||
"when host is specified!")
|
||||
|
||||
|
||||
def parse_args(argv=None):
|
||||
parser = create_parser()
|
||||
|
77
testing/raptor/raptor/power.py
Normal file
77
testing/raptor/raptor/power.py
Normal file
@ -0,0 +1,77 @@
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
from __future__ import absolute_import
|
||||
|
||||
import os
|
||||
import re
|
||||
|
||||
|
||||
def init_geckoview_power_test(raptor):
|
||||
upload_dir = os.getenv('MOZ_UPLOAD_DIR')
|
||||
if not upload_dir:
|
||||
raptor.log.critical("Geckoview power test ignored because MOZ_UPLOAD_DIR was not set")
|
||||
return
|
||||
# Set the screen off timeout to 2 hours since the device will be running
|
||||
# disconnected and would otherwise turn off the screen thereby halting
|
||||
# execution of the test. Save the current value so we can restore it later
|
||||
# since it is a persistent change.
|
||||
raptor.screen_off_timeout = raptor.device.shell_output(
|
||||
"settings get system screen_off_timeout").strip()
|
||||
raptor.device.shell_output("settings put system screen_off_timeout 7200000")
|
||||
raptor.device.shell_output("dumpsys batterystats --reset")
|
||||
raptor.device.shell_output("dumpsys batterystats --enable full-wake-history")
|
||||
filepath = os.path.join(upload_dir, 'battery-before.txt')
|
||||
with open(filepath, 'w') as output:
|
||||
output.write(raptor.device.shell_output("dumpsys battery"))
|
||||
|
||||
|
||||
def finish_geckoview_power_test(raptor):
|
||||
upload_dir = os.getenv('MOZ_UPLOAD_DIR')
|
||||
if not upload_dir:
|
||||
raptor.log.critical("Geckoview power test ignored because MOZ_UPLOAD_DIR was not set")
|
||||
return
|
||||
# Restore the screen off timeout.
|
||||
raptor.device.shell_output(
|
||||
"settings put system screen_off_timeout %s" % raptor.screen_off_timeout)
|
||||
filepath = os.path.join(upload_dir, 'battery-after.txt')
|
||||
with open(filepath, 'w') as output:
|
||||
output.write(raptor.device.shell_output("dumpsys battery"))
|
||||
verbose = raptor.device._verbose
|
||||
raptor.device._verbose = False
|
||||
filepath = os.path.join(upload_dir, 'batterystats.csv')
|
||||
with open(filepath, 'w') as output:
|
||||
output.write(raptor.device.shell_output("dumpsys batterystats --checkin"))
|
||||
filepath = os.path.join(upload_dir, 'batterystats.txt')
|
||||
with open(filepath, 'w') as output:
|
||||
batterystats = raptor.device.shell_output("dumpsys batterystats")
|
||||
output.write(batterystats)
|
||||
raptor.device._verbose = verbose
|
||||
uid = None
|
||||
cpu = wifi = smearing = screen = proportional = 0
|
||||
r_uid = re.compile(r'proc=([^:]+):"%s"' % raptor.config['binary'])
|
||||
batterystats = batterystats.split('\n')
|
||||
for line in batterystats:
|
||||
if uid is None:
|
||||
match = r_uid.search(line)
|
||||
if match:
|
||||
uid = match.group(1)
|
||||
r_power = re.compile(
|
||||
r'\s+Uid %s:\s+[\d.]+ [(] cpu=([\d.]+) wifi=([\d.]+) [)] '
|
||||
r'Including smearing: ([\d.]+)' % uid)
|
||||
else:
|
||||
match = r_power.match(line)
|
||||
if match:
|
||||
(cpu, wifi, smearing) = match.groups()
|
||||
r_screen = re.compile(r'screen=([\d.]+)')
|
||||
match = r_screen.search(line)
|
||||
if match:
|
||||
screen = match.group(1)
|
||||
r_proportional = re.compile(r'proportional=([\d.]+)')
|
||||
match = r_proportional.search(line)
|
||||
if match:
|
||||
proportional = match.group(1)
|
||||
break
|
||||
raptor.log.info('uid: %s, cpu: %s, wifi: %s, screen: %s, proportional: %s' %
|
||||
(uid, cpu, wifi, screen, proportional))
|
||||
raptor.device.command_output(["bugreport", upload_dir])
|
@ -46,6 +46,7 @@ from manifest import get_raptor_test_list
|
||||
from playback import get_playback
|
||||
from results import RaptorResultsHandler
|
||||
from gecko_profile import GeckoProfile
|
||||
from power import init_geckoview_power_test, finish_geckoview_power_test
|
||||
|
||||
|
||||
class Raptor(object):
|
||||
@ -53,7 +54,8 @@ class Raptor(object):
|
||||
|
||||
def __init__(self, app, binary, run_local=False, obj_path=None,
|
||||
gecko_profile=False, gecko_profile_interval=None, gecko_profile_entries=None,
|
||||
symbols_path=None, host=None, is_release_build=False, debug_mode=False):
|
||||
symbols_path=None, host=None, power_test=False, is_release_build=False,
|
||||
debug_mode=False):
|
||||
self.config = {}
|
||||
self.config['app'] = app
|
||||
self.config['binary'] = binary
|
||||
@ -66,6 +68,7 @@ class Raptor(object):
|
||||
self.config['gecko_profile_entries'] = gecko_profile_entries
|
||||
self.config['symbols_path'] = symbols_path
|
||||
self.config['host'] = host
|
||||
self.config['power_test'] = power_test
|
||||
self.config['is_release_build'] = is_release_build
|
||||
self.raptor_venv = os.path.join(os.getcwd(), 'raptor-venv')
|
||||
self.log = get_default_logger(component='raptor-main')
|
||||
@ -114,6 +117,8 @@ class Raptor(object):
|
||||
self.log.info("creating android device handler using mozdevice")
|
||||
self.device = ADBDevice(verbose=True)
|
||||
self.device.clear_logcat()
|
||||
if self.config['power_test']:
|
||||
init_geckoview_power_test(self)
|
||||
else:
|
||||
# create the desktop browser runner
|
||||
self.log.info("creating browser runner using mozrunner")
|
||||
@ -290,6 +295,8 @@ class Raptor(object):
|
||||
fail_if_running=False)
|
||||
except Exception:
|
||||
self.log.error("Exception launching %s" % self.config['binary'])
|
||||
if self.config['power_test']:
|
||||
finish_geckoview_power_test(self)
|
||||
raise
|
||||
self.control_server.device = self.device
|
||||
self.control_server.app_name = self.config['binary']
|
||||
@ -375,12 +382,15 @@ class Raptor(object):
|
||||
self.control_server.wait_for_quit()
|
||||
break
|
||||
finally:
|
||||
if self.config['app'] != "geckoview":
|
||||
if self.config['app'] == "geckoview":
|
||||
# TODO: if on geckoview is there some cleanup here i.e. check for crashes?
|
||||
if self.config['power_test']:
|
||||
finish_geckoview_power_test(self)
|
||||
else:
|
||||
try:
|
||||
self.runner.check_for_crashes()
|
||||
except NotImplementedError: # not implemented for Chrome
|
||||
pass
|
||||
# TODO: if on geckoview is there some cleanup here i.e. check for crashes?
|
||||
|
||||
if self.playback is not None:
|
||||
self.playback.stop()
|
||||
@ -543,6 +553,7 @@ def main(args=sys.argv[1:]):
|
||||
gecko_profile_entries=args.gecko_profile_entries,
|
||||
symbols_path=args.symbols_path,
|
||||
host=args.host,
|
||||
power_test=args.power_test,
|
||||
is_release_build=args.is_release_build,
|
||||
debug_mode=args.debug_mode)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user