• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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