1
0
mirror of https://github.com/ARM-software/workload-automation.git synced 2025-02-07 13:41:24 +00:00

RecordCommand: Improved record command to handle workloads

The wa record command now has the ability to record revent files for wa
workload.

The command with automatically deploy the workload and record both
setup and run revent recordings

Conflicts:
	wlauto/commands/record.py
This commit is contained in:
Sebastian Goscik 2016-02-25 11:30:14 +00:00
parent 98b46894d8
commit 0057a531fd
2 changed files with 109 additions and 44 deletions

View File

@ -16,11 +16,15 @@
import os import os
import sys import sys
from wlauto import Command, settings
from wlauto.core import pluginloader
from wlauto.common.resources import Executable from wlauto.common.resources import Executable
from wlauto.core.resource import NO_ONE from wlauto.core.resource import NO_ONE
from wlauto.core.resolver import ResourceResolver from wlauto.core.resolver import ResourceResolver
from wlauto.core.configuration import RunConfiguration from wlauto.core.configuration import RunConfiguration
from wlauto.core.agenda import Agenda from wlauto.core.agenda import Agenda
from wlauto.common.android.workload import ApkWorkload
class RecordCommand(Command): class RecordCommand(Command):
@ -50,78 +54,126 @@ class RecordCommand(Command):
def initialize(self, context): def initialize(self, context):
self.context = context self.context = context
self.parser.add_argument('-d', '--device', help='The name of the device') self.parser.add_argument('-d', '--device', help='The name of the device')
self.parser.add_argument('-s', '--suffix', help='The suffix of the revent file, e.g. ``setup``')
self.parser.add_argument('-o', '--output', help='Directory to save the recording in') self.parser.add_argument('-o', '--output', help='Directory to save the recording in')
self.parser.add_argument('-p', '--package', help='Package to launch before recording')
# Need validation
self.parser.add_argument('-s', '--suffix', help='The suffix of the revent file, e.g. ``setup``')
self.parser.add_argument('-C', '--clear', help='Clear app cache before launching it', self.parser.add_argument('-C', '--clear', help='Clear app cache before launching it',
action="store_true") action="store_true")
group = self.parser.add_mutually_exclusive_group(required=False)
group.add_argument('-p', '--package', help='Package to launch before recording')
group.add_argument('-w', '--workload', help='Name of a revent workload (mostly games)')
# Validate command options # Validate command options
def validate_args(self, args): def validate_args(self, args):
if args.clear and not args.package: if args.clear and not (args.package or args.workload):
print "Package must be specified if you want to clear cache\n" self.logger.error("Package/Workload must be specified if you want to clear cache")
self.parser.print_help() self.parser.print_help()
sys.exit() sys.exit()
if args.workload and args.suffix:
self.logger.error("cannot specify manual suffixes for workloads")
self.parser.print_help()
sys.exit()
if args.suffix:
args.suffix += "."
# pylint: disable=W0201 # pylint: disable=W0201
def execute(self, args): def execute(self, args):
self.validate_args(args) self.validate_args(args)
self.logger.info("Connecting to device...") self.logger.info("Connecting to device...")
ext_loader = PluginLoader(packages=settings.plugin_packages,
paths=settings.plugin_paths)
# Setup config # Setup config
self.config = RunConfiguration(ext_loader) self.config = RunConfiguration(pluginloader)
for filepath in settings.get_config_paths(): for filepath in settings.config_paths:
self.config.load_config(filepath) self.config.load_config(filepath)
self.config.set_agenda(Agenda()) self.config.set_agenda(Agenda())
self.config.finalize() self.config.finalize()
context = LightContext(self.config)
# Setup device # Setup device
self.device = ext_loader.get_device(settings.device, **settings.device_config) self.device_manager = pluginloader.get_manager(self.config.device)
self.device.validate() self.device_manager.validate()
self.device.connect() self.device_manager.connect()
self.device.initialize(context) context = LightContext(self.config, self.device_manager)
self.device_manager.initialize(context)
host_binary = context.resolver.get(Executable(NO_ONE, self.device.abi, 'revent')) self.device = self.device_manager.target
self.target_binary = self.device.install_if_needed(host_binary)
self.run(args)
def run(self, args):
if args.device: if args.device:
self.device_name = args.device self.device_name = args.device
else: else:
self.device_name = self.device.get_device_model() self.device_name = self.device.model
if args.suffix: # Install Revent
args.suffix += "." host_binary = context.resolver.get(Executable(NO_ONE, self.device.abi, 'revent'))
self.target_binary = self.device.install_if_needed(host_binary)
revent_file = self.device.path.join(self.device.working_directory, if args.workload:
'{}.{}revent'.format(self.device_name, args.suffix or "")) self.workload_record(args, context)
elif args.package:
self.package_record(args, context)
else:
self.manual_record(args, context)
def manual_record(self, args, context):
revent_file = self.device.get_workpath('{}.{}revent'.format(self.device_name, args.suffix or ""))
self._record(revent_file, "", args.output)
def package_record(self, args, context):
revent_file = self.device.get_workpath('{}.{}revent'.format(self.device_name, args.suffix or ""))
if args.clear: if args.clear:
self.device.execute("pm clear {}".format(args.package)) self.device.execute("pm clear {}".format(args.package))
if args.package: self.logger.info("Starting {}".format(args.package))
self.logger.info("Starting {}".format(args.package)) self.device.execute('monkey -p {} -c android.intent.category.LAUNCHER 1'.format(args.package))
self.device.execute('monkey -p {} -c android.intent.category.LAUNCHER 1'.format(args.package))
self.logger.info("Press Enter when you are ready to record...") self._record(revent_file, "", args.output)
def workload_record(self, args, context):
setup_file = self.device.get_workpath('{}.setup.revent'.format(self.device_name))
run_file = self.device.get_workpath('{}.run.revent'.format(self.device_name))
self.logger.info("Deploying {}".format(args.workload))
workload = pluginloader.get_workload(args.workload, self.device)
workload.apk_init_resources(context)
workload.initialize_package(context)
workload.do_post_install(context)
workload.start_activity()
if args.clear:
workload.reset(context)
self._record(setup_file, " SETUP",
args.output or os.path.join(workload.dependencies_directory, 'revent_files'))
self._record(run_file, " RUN",
args.output or os.path.join(workload.dependencies_directory, 'revent_files'))
self.logger.info("Tearing down {}".format(args.workload))
workload.apk_teardown(context)
def _record(self, revent_file, name, output_path):
self.logger.info("Press Enter when you are ready to record{}...".format(name))
raw_input("") raw_input("")
command = "{} record -t 100000 -s {}".format(self.target_binary, revent_file) command = "{} record -t 100000 -s {}".format(self.target_binary, revent_file)
self.device.kick_off(command) self.device.kick_off(command)
self.logger.info("Press Enter when you have finished recording...") self.logger.info("Press Enter when you have finished recording {}...".format(name))
raw_input("") raw_input("")
self.device.killall("revent") self.device.killall("revent")
self.logger.info("Pulling files from device") output_path = output_path or os.getcwdu()
self.device.pull(revent_file, args.output or os.getcwdu()) if not os.path.isdir(output_path):
os.mkdirs(output_path)
revent_file_name = self.device.path.basename(revent_file)
host_path = os.path.join(output_path, revent_file_name)
if os.path.exists(host_path):
self.logger.info("Revent file '{}' already exists, overwrite? [y/n]".format(revent_file_name))
if raw_input("") == "y":
os.remove(host_path)
else:
self.logger.warning("Did not pull and overwrite '{}'".format(revent_file_name))
return
self.logger.info("Pulling '{}' from device".format(self.device.path.basename(revent_file)))
self.device.pull(revent_file, output_path)
class ReplayCommand(RecordCommand): class ReplayCommand(RecordCommand):
@ -139,6 +191,7 @@ class ReplayCommand(RecordCommand):
self.parser.add_argument('-C', '--clear', help='Clear app cache before launching it', self.parser.add_argument('-C', '--clear', help='Clear app cache before launching it',
action="store_true") action="store_true")
# pylint: disable=W0201 # pylint: disable=W0201
def run(self, args): def run(self, args):
self.logger.info("Pushing file to device") self.logger.info("Pushing file to device")
@ -159,6 +212,7 @@ class ReplayCommand(RecordCommand):
# Used to satisfy the API # Used to satisfy the API
class LightContext(object): class LightContext(object):
def __init__(self, config): def __init__(self, config, device_manager):
self.resolver = ResourceResolver(config) self.resolver = ResourceResolver(config)
self.resolver.load() self.resolver.load()
self.device_manager = device_manager

