# Copyright 2016 ARM Limited # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # from __future__ import division import os import struct import signal from datetime import datetime from collections import namedtuple from wa.framework.resource import Executable, NO_ONE, ResourceResolver GENERAL_MODE = 0 GAMEPAD_MODE = 1 u16_struct = struct.Struct(' self.version >= 0: self.mode = GENERAL_MODE self._read_devices(fh) else: raise ValueError('Invalid recording version: {}'.format(self.version)) def _read_devices(self, fh): num_devices, = read_struct(fh, u32_struct) for _ in xrange(num_devices): self.device_paths.append(read_string(fh)) def _read_gamepad_info(self, fh): self.gamepad_device = UinputDeviceInfo(fh) self.device_paths.append('[GAMEPAD]') def _iter_events(self): if self.fh is None: msg = 'Attempting to iterate over events of a closed recording' raise RuntimeError(msg) self.fh.seek(self._events_start) if self.version >= 2: for _ in xrange(self.num_events): yield ReventEvent(self.fh) else: file_size = os.path.getsize(self.filepath) while self.fh.tell() < file_size: yield ReventEvent(self.fh, legacy=True) def __iter__(self): for event in self.events: yield event def __enter__(self): return self def __exit__(self, *args): self.close() def __del__(self): self.close() def get_revent_binary(abi): resolver = ResourceResolver() resolver.load() resource = Executable(NO_ONE, abi, 'revent') return resolver.get(resource) class ReventRecorder(object): def __init__(self, target): self.target = target self.executable = self.target.get_installed('revent') def deploy(self): if not self.executable: host_executable = get_revent_binary(self.target.abi) self.executable = self.target.install(host_executable) def remove(self): if self.executable: self.target.uninstall('revent') def start_record(self, revent_file): command = '{} record -s {}'.format(self.executable, revent_file) self.target.kick_off(command, self.target.is_rooted) def stop_record(self): self.target.killall('revent', signal.SIGINT, as_root=self.target.is_rooted) def replay(self, revent_file, timeout=None): self.target.killall('revent') command = "{} replay {}".format(self.executable, revent_file) self.target.execute(command, timeout=timeout)