• 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
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