toolkit/crashreporter/google-breakpad/android/common-functions.sh

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rwxr-xr-x

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

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

mercurial