xref: /aosp_15_r20/external/google-breakpad/android/common-functions.sh (revision 9712c20fc9bbfbac4935993a2ca0b3958c5adad2)
1# Copyright 2012 Google LLC
2#
3# Redistribution and use in source and binary forms, with or without
4# modification, are permitted provided that the following conditions are
5# met:
6#
7#     * Redistributions of source code must retain the above copyright
8# notice, this list of conditions and the following disclaimer.
9#     * Redistributions in binary form must reproduce the above
10# copyright notice, this list of conditions and the following disclaimer
11# in the documentation and/or other materials provided with the
12# distribution.
13#     * Neither the name of Google LLC nor the names of its
14# contributors may be used to endorse or promote products derived from
15# this software without specific prior written permission.
16#
17# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
29# Collection of common shell functions for 'run-checks.sh' et 'test-shell.sh'
30
31# All internal variables and functions use an underscore as a prefix
32# (e.g. _VERBOSE, _ALL_CLEANUPS, etc..).
33
34# Sanitize the environment
35export LANG=C
36export LC_ALL=C
37
38if [ "$BASH_VERSION" ]; then
39  set -o posix
40fi
41
42# Utility functions
43
44_ALL_CLEANUPS=
45
46# Register a function to be called when the script exits, even in case of
47# Ctrl-C, logout, etc.
48# $1: function name.
49atexit () {
50  if [ -z "$_ALL_CLEANUPS" ]; then
51    _ALL_CLEANUPS=$1
52    # Ensure a clean exit when the script is:
53    #  - Exiting normally (EXIT)
54    #  - Interrupted by Ctrl-C (INT)
55    #  - Interrupted by log out (HUP)
56    #  - Being asked to quit nicely (TERM)
57    #  - Being asked to quit and dump core (QUIT)
58    trap "_exit_cleanups \$?" EXIT INT HUP QUIT TERM
59  else
60    _ALL_CLEANUPS="$_ALL_CLEANUPS $1"
61  fi
62}
63
64# Called on exit if at least one function was registered with atexit
65# $1: final exit status code
66_exit_cleanups () {
67  local CLEANUP CLEANUPS
68  # Ignore calls to atexit during cleanups
69  CLEANUPS=$_ALL_CLEANUPS
70  _ALL_CLEANUPS=
71  for CLEANUP in $CLEANUPS; do
72    ($CLEANUP)
73  done
74  exit "$@"
75}
76
77
78
79
80# Dump a panic message then exit.
81# $1+: message
82panic () {
83  echo "ERROR: $@" >&2
84  exit 1
85}
86
87# If the previous command failed, dump a panic message then exit.
88# $1+: message.
89fail_panic () {
90  if [ $? != 0 ]; then
91    panic "$@"
92  fi;
93}
94
95_VERBOSE=0
96
97# Increase verbosity for dump/log/run/run2 functions
98increase_verbosity () {
99  _VERBOSE=$(( $_VERBOSE + 1 ))
100}
101
102# Decrease verbosity
103decrease_verbosity () {
104  _VERBOSE=$(( $_VERBOSE - 1 ))
105}
106
107# Returns success iff verbosity level is higher than a specific value
108# $1: verbosity level
109verbosity_is_higher_than () {
110  [ "$_VERBOSE" -gt "$1" ]
111}
112
113# Returns success iff verbosity level is lower than a specific value
114# $1: verbosity level
115verbosity_is_lower_than () {
116  [ "$_VERBOSE" -le "$1" ]
117}
118
119# Dump message to stdout, unless verbosity is < 0, i.e. --quiet was called
120# $1+: message
121dump () {
122  if [ "$_VERBOSE" -ge 0 ]; then
123    printf "%s\n" "$*"
124  fi
125}
126
127# If --verbose was used, dump a message to stdout.
128# $1+: message
129log () {
130  if [ "$_VERBOSE" -ge 1 ]; then
131    printf "%s\n" "$*"
132  fi
133}
134
135_RUN_LOG=
136
137# Set a run log file that can be used to collect the output of commands that
138# are not displayed.
139set_run_log () {
140  _RUN_LOG=$1
141}
142
143# Run a command. Output depends on $_VERBOSE:
144#   $_VERBOSE <= 0:  Run command, store output into the run log
145#   $_VERBOSE >= 1:  Dump command, run it, output goest to stdout
146# Note: Ideally, the command's output would go to the run log for $_VERBOSE >= 1
147#       but the 'tee' tool doesn't preserve the status code of its input pipe
148#       in case of error.
149run () {
150  local LOGILE
151  if [ "$_RUN_LOG" ]; then
152    LOGFILE=$_RUN_LOG
153  else
154    LOGFILE=/dev/null
155  fi
156
157  if [ "$_VERBOSE" -ge 1 ]; then
158    echo "COMMAND: $@"
159    "$@"
160  else
161    "$@" >>$LOGFILE 2>&1
162  fi
163}
164
165# Same as run(), but only dump command output for $_VERBOSE >= 2
166run2 () {
167  local LOGILE
168  if [ "$_RUN_LOG" ]; then
169    LOGFILE=$_RUN_LOG
170  else
171    LOGFILE=/dev/null
172  fi
173
174  if [ "$_VERBOSE" -ge 1 ]; then
175    echo "COMMAND: $@"
176  fi
177  if [ "$_VERBOSE" -ge 2 ]; then
178    "$@"
179  else
180    "$@" >>$LOGFILE 2>&1
181  fi
182}
183
184# Extract number of cores to speed up the builds
185# Out: number of CPU cores
186get_core_count () {
187  case $(uname -s) in
188    Linux)
189      grep -c -e '^processor' /proc/cpuinfo
190      ;;
191    Darwin)
192      sysctl -n hw.ncpu
193      ;;
194    CYGWIN*|*_NT-*)
195      echo $NUMBER_OF_PROCESSORS
196      ;;
197    *)
198      echo 1
199      ;;
200  esac
201}
202
203
204# Check for the Android ADB program.
205#
206# On success, return nothing, but updates internal variables so later calls to
207# adb_shell, adb_push, etc.. will work. You can get the path to the ADB program
208# with adb_get_program if needed.
209#
210# On failure, returns 1, and updates the internal adb error message, which can
211# be retrieved with adb_get_error.
212#
213# $1: optional ADB program path.
214# Return: success or failure.
215_ADB=
216_ADB_STATUS=
217_ADB_ERROR=
218
219adb_check () {
220  # First, try to find the executable in the path, or the SDK install dir.
221  _ADB=$1
222  if [ -z "$_ADB" ]; then
223    _ADB=$(which adb 2>/dev/null)
224    if [ -z "$_ADB" -a "$ANDROID_SDK_ROOT" ]; then
225      _ADB=$ANDROID_SDK_ROOT/platform-tools/adb
226      if [ ! -f "$_ADB" ]; then
227        _ADB=
228      fi
229    fi
230    if [ -z "$_ADB" ]; then
231      _ADB_STATUS=1
232      _ADB_ERROR="The Android 'adb' tool is not in your path."
233      return 1
234    fi
235  fi
236
237  log "Found ADB program: $_ADB"
238
239  # Check that it works correctly
240  local ADB_VERSION
241  ADB_VERSION=$("$_ADB" version 2>/dev/null)
242  case $ADB_VERSION in
243    "Android Debug Bridge "*) # Pass
244      log "Found ADB version: $ADB_VERSION"
245      ;;
246    *) # Fail
247      _ADB_ERROR="Your ADB binary reports a bad version ($ADB_VERSION): $_ADB"
248      _ADB_STATUS=1
249      return 1
250  esac
251
252  _ADB_STATUS=0
253  return 0
254}
255
256
257# Return the path to the Android ADB program, if correctly detected.
258# On failure, return the empty string.
259# Out: ADB program path (or empty on failure)
260# Return: success or failure.
261adb_get_program () {
262  # Return cached value as soon as possible.
263  if [ -z "$_ADB_STATUS" ]; then
264    adb_check $1
265  fi
266  echo "$_ADB"
267  return $_ADB_STATUS
268}
269
270# Return the error corresponding to the last ADB function failure.
271adb_get_error () {
272  echo "$_ADB_ERROR"
273}
274
275# Check that there is one device connected through ADB.
276# In case of failure, use adb_get_error to know why this failed.
277# $1: Optional adb program path
278# Return: success or failure.
279_ADB_DEVICE=
280_ADB_DEVICE_STATUS=
281adb_check_device () {
282  if [ "$_ADB_DEVICE_STATUS" ]; then
283    return $_ADB_DEVICE_STATUS
284  fi
285
286  # Check for ADB.
287  if ! adb_check $1; then
288    _ADB_DEVICE_STATUS=$_ADB_STATUS
289    return 1
290  fi
291
292  local ADB_DEVICES NUM_DEVICES FINGERPRINT
293
294  # Count the number of connected devices.
295  ADB_DEVICES=$("$_ADB" devices 2>/dev/null | awk '$2 == "device" { print $1; }')
296  NUM_DEVICES=$(echo "$ADB_DEVICES" | wc -l)
297  case $NUM_DEVICES in
298    0)
299      _ADB_ERROR="No Android device connected. Please connect one to your machine."
300      _ADB_DEVICE_STATUS=1
301      return 1
302      ;;
303    1) # Pass
304      # Ensure the same device will be called in later adb_shell calls.
305      export ANDROID_SERIAL=$ADB_DEVICES
306      ;;
307    *) # 2 or more devices.
308      if [ "$ANDROID_SERIAL" ]; then
309        ADB_DEVICES=$ANDROID_SERIAL
310        NUM_DEVICES=1
311      else
312        _ADB_ERROR="More than one Android device connected. \
313Please define ANDROID_SERIAL in your environment"
314        _ADB_DEVICE_STATUS=1
315        return 1
316      fi
317      ;;
318  esac
319
320  _ADB_DEVICE_STATUS=0
321  _ADB_DEVICE=$ADB_DEVICES
322
323  FINGERPRINT=$(adb_shell getprop ro.build.fingerprint)
324  log "Using ADB device: $ANDROID_SERIAL ($FINGERPRINT)"
325  return 0
326}
327
328# The 'adb shell' command is pretty hopeless, try to make sense of it by:
329#   1/ Removing trailing \r from line endings.
330#   2/ Ensuring the function returns the command's status code.
331#
332# $1+: Command
333# Out: command output (stdout + stderr combined)
334# Return: command exit status
335adb_shell () {
336  local RET ADB_LOG
337  # Check for ADB device.
338  adb_check_device || return 1
339  ADB_LOG=$(mktemp "${TMPDIR:-/tmp}/adb-XXXXXXXX")
340  "$_ADB" shell "$@" ";" echo \$? > "$ADB_LOG" 2>&1
341  sed -i -e 's![[:cntrl:]]!!g' "$ADB_LOG"  # Remove \r.
342  RET=$(sed -e '$!d' "$ADB_LOG")           # Last line contains status code.
343  sed -e '$d' "$ADB_LOG"                   # Print everything except last line.
344  rm -f "$ADB_LOG"
345  return $RET
346}
347
348# Push a file to a device.
349# $1: source file path
350# $2: device target file path
351# Return: success or failure.
352adb_push () {
353  adb_check_device || return 1
354  run "$_ADB" push "$1" "$2"
355}
356
357# Pull a file from a device
358# $1: device file path
359# $2: target host file path
360# Return: success or failure.
361adb_pull () {
362  adb_check_device || return 1
363  run "$_ADB" pull "$1" "$2"
364}
365
366# Same as adb_push, but will panic if the operations didn't succeed.
367adb_install () {
368  adb_push "$@"
369  fail_panic "Failed to install $1 to the Android device at $2"
370}
371
372