1
0
mirror of https://github.com/ARM-software/workload-automation.git synced 2025-01-19 04:21:17 +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 sys
from wlauto import Command, settings
from wlauto.core import pluginloader
from wlauto.common.resources import Executable
from wlauto.core.resource import NO_ONE
from wlauto.core.resolver import ResourceResolver
from wlauto.core.configuration import RunConfiguration
from wlauto.core.agenda import Agenda
from wlauto.common.android.workload import ApkWorkload
class RecordCommand(Command):
@ -50,78 +54,126 @@ class RecordCommand(Command):
def initialize(self, context):
self.context = context
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('-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',
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
def validate_args(self, args):
if args.clear and not args.package:
print "Package must be specified if you want to clear cache\n"
if args.clear and not (args.package or args.workload):
self.logger.error("Package/Workload must be specified if you want to clear cache")
self.parser.print_help()
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
def execute(self, args):
self.validate_args(args)
self.logger.info("Connecting to device...")
ext_loader = PluginLoader(packages=settings.plugin_packages,
paths=settings.plugin_paths)
# Setup config
self.config = RunConfiguration(ext_loader)
for filepath in settings.get_config_paths():
self.config = RunConfiguration(pluginloader)
for filepath in settings.config_paths:
self.config.load_config(filepath)
self.config.set_agenda(Agenda())
self.config.finalize()
context = LightContext(self.config)
# Setup device
self.device = ext_loader.get_device(settings.device, **settings.device_config)
self.device.validate()
self.device.connect()
self.device.initialize(context)
host_binary = context.resolver.get(Executable(NO_ONE, self.device.abi, 'revent'))
self.target_binary = self.device.install_if_needed(host_binary)
self.run(args)
def run(self, args):
self.device_manager = pluginloader.get_manager(self.config.device)
self.device_manager.validate()
self.device_manager.connect()
context = LightContext(self.config, self.device_manager)
self.device_manager.initialize(context)
self.device = self.device_manager.target
if args.device:
self.device_name = args.device
else:
self.device_name = self.device.get_device_model()
self.device_name = self.device.model
if args.suffix:
args.suffix += "."
# Install Revent
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,
'{}.{}revent'.format(self.device_name, args.suffix or ""))
if args.workload:
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:
self.device.execute("pm clear {}".format(args.package))
if args.package:
self.logger.info("Starting {}".format(args.package))
self.device.execute('monkey -p {} -c android.intent.category.LAUNCHER 1'.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.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("")
command = "{} record -t 100000 -s {}".format(self.target_binary, revent_file)
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("")
self.device.killall("revent")
self.logger.info("Pulling files from device")
self.device.pull(revent_file, args.output or os.getcwdu())
output_path = output_path 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):
@ -139,6 +191,7 @@ class ReplayCommand(RecordCommand):
self.parser.add_argument('-C', '--clear', help='Clear app cache before launching it',
action="store_true")
# pylint: disable=W0201
def run(self, args):
self.logger.info("Pushing file to device")
@ -159,6 +212,7 @@ class ReplayCommand(RecordCommand):
# Used to satisfy the API
class LightContext(object):
def __init__(self, config):
def __init__(self, config, device_manager):
self.resolver = ResourceResolver(config)
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_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):
if _call_super:
super(ReventWorkload, self).__init__(device, **kwargs)
devpath = self.device.path
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.on_device_revent_binary = None
self.setup_timeout = kwargs.get('setup_timeout', self.default_setup_timeout)
self.run_timeout = kwargs.get('run_timeout', self.default_run_timeout)
self.revent_setup_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_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.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)
def init_resources(self, context):
self.apk_init_resources(context)
ReventWorkload.init_resources(self, context)
def setup(self, context):
@ -461,11 +469,14 @@ class GameWorkload(ApkWorkload, ReventWorkload):
def run(self, context):
ReventWorkload.run(self, context)
def teardown(self, context):
def apk_teardown(self, context):
if not self.saved_state_file:
ApkWorkload.teardown(self, context)
else:
self.device.execute('am force-stop {}'.format(self.package))
def teardown(self, context):
self.apk_teardown(context)
ReventWorkload.teardown(self, context)
def _deploy_assets(self, context, timeout=300):
@ -478,7 +489,7 @@ class GameWorkload(ApkWorkload, ReventWorkload):
kind = 'data'
if ':' in resource_file:
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):
asset_tarball = context.resolver.get(PluginAsset(self, resource_file))
if not asset_tarball:
@ -488,7 +499,7 @@ class GameWorkload(ApkWorkload, ReventWorkload):
# exist.
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,
self.device.busybox,
ondevice_cache)