blob: bc71ca371834cacf78a5d2ed5dc26b8a4df0afaf [file] [log] [blame]
#!/bin/bash
# Copyright (C) 2018 The Android Open Source Project
#
# 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.
set -e
SCRIPT_DIR="$(realpath "$(dirname "${BASH_SOURCE[0]}")")"
if [ "$TMPDIR" == "" ]; then
TMPDIR=/tmp
fi
function get_gn_value() {
local out=$1
local key=$2
"$SCRIPT_DIR/gn" args "$out" --list=$key --short | awk '{print $3}' \
| tr -d '"'
}
function is_monolithic() {
local out=$1
value=$(get_gn_value "$out" "monolithic_binaries")
test "$value" == "true"
}
function is_android() {
local out=$1
value=$(get_gn_value "$out" "target_os")
test "$value" == "android"
}
function is_ssh_target() {
[[ -n "$SSH_TARGET" ]]
}
function is_mac() {
# shellcheck disable=2251
! test -d /proc
return $?
}
function tmux_ensure_bash() {
if [[ $SHELL == *"fish" ]]; then
tmux send-keys "bash" Enter
fi
}
function reset_tracing() {
if is_android "$OUT"; then
# Newer versions of Android don't have debugfs mounted at all
# anymore so use /sys/kernel/tracing if /d/tracing doesn't exist
adb shell 'test -d /sys/kernel/tracing && echo 0 > /sys/kernel/tracing/tracing_on || echo 0 > /sys/kernel/debug/tracing/tracing_on'
elif ! is_mac; then
# shellcheck disable=SC2016
local script='
if [ ! -w /sys/kernel/debug ]; then
echo "debugfs not accessible, try sudo chown -R $USER /sys/kernel/debug"
sudo chown -R "$USER" /sys/kernel/debug
fi
echo 0 > /sys/kernel/debug/tracing/tracing_on
'
if is_ssh_target; then
# shellcheck disable=SC2029
ssh -t "$SSH_TARGET" "sh -c '$script'"
else
sh -c "$script"
fi
fi
}
function adb_supports_push_sync() {
adb --help 2>&1 | grep 'push.*\[--sync\]' >/dev/null 2>&1
}
function push() {
if is_android "$OUT"; then
local maybe_sync=''
if adb_supports_push_sync; then
maybe_sync='--sync'
fi
echo adb push $maybe_sync "$1" "$DIR"
adb push $maybe_sync "$1" "$DIR"
elif is_ssh_target; then
echo scp "$1" "$SSH_TARGET:$DIR"
scp "$1" "$SSH_TARGET:$DIR"
else
echo cp "$1" "$DIR"
cp "$1" "$DIR"
fi
}
function pull() {
if is_android "$OUT"; then
echo adb pull "$DIR/$1" "$2"
adb pull "$DIR/$1" "$2"
elif is_ssh_target; then
echo scp "$SSH_TARGET:$DIR/$1" "$2"
scp "$SSH_TARGET:$DIR/$1" "$2"
else
echo mv "$DIR/$1" "$2"
mv "$DIR/$1" "$2"
fi
}
BACKGROUND=0
SKIP_CONVERTERS=0
TMUX_LAYOUT="even-vertical"
CPU_MASK=""
while getopts "bl:nt:c:C:z:s:" o; do
case "$o" in
b) BACKGROUND=1 ;;
l) TMUX_LAYOUT=${OPTARG} ;;
n) SKIP_CONVERTERS=1 ;;
t) SSH_TARGET=${OPTARG} ;;
c) CONFIG=${OPTARG} ;;
C) OUT=${OPTARG} ;;
z) CPU_MASK=${OPTARG} ;;
s) SCRIPT=${OPTARG} ;;
*)
echo >&2 "Invalid option $o"
exit
;;
esac
done
# Allow out to be passed as argument
shift $((OPTIND - 1))
OUT="${OUT:-$1}"
# Provide useful usage information
if [ -z "$OUT" ]; then
echo "Usage: $0 [OPTION]... [OUTPUT]"
echo ""
echo "Options:"
echo " -b run in the background"
echo " -l LAYOUT tmux pane layout"
echo " -n skip post-trace convertors"
echo " -t TARGET SSH device target"
echo " -c CONFIG trace configuration file"
echo " -C OUTPUT output directory"
echo " -z MASK constrain binaries to given cpu mask (taskset syntax)"
echo " -s SCRIPT a script to put into a tmux pane"
echo ""
echo "Environment variables:"
echo " SSH_TARGET SSH device target"
echo " CONFIG trace configuration file"
echo " OUT output directory"
exit 1
fi
# Warn about invalid output directories
if [ ! -f "$OUT/args.gn" ]; then
echo >&2 "OUT=$OUT doesn't look like an output directory."
echo >&2 "Please specify a directory by doing:"
echo >&2 " export OUT=out/xxx $0"
exit 1
fi
# Check SSH target is valid
if is_ssh_target && ! ssh -q "$SSH_TARGET" exit; then
echo >&2 "SSH_TARGET=$SSH_TARGET doesn't look like a valid SSH target."
echo >&2 "Please specify a SSH cross-compilation target by doing:"
echo >&2 " export SSH_TARGET=<user>@<host> $0"
exit 1
fi
if ! builtin type -P tmux &>/dev/null; then
echo >&2 "tmux not found"
exit 1
fi
# You can set the config to one of the files under test/configs e.g.
# CONFIG=ftrace.cfg or to :test. Defaults to :test.
CONFIG="${CONFIG:-:test}"
if is_android "$OUT"; then
DIR=/data/local/tmp
elif is_ssh_target; then
DIR=$(ssh "$SSH_TARGET" mktemp -d $TMPDIR/perfetto.XXXXXX)
elif is_mac; then
DIR=$(mktemp -d $TMPDIR/perfetto.XXXXXX)
else
DIR=$(mktemp -p $TMPDIR -d perfetto.XXXXXX)
fi
# (re)build the binaries
BUILD_TARGETS=(traced traced_probes perfetto test/configs)
if [[ SKIP_CONVERTERS -eq 0 ]]; then
BUILD_TARGETS+=(trace_to_text)
fi
"$SCRIPT_DIR/ninja" -C "$OUT" ${BUILD_TARGETS[*]}
push "$OUT/traced"
push "$OUT/traced_probes"
push "$OUT/perfetto"
reset_tracing
if is_android "$OUT"; then
PREFIX="PERFETTO_CONSUMER_SOCK_NAME=@perfetto_test_consumer PERFETTO_PRODUCER_SOCK_NAME=@perfetto_test_producer"
else
PREFIX=""
fi
if ! is_monolithic "$OUT"; then
PREFIX="$PREFIX LD_LIBRARY_PATH=$DIR"
push "$OUT/libperfetto.so"
fi
CONFIG_DEVICE_PATH="$CONFIG"
CMD_OPTS=""
# Shorthand for using serialized test configs.
if [[ "$CONFIG" == *.protobuf ]]; then
CONFIG_DEVICE_PATH="$CONFIG"
CONFIG_PATH=$OUT/$CONFIG
if [[ ! -f $CONFIG_PATH ]]; then
echo >&2 "Config \"$CONFIG_PATH\" not known."
exit 1
fi
push "$CONFIG_PATH"
elif [[ "$CONFIG" != ":test" ]]; then
CONFIG_DEVICE_PATH="$(basename "$CONFIG")"
CONFIG_PATH=$CONFIG
# If path isn't valid, assume it's a name of a test config.
if [[ ! -f $CONFIG_PATH ]]; then
CONFIG_PATH=test/configs/$CONFIG
if [[ ! -f $CONFIG_PATH ]]; then
echo >&2 "Config \"$CONFIG\" not known."
exit 1
fi
fi
CMD_OPTS="--txt $CMD_OPTS"
push "$CONFIG_PATH"
fi
if [[ -f "$SCRIPT" ]]; then
push "$SCRIPT"
fi
POSTFIX=""
if [[ -n "$CPU_MASK" ]]; then
PREFIX="$PREFIX taskset $CPU_MASK"
fi
if [[ BACKGROUND -eq 1 ]]; then
PREFIX="$PREFIX nohup"
POSTFIX=" &> /dev/null &"
fi
if tmux has-session -t demo; then
tmux kill-session -t demo
fi
tmux -2 new-session -d -s demo
if [ ! -z "$ANDROID_ADB_SERVER_PORT" ]; then
tmux set-environment -t demo ANDROID_ADB_SERVER_PORT $ANDROID_ADB_SERVER_PORT
fi
if tmux -V | awk '{split($2, ver, "."); if (ver[1] < 2) exit 1 ; else if (ver[1] == 2 && ver[2] < 1) exit 1 }'; then
tmux set-option -g mouse on
else
tmux set-option -g mode-mouse on
tmux set-option -g mouse-resize-pane on
tmux set-option -g mouse-select-pane on
tmux set-option -g mouse-select-window on
fi
tmux split-window -v
tmux split-window -v
if [[ -n "$SCRIPT" ]]; then
tmux split-window -v
fi
tmux select-layout "${TMUX_LAYOUT}"
tmux select-pane -t 0
tmux send-keys "clear" C-m
if is_android "$OUT"; then
tmux send-keys "adb shell" C-m
fi
tmux select-pane -t 1
tmux send-keys "clear" C-m
if is_android "$OUT"; then
tmux send-keys "adb shell" C-m
fi
tmux select-pane -t 2
tmux send-keys "clear" C-m
if is_android "$OUT"; then
tmux send-keys "adb shell" C-m
fi
if [[ -n "$SCRIPT" ]]; then
tmux select-pane -t 3
tmux send-keys "clear" C-m
if is_android "$OUT"; then
tmux send-keys "adb shell" C-m
fi
fi
sleep 2
tmux select-pane -t 1
if is_ssh_target; then
tmux send-keys "ssh $SSH_TARGET" Enter
fi
tmux_ensure_bash
tmux send-keys "PS1='[traced]$ '" Enter
tmux send-keys "cd $DIR" Enter
tmux send-keys "clear" C-m
tmux send-keys "$PREFIX ./traced $POSTFIX" Enter
tmux select-pane -t 0
if is_ssh_target; then
tmux send-keys "ssh $SSH_TARGET" Enter
fi
tmux_ensure_bash
tmux send-keys "PS1='[traced_probes]$ '" Enter
tmux send-keys "cd $DIR" Enter
tmux send-keys "clear" C-m
tmux send-keys "$PREFIX ./traced_probes $POSTFIX" Enter
tmux select-pane -t 2
if is_ssh_target; then
tmux send-keys "ssh $SSH_TARGET" Enter
fi
tmux_ensure_bash
tmux send-keys "PS1='[consumer]$ '" Enter
tmux send-keys "cd $DIR" Enter
tmux send-keys "clear" C-m
tmux send-keys "$PREFIX ./perfetto $CMD_OPTS -c $CONFIG_DEVICE_PATH -o trace $POSTFIX"
if [[ -n "$SCRIPT" ]]; then
tmux select-pane -t 3
if is_ssh_target; then
tmux send-keys "ssh $SSH_TARGET" Enter
fi
tmux_ensure_bash
tmux send-keys "PS1='[script]$ '" Enter
tmux send-keys "cd $DIR" Enter
tmux send-keys "clear" C-m
if [[ -f "$SCRIPT" ]]; then
tmux send-keys "./$(basename "$SCRIPT")"
else
tmux send-keys "$SCRIPT"
fi
fi
# Select consumer pane.
tmux select-pane -t 2
tmux -2 attach-session -t demo
if [[ BACKGROUND -eq 1 ]]; then
exit 0
fi
reset_tracing
TRACE=$TMPDIR/trace
echo -e "\n\x1b[32mPulling trace into $TRACE.perfetto-trace\x1b[0m"
pull trace "$TRACE.perfetto-trace"
if [[ SKIP_CONVERTERS -eq 0 ]]; then
echo -e "\n\x1b[32mPulling trace into $TRACE.pbtext\x1b[0m"
"$OUT/trace_to_text" text <"$TRACE.perfetto-trace" >"$TRACE.pbtext"
echo -e "\n\x1b[32mPulling trace into $TRACE.json\x1b[0m"
"$OUT/trace_to_text" systrace <"$TRACE.perfetto-trace" >"$TRACE.json"
# Keep this last so it can fail.
fi