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