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

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

mercurial