Merge pull request #130 from Leo-Yan/fix_energy_probe_signal_2
energy_probe: send signal SIGINT to caiman
diff --git a/devlib/instrument/monsoon.py b/devlib/instrument/monsoon.py
index 9d544fd..e373d68 100644
--- a/devlib/instrument/monsoon.py
+++ b/devlib/instrument/monsoon.py
@@ -14,8 +14,8 @@
https://android.googlesource.com/platform/cts/+/master/tools/utils/monsoon.py
Download this script and put it in your $PATH (or pass it as the monsoon_bin
-parameter to MonsoonInstrument). `pip install gflags pyserial` to install the
-dependencies.
+parameter to MonsoonInstrument). `pip install python-gflags pyserial` to install
+the dependencies.
"""
class MonsoonInstrument(Instrument):
diff --git a/devlib/module/cpufreq.py b/devlib/module/cpufreq.py
index d72b8fd..01fb79b 100644
--- a/devlib/module/cpufreq.py
+++ b/devlib/module/cpufreq.py
@@ -421,3 +421,14 @@
sysfile = '/sys/devices/system/cpu/{}/cpufreq/affected_cpus'.format(cpu)
return [int(c) for c in self.target.read_value(sysfile).split()]
+
+ def iter_domains(self):
+ """
+ Iterate over the frequency domains in the system
+ """
+ cpus = set(range(self.target.number_of_cpus))
+ while cpus:
+ cpu = iter(cpus).next()
+ domain = self.target.cpufreq.get_domain_cpus(cpu)
+ yield domain
+ cpus = cpus.difference(domain)
diff --git a/devlib/target.py b/devlib/target.py
index 9d7f282..35473b4 100644
--- a/devlib/target.py
+++ b/devlib/target.py
@@ -4,6 +4,7 @@
import logging
import posixpath
import subprocess
+import tarfile
import tempfile
import threading
from collections import namedtuple
@@ -281,11 +282,34 @@
def pull(self, source, dest, timeout=None):
return self.conn.pull(source, dest, timeout=timeout)
- # execution
+ def get_directory(self, source_dir, dest):
+ """ Pull a directory from the device, after compressing dir """
+ # Create all file names
+ tar_file_name = source_dir.lstrip(self.path.sep).replace(self.path.sep, '.')
+ # Host location of dir
+ outdir = os.path.join(dest, tar_file_name)
+ # Host location of archive
+ tar_file_name = '{}.tar'.format(tar_file_name)
+ tempfile = os.path.join(dest, tar_file_name)
- def _execute_util(self, command, timeout=None, check_exit_code=True, as_root=False):
- command = '{} {}'.format(self.shutils, command)
- return self.conn.execute(command, timeout, check_exit_code, as_root)
+ # Does the folder exist?
+ self.execute('ls -la {}'.format(source_dir))
+ # Try compressing the folder
+ try:
+ self.execute('{} tar -cvf {} {}'.format(self.busybox, tar_file_name,
+ source_dir))
+ except TargetError:
+ self.logger.debug('Failed to run tar command on target! ' \
+ 'Not pulling directory {}'.format(source_dir))
+ # Pull the file
+ os.mkdir(outdir)
+ self.pull(tar_file_name, tempfile )
+ # Decompress
+ f = tarfile.open(tempfile, 'r')
+ f.extractall(outdir)
+ os.remove(tempfile)
+
+ # execution
def execute(self, command, timeout=None, check_exit_code=True, as_root=False):
return self.conn.execute(command, timeout, check_exit_code, as_root)
@@ -556,8 +580,16 @@
else:
raise ValueError('Unknown compression format: {}'.format(ext))
+ def sleep(self, duration):
+ timeout = duration + 10
+ self.execute('sleep {}'.format(duration), timeout=timeout)
+
# internal methods
+ def _execute_util(self, command, timeout=None, check_exit_code=True, as_root=False):
+ command = '{} {}'.format(self.shutils, command)
+ return self.conn.execute(command, timeout, check_exit_code, as_root)
+
def _extract_archive(self, path, cmd, dest=None):
cmd = '{} ' + cmd # busybox
if dest:
@@ -1067,6 +1099,13 @@
if not self.is_screen_on():
self.execute('input keyevent 26')
+ def ensure_screen_is_off(self):
+ if self.is_screen_on():
+ self.execute('input keyevent 26')
+
+ def homescreen(self):
+ self.execute('am start -a android.intent.action.MAIN -c android.intent.category.HOME')
+
def _resolve_paths(self):
if self.working_directory is None:
self.working_directory = '/data/local/tmp/devlib-target'
diff --git a/devlib/trace/ftrace.py b/devlib/trace/ftrace.py
index 7affed5..d4e37e1 100644
--- a/devlib/trace/ftrace.py
+++ b/devlib/trace/ftrace.py
@@ -60,6 +60,7 @@
autoview=False,
no_install=False,
strict=False,
+ report_on_target=False,
):
super(FtraceCollector, self).__init__(target)
self.events = events if events is not None else DEFAULT_EVENTS
@@ -70,7 +71,10 @@
self.automark = automark
self.autoreport = autoreport
self.autoview = autoview
- self.target_output_file = os.path.join(self.target.working_directory, OUTPUT_TRACE_FILE)
+ self.report_on_target = report_on_target
+ self.target_output_file = target.path.join(self.target.working_directory, OUTPUT_TRACE_FILE)
+ text_file_name = target.path.splitext(OUTPUT_TRACE_FILE)[0] + '.txt'
+ self.target_text_file = target.path.join(self.target.working_directory, text_file_name)
self.target_binary = None
self.host_binary = None
self.start_time = None
@@ -93,7 +97,7 @@
if not self.target.is_rooted:
raise TargetError('trace-cmd instrument cannot be used on an unrooted device.')
- if self.autoreport and self.host_binary is None:
+ if self.autoreport and not self.report_on_target and self.host_binary is None:
raise HostError('trace-cmd binary must be installed on the host if autoreport=True.')
if self.autoview and self.kernelshark is None:
raise HostError('kernelshark binary must be installed on the host if autoview=True.')
@@ -202,8 +206,9 @@
def get_trace(self, outfile):
if os.path.isdir(outfile):
- outfile = os.path.join(outfile, os.path.dirname(self.target_output_file))
- self.target.execute('{} extract -o {}'.format(self.target_binary, self.target_output_file),
+ outfile = os.path.join(outfile, os.path.basename(self.target_output_file))
+ self.target.execute('{0} extract -o {1}; chmod 666 {1}'.format(self.target_binary,
+ self.target_output_file),
timeout=TIMEOUT, as_root=True)
# The size of trace.dat will depend on how long trace-cmd was running.
@@ -216,7 +221,12 @@
else:
if self.autoreport:
textfile = os.path.splitext(outfile)[0] + '.txt'
- self.report(outfile, textfile)
+ if self.report_on_target:
+ self.generate_report_on_target()
+ self.target.pull(self.target_text_file,
+ textfile, timeout=pull_timeout)
+ else:
+ self.report(outfile, textfile)
if self.autoview:
self.view(outfile)
@@ -286,6 +296,12 @@
except OSError:
raise HostError('Could not find trace-cmd. Please make sure it is installed and is in PATH.')
+ def generate_report_on_target(self):
+ command = '{} report {} > {}'.format(self.target_binary,
+ self.target_output_file,
+ self.target_text_file)
+ self.target.execute(command, timeout=TIMEOUT)
+
def view(self, binfile):
check_output('{} {}'.format(self.kernelshark, binfile), shell=True)
diff --git a/devlib/utils/android.py b/devlib/utils/android.py
index 5832553..bd49ea4 100644
--- a/devlib/utils/android.py
+++ b/devlib/utils/android.py
@@ -189,7 +189,7 @@
self.ls_command = 'ls -1'
else:
self.ls_command = 'ls'
- logger.info("ls command is set to {}".format(self.ls_command))
+ logger.debug("ls command is set to {}".format(self.ls_command))
def __init__(self, device=None, timeout=None, platform=None):
self.timeout = timeout if timeout is not None else self.default_timeout
diff --git a/devlib/utils/ssh.py b/devlib/utils/ssh.py
index b82680e..8704008 100644
--- a/devlib/utils/ssh.py
+++ b/devlib/utils/ssh.py
@@ -439,26 +439,40 @@
# First check if the connection is set up to interact with gem5
self._check_ready()
- filename = os.path.basename(source)
+ result = self._gem5_shell("ls {}".format(source))
+ files = result.split()
- logger.debug("pull_file {} {}".format(source, filename))
- # We don't check the exit code here because it is non-zero if the source
- # and destination are the same. The ls below will cause an error if the
- # file was not where we expected it to be.
- if os.path.dirname(source) != os.getcwd():
- self._gem5_shell("cat '{}' > '{}'".format(source, filename))
- self._gem5_shell("sync")
- self._gem5_shell("ls -la {}".format(filename))
- logger.debug('Finished the copy in the simulator')
- self._gem5_util("writefile {}".format(filename))
+ for filename in files:
+ dest_file = os.path.basename(filename)
+ logger.debug("pull_file {} {}".format(filename, dest_file))
+ # writefile needs the file to be copied to be in the current
+ # working directory so if needed, copy to the working directory
+ # We don't check the exit code here because it is non-zero if the
+ # source and destination are the same. The ls below will cause an
+ # error if the file was not where we expected it to be.
+ if os.path.isabs(source):
+ if os.path.dirname(source) != self.execute('pwd',
+ check_exit_code=False):
+ self._gem5_shell("cat '{}' > '{}'".format(filename,
+ dest_file))
+ self._gem5_shell("sync")
+ self._gem5_shell("ls -la {}".format(dest_file))
+ logger.debug('Finished the copy in the simulator')
+ self._gem5_util("writefile {}".format(dest_file))
- if 'cpu' not in filename:
- while not os.path.exists(os.path.join(self.gem5_out_dir, filename)):
- time.sleep(1)
+ if 'cpu' not in filename:
+ while not os.path.exists(os.path.join(self.gem5_out_dir,
+ dest_file)):
+ time.sleep(1)
- # Perform the local move
- shutil.move(os.path.join(self.gem5_out_dir, filename), dest)
- logger.debug("Pull complete.")
+ # Perform the local move
+ if os.path.exists(os.path.join(dest, dest_file)):
+ logger.warning(
+ 'Destination file {} already exists!'\
+ .format(dest_file))
+ else:
+ shutil.move(os.path.join(self.gem5_out_dir, dest_file), dest)
+ logger.debug("Pull complete.")
def execute(self, command, timeout=1000, check_exit_code=True,
as_root=False, strip_colors=True):
@@ -468,7 +482,9 @@
# First check if the connection is set up to interact with gem5
self._check_ready()
- output = self._gem5_shell(command, as_root=as_root)
+ output = self._gem5_shell(command,
+ check_exit_code=check_exit_code,
+ as_root=as_root)
if strip_colors:
output = strip_bash_colors(output)
return output
diff --git a/setup.py b/setup.py
index 47a4475..e7753d4 100644
--- a/setup.py
+++ b/setup.py
@@ -74,6 +74,7 @@
extras_require={
'daq': ['daqpower'],
'doc': ['sphinx'],
+ 'monsoon': ['python-gflags'],
},
# https://pypi.python.org/pypi?%3Aaction=list_classifiers
classifiers=[