xref: /aosp_15_r20/external/perfetto/tools/tmux (revision 6dbdd20afdafa5e3ca9b8809fa73465d530080dc)
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 'test -d /sys/kernel/tracing && echo 0 > /sys/kernel/tracing/tracing_on'
60  elif ! is_mac; then
61    # shellcheck disable=SC2016
62    local script='
63    if [ ! -w /sys/kernel/tracing ]; then
64      echo "tracefs not accessible, try sudo chown -R $USER /sys/kernel/tracing"
65      sudo chown -R "$USER" /sys/kernel/tracing
66    fi
67
68    echo 0 > /sys/kernel/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
196if is_android "$OUT"; then
197  TRACECONV="gcc_like_host/traceconv"
198else
199  TRACECONV="traceconv"
200fi
201
202
203# (re)build the binaries
204BUILD_TARGETS=(traced traced_probes perfetto test/configs)
205if [[ SKIP_CONVERTERS -eq 0 ]]; then
206  BUILD_TARGETS+=($TRACECONV)
207fi
208
209"$SCRIPT_DIR/ninja" -C "$OUT" ${BUILD_TARGETS[*]}
210
211push "$OUT/traced"
212push "$OUT/traced_probes"
213push "$OUT/perfetto"
214reset_tracing
215
216if is_android "$OUT"; then
217  PREFIX="PERFETTO_CONSUMER_SOCK_NAME=@perfetto_test_consumer PERFETTO_PRODUCER_SOCK_NAME=@perfetto_test_producer"
218else
219  PREFIX=""
220fi
221
222if ! is_monolithic "$OUT"; then
223  PREFIX="$PREFIX LD_LIBRARY_PATH=$DIR"
224  push "$OUT/libperfetto.so"
225fi
226
227CONFIG_DEVICE_PATH="$CONFIG"
228CMD_OPTS=""
229# Shorthand for using serialized test configs.
230if [[ "$CONFIG" == *.protobuf ]]; then
231  CONFIG_DEVICE_PATH="$CONFIG"
232  CONFIG_PATH=$OUT/$CONFIG
233  if [[ ! -f $CONFIG_PATH ]]; then
234    echo >&2 "Config \"$CONFIG_PATH\" not known."
235    exit 1
236  fi
237  push "$CONFIG_PATH"
238elif [[ "$CONFIG" != ":test" ]]; then
239  CONFIG_DEVICE_PATH="$(basename "$CONFIG")"
240  CONFIG_PATH=$CONFIG
241  # If path isn't valid, assume it's a name of a test config.
242  if [[ ! -f $CONFIG_PATH ]]; then
243    CONFIG_PATH=test/configs/$CONFIG
244    if [[ ! -f $CONFIG_PATH ]]; then
245      echo >&2 "Config \"$CONFIG\" not known."
246      exit 1
247    fi
248  fi
249  CMD_OPTS="--txt $CMD_OPTS"
250  push "$CONFIG_PATH"
251fi
252
253if [[ -f "$SCRIPT" ]]; then
254  push "$SCRIPT"
255fi
256
257POSTFIX=""
258
259if [[ -n "$CPU_MASK" ]]; then
260  PREFIX="$PREFIX taskset $CPU_MASK"
261fi
262
263if [[ BACKGROUND -eq 1 ]]; then
264  PREFIX="$PREFIX nohup"
265  POSTFIX=" &> /dev/null &"
266fi
267
268if tmux has-session -t demo; then
269  tmux kill-session -t demo
270fi
271tmux -2 new-session -d -s demo
272
273if [ ! -z "$ANDROID_ADB_SERVER_PORT" ]; then
274  tmux set-environment -t demo ANDROID_ADB_SERVER_PORT $ANDROID_ADB_SERVER_PORT
275fi
276
277if tmux -V | awk '{split($2, ver, "."); if (ver[1] < 2) exit 1 ; else if (ver[1] == 2 && ver[2] < 1) exit 1 }'; then
278  tmux set-option -g mouse on
279else
280  tmux set-option -g mode-mouse on
281  tmux set-option -g mouse-resize-pane on
282  tmux set-option -g mouse-select-pane on
283  tmux set-option -g mouse-select-window on
284fi
285
286tmux split-window -v
287tmux split-window -v
288
289if [[ -n "$SCRIPT" ]]; then
290  tmux split-window -v
291fi
292
293tmux select-layout "${TMUX_LAYOUT}"
294
295tmux select-pane -t 0
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 1
302tmux send-keys "clear" C-m
303if is_android "$OUT"; then
304  tmux send-keys "adb shell" C-m
305fi
306
307tmux select-pane -t 2
308tmux send-keys "clear" C-m
309if is_android "$OUT"; then
310  tmux send-keys "adb shell" C-m
311fi
312
313if [[ -n "$SCRIPT" ]]; then
314  tmux select-pane -t 3
315  tmux send-keys "clear" C-m
316  if is_android "$OUT"; then
317    tmux send-keys "adb shell" C-m
318  fi
319fi
320
321sleep 2
322
323tmux select-pane -t 1
324if is_ssh_target; then
325  tmux send-keys "ssh $SSH_TARGET" Enter
326fi
327tmux_ensure_bash
328tmux send-keys "PS1='[traced]$ '" Enter
329tmux send-keys "cd $DIR" Enter
330tmux send-keys "clear" C-m
331tmux send-keys "$PREFIX ./traced $POSTFIX" Enter
332
333tmux select-pane -t 0
334if is_ssh_target; then
335  tmux send-keys "ssh $SSH_TARGET" Enter
336fi
337tmux_ensure_bash
338tmux send-keys "PS1='[traced_probes]$ '" Enter
339tmux send-keys "cd $DIR" Enter
340tmux send-keys "clear" C-m
341tmux send-keys "$PREFIX ./traced_probes $POSTFIX" Enter
342
343tmux select-pane -t 2
344if is_ssh_target; then
345  tmux send-keys "ssh $SSH_TARGET" Enter
346fi
347tmux_ensure_bash
348tmux send-keys "PS1='[consumer]$ '" Enter
349tmux send-keys "cd $DIR" Enter
350tmux send-keys "clear" C-m
351tmux send-keys "$PREFIX ./perfetto $CMD_OPTS -c $CONFIG_DEVICE_PATH -o trace $POSTFIX"
352
353if [[ -n "$SCRIPT" ]]; then
354  tmux select-pane -t 3
355  if is_ssh_target; then
356    tmux send-keys "ssh $SSH_TARGET" Enter
357  fi
358  tmux_ensure_bash
359  tmux send-keys "PS1='[script]$ '" Enter
360  tmux send-keys "cd $DIR" Enter
361  tmux send-keys "clear" C-m
362  if [[ -f "$SCRIPT" ]]; then
363    tmux send-keys "./$(basename "$SCRIPT")"
364  else
365    tmux send-keys "$SCRIPT"
366  fi
367fi
368
369# Select consumer pane.
370tmux select-pane -t 2
371
372tmux -2 attach-session -t demo
373if [[ BACKGROUND -eq 1 ]]; then
374  exit 0
375fi
376
377reset_tracing
378
379TRACE=$TMPDIR/trace
380echo -e "\n\x1b[32mPulling trace into $TRACE.perfetto-trace\x1b[0m"
381pull trace "$TRACE.perfetto-trace"
382
383if [[ SKIP_CONVERTERS -eq 0 ]]; then
384  echo -e "\n\x1b[32mPulling trace into $TRACE.pbtext\x1b[0m"
385  "$OUT/$TRACECONV" text <"$TRACE.perfetto-trace" >"$TRACE.pbtext"
386fi
387