Merge branch 'master' of ssh://github.com/ARM-software/devlib
Change-Id: I6d3051f6ef0e49ea2efb26daec42ff1cd0dce8b0
diff --git a/devlib/bin/scripts/shutils.in b/devlib/bin/scripts/shutils.in
index 49d7407..c6ef572 100755
--- a/devlib/bin/scripts/shutils.in
+++ b/devlib/bin/scripts/shutils.in
@@ -177,6 +177,16 @@
exit 0
}
+cgroup_trace_attach_task() {
+ DST_ROOT=${1}
+ DST_PATH=${2}
+ TASKS_FILE=${3}
+
+ cat $TASKS_FILE | while read PID; do
+ echo "cgroup_attach_task_devlib: dst_root=$DST_ROOT dst_path=$DST_PATH pid=$PID" > /sys/kernel/debug/tracing/trace_marker
+ done
+}
+
cgroups_freezer_set_state() {
STATE=${1}
SYSFS_ENTRY=${2}/freezer.state
@@ -253,6 +263,9 @@
cpufreq_trace_all_frequencies)
cpufreq_trace_all_frequencies $*
;;
+cgroup_trace_attach_task)
+ cgroup_trace_attach_task $*
+ ;;
cpuidle_wake_all_cpus)
cpuidle_wake_all_cpus $*
;;
diff --git a/devlib/instrument/monsoon.py b/devlib/instrument/monsoon.py
index 3103618..ceaa627 100644
--- a/devlib/instrument/monsoon.py
+++ b/devlib/instrument/monsoon.py
@@ -61,6 +61,8 @@
if self.process:
self.process.kill()
+ os.system(self.monsoon_bin + ' --usbpassthrough off')
+
cmd = [self.monsoon_bin,
'--hz', str(self.sample_rate_hz),
'--samples', '-1', # -1 means sample indefinitely
@@ -97,6 +99,11 @@
self.buffer_file = None
self.output = (stdout, stderr)
+ os.system(self.monsoon_bin + ' --usbpassthrough on')
+
+ # Wait for USB connection to be restored
+ print ('waiting for usb connection to be back')
+ os.system('adb wait-for-device')
def get_data(self, outfile):
if self.process:
diff --git a/devlib/module/cgroups.py b/devlib/module/cgroups.py
index 8987899..ff930fa 100644
--- a/devlib/module/cgroups.py
+++ b/devlib/module/cgroups.py
@@ -287,6 +287,11 @@
logging.debug('Tasks: %s', task_ids)
return map(int, task_ids)
+ # Used to insert fake cgroup attach events to know existing cgroup assignments
+ def trace_cgroup_tasks(self):
+ exec_cmd = "cgroup_trace_attach_task {} {} {}".format(self.controller.hid, self.directory, self.tasks_file)
+ self.target._execute_util(exec_cmd)
+
def add_task(self, tid):
self.target.write_value(self.tasks_file, tid, verify=False)
diff --git a/devlib/module/cpufreq.py b/devlib/module/cpufreq.py
index a8028f3..5ce3c83 100644
--- a/devlib/module/cpufreq.py
+++ b/devlib/module/cpufreq.py
@@ -12,6 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
+import json
from devlib.module import Module
from devlib.exception import TargetError
from devlib.utils.misc import memoized
@@ -445,3 +446,55 @@
domain = self.target.cpufreq.get_related_cpus(cpu)
yield domain
cpus = cpus.difference(domain)
+
+ def get_time_in_state(self, clusters):
+ """
+ Gets the time at each frequency on each cluster
+ :param clusters: A list of clusters on the device. Each cluster is a
+ list of cpus on that cluster.
+ """
+ time_in_state_by_cluster = {}
+
+ for i, cluster in enumerate(clusters):
+ frequencies = self.list_frequencies(cluster[0])
+ time_in_state = dict((str(freq), 0) for freq in frequencies)
+
+ for cpu in cluster:
+ stats = self.target.execute('cat '\
+ '/sys/devices/system/cpu/cpu{}/cpufreq/stats'
+ '/time_in_state'.format(cpu))
+ for entry in stats.split('\n'):
+ if len(entry) > 0:
+ freq, time = entry.split(' ')
+ time_in_state[freq] += int(time)
+
+ time_in_state_by_cluster[str(i)] = time_in_state
+
+ return time_in_state_by_cluster
+
+ def dump_time_in_state_delta(self, start, clusters, dump_file):
+ """
+ Dumps the time between the stop and start by cluster by frequency
+ :param start: The inital output from a call to cpufreq.get_time_in_state
+ :param clusters: A list of clusters on the device. Each cluster is a
+ list of cpus on that cluster.
+ :param dump_file: A file to dump the delta time_in_state_delta to.
+ """
+ stop = self.get_time_in_state(clusters)
+
+ time_in_state_delta = {}
+
+ for cl in start:
+ time_in_state_delta[cl] = {}
+
+ for freq in start[cl].keys():
+ time_in_start = start[cl][freq]
+ time_in_stop = stop[cl][freq]
+ time_in_state_delta[cl][freq] = time_in_stop - time_in_start
+
+ output = {'time_delta' : time_in_state_delta,
+ 'clusters' : {str(i) : [str(c) for c in cl]
+ for i, cl in enumerate(clusters)}}
+
+ with open(dump_file, 'w') as dfile:
+ json.dump(output, dfile, indent=4, sort_keys=True)
diff --git a/devlib/utils/android.py b/devlib/utils/android.py
index 14cb253..bdf2854 100644
--- a/devlib/utils/android.py
+++ b/devlib/utils/android.py
@@ -508,7 +508,15 @@
logger.debug('Discovering ANDROID_HOME from adb path.')
env.platform_tools = os.path.dirname(adb_full_path)
env.android_home = os.path.dirname(env.platform_tools)
- _init_common(env)
+ try:
+ _init_common(env)
+ except:
+ env.aapt = which('aapt')
+ if env.aapt:
+ logger.info('Using aapt: ' + env.aapt)
+ else:
+ raise RuntimeError('aapt not found, try setting ANDROID_HOME to \
+ Android SDK or run LISA from android environment')
return env
diff --git a/devlib/utils/android_build.py b/devlib/utils/android_build.py
new file mode 100644
index 0000000..de638ba
--- /dev/null
+++ b/devlib/utils/android_build.py
@@ -0,0 +1,56 @@
+# SPDX-License-Identifier: Apache-2.0
+#
+# Copyright (C) 2015, ARM Limited and contributors.
+#
+# 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.
+#
+
+import logging
+import os
+import shutil
+import subprocess
+from collections import namedtuple
+
+class Build(object):
+ """
+ Collection of Android related build actions
+ """
+ def __init__(self, te):
+ if (te.ANDROID_BUILD_TOP and te.TARGET_PRODUCT and te.TARGET_BUILD_VARIANT):
+ self._te = te
+ else:
+ te._log.warning('Build initialization failed: invalid paramterers')
+ raise
+
+ def exec_cmd(self, cmd):
+ ret = subprocess.call(cmd, shell=True)
+ if ret != 0:
+ raise RuntimeError('Command \'{}\' returned error code {}'.format(cmd, ret))
+
+ def build_module(self, module_path):
+ """
+ Build a module and its dependencies.
+
+ :param module_path: module path
+ :type module_path: str
+
+ """
+ cur_dir = os.getcwd()
+ os.chdir(self._te.ANDROID_BUILD_TOP)
+ lunch_target = self._te.TARGET_PRODUCT + '-' + self._te.TARGET_BUILD_VARIANT
+ self.exec_cmd('source build/envsetup.sh && lunch ' +
+ lunch_target + ' && mmma -j16 ' + module_path)
+ os.chdir(cur_dir)
+
+
+# vim :set tabstop=4 shiftwidth=4 expandtab