View File

@ -301,19 +301,24 @@ class ReventWorkload(Workload):
default_setup_timeout = 5 * 60 # in seconds default_setup_timeout = 5 * 60 # in seconds
default_run_timeout = 10 * 60 # in seconds default_run_timeout = 10 * 60 # in seconds
@property
def on_device_setup_revent(self):
return self.device.get_workpath('{}.setup.revent'.format(self.device.model))
@property
def on_device_run_revent(self):
return self.device.get_workpath('{}.run.revent'.format(self.device.model))
def __init__(self, device, _call_super=True, **kwargs): def __init__(self, device, _call_super=True, **kwargs):
if _call_super: if _call_super:
super(ReventWorkload, self).__init__(device, **kwargs) super(ReventWorkload, self).__init__(device, **kwargs)
devpath = self.device.path self.on_device_revent_binary = None
self.on_device_revent_binary = devpath.join(self.device.binaries_directory, 'revent')
self.on_device_setup_revent = devpath.join(self.device.working_directory, '{}.setup.revent'.format(self.device.name))
self.on_device_run_revent = devpath.join(self.device.working_directory, '{}.run.revent'.format(self.device.name))
self.setup_timeout = kwargs.get('setup_timeout', self.default_setup_timeout) self.setup_timeout = kwargs.get('setup_timeout', self.default_setup_timeout)
self.run_timeout = kwargs.get('run_timeout', self.default_run_timeout) self.run_timeout = kwargs.get('run_timeout', self.default_run_timeout)
self.revent_setup_file = None self.revent_setup_file = None
self.revent_run_file = None self.revent_run_file = None
def init_resources(self, context): def initialize(self, context):
self.revent_setup_file = context.resolver.get(wlauto.common.android.resources.ReventFile(self, 'setup')) self.revent_setup_file = context.resolver.get(wlauto.common.android.resources.ReventFile(self, 'setup'))
self.revent_run_file = context.resolver.get(wlauto.common.android.resources.ReventFile(self, 'run')) self.revent_run_file = context.resolver.get(wlauto.common.android.resources.ReventFile(self, 'run'))
@ -433,8 +438,11 @@ class GameWorkload(ApkWorkload, ReventWorkload):
self.module_dir = os.path.dirname(sys.modules[self.__module__].__file__) self.module_dir = os.path.dirname(sys.modules[self.__module__].__file__)
self.revent_dir = os.path.join(self.module_dir, 'revent_files') self.revent_dir = os.path.join(self.module_dir, 'revent_files')
def init_resources(self, context): def apk_init_resources(self, context):
ApkWorkload.init_resources(self, context) ApkWorkload.init_resources(self, context)
def init_resources(self, context):
self.apk_init_resources(context)
ReventWorkload.init_resources(self, context) ReventWorkload.init_resources(self, context)
def setup(self, context): def setup(self, context):
@ -461,11 +469,14 @@ class GameWorkload(ApkWorkload, ReventWorkload):
def run(self, context): def run(self, context):
ReventWorkload.run(self, context) ReventWorkload.run(self, context)
def teardown(self, context): def apk_teardown(self, context):
if not self.saved_state_file: if not self.saved_state_file:
ApkWorkload.teardown(self, context) ApkWorkload.teardown(self, context)
else: else:
self.device.execute('am force-stop {}'.format(self.package)) self.device.execute('am force-stop {}'.format(self.package))
def teardown(self, context):
self.apk_teardown(context)
ReventWorkload.teardown(self, context) ReventWorkload.teardown(self, context)
def _deploy_assets(self, context, timeout=300): def _deploy_assets(self, context, timeout=300):
@ -478,7 +489,7 @@ class GameWorkload(ApkWorkload, ReventWorkload):
kind = 'data' kind = 'data'
if ':' in resource_file: if ':' in resource_file:
kind, resource_file = resource_file.split(':', 1) kind, resource_file = resource_file.split(':', 1)
ondevice_cache = self.device.path.join(self.device.resource_cache, self.name, resource_file) ondevice_cache = self.device.path.join(self.device.working_directory, '.cache', self.name, resource_file)
if not self.device.file_exists(ondevice_cache): if not self.device.file_exists(ondevice_cache):
asset_tarball = context.resolver.get(PluginAsset(self, resource_file)) asset_tarball = context.resolver.get(PluginAsset(self, resource_file))
if not asset_tarball: if not asset_tarball:
@ -488,7 +499,7 @@ class GameWorkload(ApkWorkload, ReventWorkload):
# exist. # exist.
self.device.push(asset_tarball, ondevice_cache, timeout=timeout) self.device.push(asset_tarball, ondevice_cache, timeout=timeout)
device_asset_directory = self.device.path.join(self.context.device_manager.external_storage_directory, 'Android', kind) device_asset_directory = self.device.path.join(context.device_manager.external_storage_directory, 'Android', kind)
deploy_command = 'cd {} && {} tar -xzf {}'.format(device_asset_directory, deploy_command = 'cd {} && {} tar -xzf {}'.format(device_asset_directory,
self.device.busybox, self.device.busybox,
ondevice_cache) ondevice_cache)