1#!/bin/bash 2# Copyright (C) 2018 The Android Open Source Project 3# 4# Licensed under the Apache License, Version 2.0 (the "License"); 5# you may not use this file except in compliance with the License. 6# You may obtain a copy of the License at 7# 8# http://www.apache.org/licenses/LICENSE-2.0 9# 10# Unless required by applicable law or agreed to in writing, software 11# distributed under the License is distributed on an "AS IS" BASIS, 12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13# See the License for the specific language governing permissions and 14# limitations under the License. 15set -e 16SCRIPT_DIR="$(realpath "$(dirname "${BASH_SOURCE[0]}")")" 17 18if [ "$TMPDIR" == "" ]; then 19 TMPDIR=/tmp 20fi 21 22function get_gn_value() { 23 local out=$1 24 local key=$2 25 "$SCRIPT_DIR/gn" args "$out" --list=$key --short | awk '{print $3}' \ 26 | tr -d '"' 27} 28 29function is_monolithic() { 30 local out=$1 31 value=$(get_gn_value "$out" "monolithic_binaries") 32 test "$value" == "true" 33} 34 35function is_android() { 36 local out=$1 37 value=$(get_gn_value "$out" "target_os") 38 test "$value" == "android" 39} 40 41function is_ssh_target() { 42 [[ -n "$SSH_TARGET" ]] 43} 44 45function is_mac() { 46 # shellcheck disable=2251 47 ! test -d /proc 48 return $? 49} 50 51function tmux_ensure_bash() { 52 if [[ $SHELL == *"fish" ]]; then 53 tmux send-keys "bash" Enter 54 fi 55} 56 57function reset_tracing() { 58 if is_android "$OUT"; then 59 adb shell 'echo 0 > /d/tracing/tracing_on' 60 elif ! is_mac; then 61 # shellcheck disable=SC2016 62 local script=' 63 if [ ! -w /sys/kernel/debug ]; then 64 echo "debugfs not accessible, try sudo chown -R $USER /sys/kernel/debug" 65 sudo chown -R "$USER" /sys/kernel/debug 66 fi 67 68 echo 0 > /sys/kernel/debug/tracing/tracing_on 69 ' 70 71 if is_ssh_target; then 72 # shellcheck disable=SC2029 73 ssh -t "$SSH_TARGET" "sh -c '$script'" 74 else 75 sh -c "$script" 76 fi 77 fi 78} 79 80function adb_supports_push_sync() { 81 adb --help 2>&1 | grep 'push.*\[--sync\]' >/dev/null 2>&1 82} 83 84function push() { 85 if is_android "$OUT"; then 86 local maybe_sync='' 87 if adb_supports_push_sync; then 88 maybe_sync='--sync' 89 fi 90 echo adb push $maybe_sync "$1" "$DIR" 91 adb push $maybe_sync "$1" "$DIR" 92 elif is_ssh_target; then 93 echo scp "$1" "$SSH_TARGET:$DIR" 94 scp "$1" "$SSH_TARGET:$DIR" 95 else 96 echo cp "$1" "$DIR" 97 cp "$1" "$DIR" 98 fi 99} 100 101function pull() { 102 if is_android "$OUT"; then 103 echo adb pull "$DIR/$1" "$2" 104 adb pull "$DIR/$1" "$2" 105 elif is_ssh_target; then 106 echo scp "$SSH_TARGET:$DIR/$1" "$2" 107 scp "$SSH_TARGET:$DIR/$1" "$2" 108 else 109 echo mv "$DIR/$1" "$2" 110 mv "$DIR/$1" "$2" 111 fi 112} 113 114BACKGROUND=0 115SKIP_CONVERTERS=0 116TMUX_LAYOUT="even-vertical" 117CPU_MASK="" 118 119while getopts "bl:nt:c:C:z:s:" o; do 120 case "$o" in 121 b) BACKGROUND=1 ;; 122 l) TMUX_LAYOUT=${OPTARG} ;; 123 n) SKIP_CONVERTERS=1 ;; 124 t) SSH_TARGET=${OPTARG} ;; 125 c) CONFIG=${OPTARG} ;; 126 C) OUT=${OPTARG} ;; 127 z) CPU_MASK=${OPTARG} ;; 128 s) SCRIPT=${OPTARG} ;; 129 *) 130 echo >&2 "Invalid option $o" 131 exit 132 ;; 133 esac 134done 135 136# Allow out to be passed as argument 137shift $((OPTIND - 1)) 138OUT="${OUT:-$1}" 139 140# Provide useful usage information 141if [ -z "$OUT" ]; then 142 echo "Usage: $0 [OPTION]... [OUTPUT]" 143 echo "" 144 echo "Options:" 145 echo " -b run in the background" 146 echo " -l LAYOUT tmux pane layout" 147 echo " -n skip post-trace convertors" 148 echo " -t TARGET SSH device target" 149 echo " -c CONFIG trace configuration file" 150 echo " -C OUTPUT output directory" 151 echo " -z MASK constrain binaries to given cpu mask (taskset syntax)" 152 echo " -s SCRIPT a script to put into a tmux pane" 153 echo "" 154 echo "Environment variables:" 155 echo " SSH_TARGET SSH device target" 156 echo " CONFIG trace configuration file" 157 echo " OUT output directory" 158 exit 1 159fi 160 161# Warn about invalid output directories 162if [ ! -f "$OUT/args.gn" ]; then 163 echo >&2 "OUT=$OUT doesn't look like an output directory." 164 echo >&2 "Please specify a directory by doing:" 165 echo >&2 " export OUT=out/xxx $0" 166 exit 1 167fi 168 169# Check SSH target is valid 170if is_ssh_target && ! ssh -q "$SSH_TARGET" exit; then 171 echo >&2 "SSH_TARGET=$SSH_TARGET doesn't look like a valid SSH target." 172 echo >&2 "Please specify a SSH cross-compilation target by doing:" 173 echo >&2 " export SSH_TARGET=<user>@<host> $0" 174 exit 1 175fi 176 177if ! builtin type -P tmux &>/dev/null; then 178 echo >&2 "tmux not found" 179 exit 1 180fi 181 182# You can set the config to one of the files under test/configs e.g. 183# CONFIG=ftrace.cfg or to :test. Defaults to :test. 184CONFIG="${CONFIG:-:test}" 185 186if is_android "$OUT"; then 187 DIR=/data/local/tmp 188elif is_ssh_target; then 189 DIR=$(ssh "$SSH_TARGET" mktemp -d $TMPDIR/perfetto.XXXXXX) 190elif is_mac; then 191 DIR=$(mktemp -d $TMPDIR/perfetto.XXXXXX) 192else 193 DIR=$(mktemp -p $TMPDIR -d perfetto.XXXXXX) 194fi 195 196# (re)build the binaries 197BUILD_TARGETS=(traced traced_probes perfetto test/configs) 198if [[ SKIP_CONVERTERS -eq 0 ]]; then 199 BUILD_TARGETS+=(trace_to_text) 200fi 201 202"$SCRIPT_DIR/ninja" -C "$OUT" ${BUILD_TARGETS[*]} 203 204push "$OUT/traced" 205push "$OUT/traced_probes" 206push "$OUT/perfetto" 207reset_tracing 208 209if is_android "$OUT"; then 210 PREFIX="PERFETTO_CONSUMER_SOCK_NAME=@perfetto_test_consumer PERFETTO_PRODUCER_SOCK_NAME=@perfetto_test_producer" 211else 212 PREFIX="" 213fi 214 215if ! is_monolithic "$OUT"; then 216 PREFIX="$PREFIX LD_LIBRARY_PATH=$DIR" 217 push "$OUT/libperfetto.so" 218fi 219 220CONFIG_DEVICE_PATH="$CONFIG" 221CMD_OPTS="" 222# Shorthand for using serialized test configs. 223if [[ "$CONFIG" == *.protobuf ]]; then 224 CONFIG_DEVICE_PATH="$CONFIG" 225 CONFIG_PATH=$OUT/$CONFIG 226 if [[ ! -f $CONFIG_PATH ]]; then 227 echo >&2 "Config \"$CONFIG_PATH\" not known." 228 exit 1 229 fi 230 push "$CONFIG_PATH" 231elif [[ "$CONFIG" != ":test" ]]; then 232 CONFIG_DEVICE_PATH="$(basename "$CONFIG")" 233 CONFIG_PATH=$CONFIG 234 # If path isn't valid, assume it's a name of a test config. 235 if [[ ! -f $CONFIG_PATH ]]; then 236 CONFIG_PATH=test/configs/$CONFIG 237 if [[ ! -f $CONFIG_PATH ]]; then 238 echo >&2 "Config \"$CONFIG\" not known." 239 exit 1 240 fi 241 fi 242 CMD_OPTS="--txt $CMD_OPTS" 243 push "$CONFIG_PATH" 244fi 245 246if [[ -f "$SCRIPT" ]]; then 247 push "$SCRIPT" 248fi 249 250POSTFIX="" 251 252if [[ -n "$CPU_MASK" ]]; then 253 PREFIX="$PREFIX taskset $CPU_MASK" 254fi 255 256if [[ BACKGROUND -eq 1 ]]; then 257 PREFIX="$PREFIX nohup" 258 POSTFIX=" &> /dev/null &" 259fi 260 261if tmux has-session -t demo; then 262 tmux kill-session -t demo 263fi 264tmux -2 new-session -d -s demo 265 266if [ ! -z "$ANDROID_ADB_SERVER_PORT" ]; then 267 tmux set-environment -t demo ANDROID_ADB_SERVER_PORT $ANDROID_ADB_SERVER_PORT 268fi 269 270if tmux -V | awk '{split($2, ver, "."); if (ver[1] < 2) exit 1 ; else if (ver[1] == 2 && ver[2] < 1) exit 1 }'; then 271 tmux set-option -g mouse on 272else 273 tmux set-option -g mode-mouse on 274 tmux set-option -g mouse-resize-pane on 275 tmux set-option -g mouse-select-pane on 276 tmux set-option -g mouse-select-window on 277fi 278 279tmux split-window -v 280tmux split-window -v 281 282if [[ -n "$SCRIPT" ]]; then 283 tmux split-window -v 284fi 285 286tmux select-layout "${TMUX_LAYOUT}" 287 288tmux select-pane -t 0 289tmux send-keys "clear" C-m 290if is_android "$OUT"; then 291 tmux send-keys "adb shell" C-m 292fi 293 294tmux select-pane -t 1 295tmux send-keys "clear" C-m 296if is_android "$OUT"; then 297 tmux send-keys "adb shell" C-m 298fi 299 300tmux select-pane -t 2 301tmux send-keys "clear" C-m 302if is_android "$OUT"; then 303 tmux send-keys "adb shell" C-m 304fi 305 306if [[ -n "$SCRIPT" ]]; then 307 tmux select-pane -t 3 308 tmux send-keys "clear" C-m 309 if is_android "$OUT"; then 310 tmux send-keys "adb shell" C-m 311 fi 312fi 313 314sleep 2 315 316tmux select-pane -t 1 317if is_ssh_target; then 318 tmux send-keys "ssh $SSH_TARGET" Enter 319fi 320tmux_ensure_bash 321tmux send-keys "PS1='[traced]$ '" Enter 322tmux send-keys "cd $DIR" Enter 323tmux send-keys "clear" C-m 324tmux send-keys "$PREFIX ./traced $POSTFIX" Enter 325 326tmux select-pane -t 0 327if is_ssh_target; then 328 tmux send-keys "ssh $SSH_TARGET" Enter 329fi 330tmux_ensure_bash 331tmux send-keys "PS1='[traced_probes]$ '" Enter 332tmux send-keys "cd $DIR" Enter 333tmux send-keys "clear" C-m 334tmux send-keys "$PREFIX ./traced_probes $POSTFIX" Enter 335 336tmux select-pane -t 2 337if is_ssh_target; then 338 tmux send-keys "ssh $SSH_TARGET" Enter 339fi 340tmux_ensure_bash 341tmux send-keys "PS1='[consumer]$ '" Enter 342tmux send-keys "cd $DIR" Enter 343tmux send-keys "clear" C-m 344tmux send-keys "$PREFIX ./perfetto $CMD_OPTS -c $CONFIG_DEVICE_PATH -o trace $POSTFIX" 345 346if [[ -n "$SCRIPT" ]]; then 347 tmux select-pane -t 3 348 if is_ssh_target; then 349 tmux send-keys "ssh $SSH_TARGET" Enter 350 fi 351 tmux_ensure_bash 352 tmux send-keys "PS1='[script]$ '" Enter 353 tmux send-keys "cd $DIR" Enter 354 tmux send-keys "clear" C-m 355 if [[ -f "$SCRIPT" ]]; then 356 tmux send-keys "./$(basename "$SCRIPT")" 357 else 358 tmux send-keys "$SCRIPT" 359 fi 360fi 361 362# Select consumer pane. 363tmux select-pane -t 2 364 365tmux -2 attach-session -t demo 366if [[ BACKGROUND -eq 1 ]]; then 367 exit 0 368fi 369 370reset_tracing 371 372TRACE=$TMPDIR/trace 373echo -e "\n\x1b[32mPulling trace into $TRACE.protobuf\x1b[0m" 374pull trace "$TRACE.protobuf" 375 376if [[ SKIP_CONVERTERS -eq 0 ]]; then 377 echo -e "\n\x1b[32mPulling trace into $TRACE.pbtext\x1b[0m" 378 "$OUT/trace_to_text" text <"$TRACE.protobuf" >"$TRACE.pbtext" 379 echo -e "\n\x1b[32mPulling trace into $TRACE.json\x1b[0m" 380 "$OUT/trace_to_text" systrace <"$TRACE.protobuf" >"$TRACE.json" 381 # Keep this last so it can fail. 382fi 383