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