Created
June 9, 2017 14:36
-
-
Save leinardi/da1eac168f43bd6a0d3af149bf3f15e0 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env bash | |
if [ "$1" == "-h" ] || [ "$1" == "--help" ] ; then | |
echo "`basename $0` - run a command spawning an Android Emulator before. It can be used to run Android Tests." | |
echo "Usage: `basename $0` COMMAND" | |
echo "Example: $ `basename $0` ./gradlew connectedPayGermanyCompatDebugAndroidTest --info" | |
exit 0 | |
fi | |
# grab some variables | |
ADB=$ANDROID_HOME/platform-tools/adb | |
AVD_PREFIX="avd_" | |
SUCCESS=0 | |
ERROR_PORT_LOCKED=43 | |
ERROR_CREATING_AVD=65 | |
ERROR_STARTING_EMULATOR=69 | |
ERROR_WAIT_FOR_BOOT_TIMEOUT=408 | |
LOCK_TIMEOUT_IN_SECONDS=3600 | |
WAIT_TIMEOUT_IN_SECONDS=120 | |
## emulator_count | |
if [ "x${emulator_count}" != "x" ]; then | |
EMULATOR_COUNT="${emulator_count}" | |
else | |
EMULATOR_COUNT="1" | |
fi | |
## android_target | |
if [ "x${android_package}" != "x" ]; then | |
ANDROID_PACKAGE="${android_package}" | |
else | |
ANDROID_PACKAGE="system-images;android-25;google_apis;x86" | |
fi | |
## android_target | |
if [ "x${android_abi}" != "x" ]; then | |
ANDROID_ABI="${android_abi}" | |
else | |
ANDROID_ABI="google_apis/x86" | |
fi | |
## android_skin | |
if [ "x${android_skin}" != "x" ]; then | |
ANDROID_SKIN="${android_skin}" | |
else | |
ANDROID_SKIN="480x800" | |
fi | |
## sdcard_size | |
if [ "x${sdcard_size}" != "x" ]; then | |
SDCARD="${sdcard_size}" | |
else | |
SDCARD="256M" | |
fi | |
## port number to start searching for free ports for the console | |
if [ "x${console_port_start}" != "x" ]; then | |
console_port="${console_port_start}" | |
else | |
console_port="5554" | |
fi | |
## port number to start searching for free ports for the console | |
if [ "x${TMPDIR}" == "x" ]; then | |
TMPDIR="/tmp" | |
fi | |
# Functions | |
function checkPortAndLockIt { | |
local CONSOLE_PORT=$1 | |
local LOCK_FILE_PATH="$TMPDIR/${AVD_PREFIX}${CONSOLE_PORT}.lock" | |
if lsof -i -P -n | grep ":${CONSOLE_PORT} (LISTEN)\|:$(( ${CONSOLE_PORT} + 1 )) (LISTEN)" --quiet; then | |
echo ">>>>>> Port NOT available" | |
return $ERROR_PORT_LOCKED | |
else | |
echo ">>>>>> Port available" | |
if [ -f $LOCK_FILE_PATH ]; then | |
local LOCK_TIME=`cat ${LOCK_FILE_PATH}` | |
local NOW=`date +%s` | |
local ELAPSED=`expr $NOW - $LOCK_TIME` | |
if [ $ELAPSED -gt $LOCK_TIMEOUT_IN_SECONDS ]; then | |
echo ">>>>>> Port locked for more than 1 hour. Overriding..." | |
killEmulator $CONSOLE_PORT | |
echo `date +%s` > $LOCK_FILE_PATH | |
return $SUCCESS | |
else | |
echo ">>>>>> File locked" | |
return $ERROR_PORT_LOCKED | |
fi | |
else | |
echo ">>>>>> File NOT locked. Locking..." | |
echo `date +%s` > $LOCK_FILE_PATH | |
return $SUCCESS | |
fi | |
fi | |
} | |
# Create an array of free port numbers to use for the emulators | |
# Yes, this looks unnecessarily complex, but CONSOLE_PORT needs to | |
# be an even integer and can only be within a range of 5554-5584. | |
function findFreePorts { | |
echo "Searching for available ports" | |
for (( i=0 ; i < $EMULATOR_COUNT; i++ )) | |
{ | |
while ! checkPortAndLockIt ${console_port} | |
do | |
echo "Port ${console_port} busy" | |
#Console Port should and can only be an even number | |
#Android allows only even numbers | |
console_port=$(( ${console_port} + 2 )) | |
echo PORT1 ${console_port} | |
done | |
ports[k]=${console_port} | |
#Console Port should and can only be an even number | |
#Android allows only even numbers | |
console_port=$(( ${console_port} + 2 )) | |
} | |
} | |
# create the AVD | |
function createAVD { | |
local CONSOLE_PORT=$1 | |
echo "[emulator-$CONSOLE_PORT] Creating emulator $AVD_PREFIX$CONSOLE_PORT" | |
if ! echo no | ${ANDROID_HOME}/tools/bin/avdmanager create avd --force --name $AVD_PREFIX$CONSOLE_PORT --package "$ANDROID_PACKAGE" --sdcard $SDCARD --abi $ANDROID_ABI --device "4in WVGA (Nexus S)"; then | |
exit $ERROR_CREATING_AVD | |
fi | |
} | |
# start the AVD | |
# This starts the emulator | |
function startEmulator { | |
local CONSOLE_PORT=$1 | |
echo "[emulator-$CONSOLE_PORT] Starting emulator with avd $AVD_PREFIX$CONSOLE_PORT and console port $CONSOLE_PORT" | |
${ANDROID_HOME}/tools/emulator -avd $AVD_PREFIX$CONSOLE_PORT -port $CONSOLE_PORT -skin $ANDROID_SKIN -no-boot-anim -noaudio -no-window & | |
# Minimum boot up time of the emulator | |
sleep 10 | |
# This waits for emulator to start up | |
echo "[emulator-$CONSOLE_PORT] Waiting for emulator to boot completely" | |
wait_for_boot_complete "getprop dev.bootcomplete" 1 | |
wait_for_boot_complete "getprop sys.boot_completed" 1 | |
} | |
# unlock Emulator | |
function unlockEmulator { | |
local CONSOLE_PORT=$1 | |
echo "[emulator-$CONSOLE_PORT] Getting out of home screen" | |
$ADB -s emulator-$CONSOLE_PORT shell input keyevent 82 | |
$ADB -s emulator-$CONSOLE_PORT shell input keyevent 4 | |
} | |
# disable animations | |
function disableAnimations { | |
local CONSOLE_PORT=$1 | |
echo "[emulator-$CONSOLE_PORT] Disabling animations for less flaky tests on all devices" | |
$ADB -s emulator-$CONSOLE_PORT shell settings put global window_animation_scale 0 | |
$ADB -s emulator-$CONSOLE_PORT shell settings put global transition_animation_scale 0 | |
$ADB -s emulator-$CONSOLE_PORT shell settings put global animator_duration_scale 0 | |
$ADB -s emulator-$CONSOLE_PORT shell settings put system window_animation_scale 0 | |
$ADB -s emulator-$CONSOLE_PORT shell settings put system transition_animation_scale 0 | |
$ADB -s emulator-$CONSOLE_PORT shell settings put system animator_duration_scale 0 | |
$ADB -s emulator-$CONSOLE_PORT reboot | |
# Minimum boot up time of the emulator | |
sleep 12 | |
# This waits for emulator to start up | |
echo "[emulator-$CONSOLE_PORT] Waiting for emulator to boot completely" | |
wait_for_boot_complete "getprop dev.bootcomplete" 1 | |
wait_for_boot_complete "getprop sys.boot_completed" 1 | |
} | |
# create one emulator instance | |
function createOneEmulatorInstance { | |
local CONSOLE_PORT=$1 | |
createAVD $CONSOLE_PORT | |
startEmulator $CONSOLE_PORT | |
unlockEmulator $CONSOLE_PORT | |
disableAnimations $CONSOLE_PORT | |
} | |
# kill emulator | |
function killEmulator { | |
local CONSOLE_PORT=$1 | |
local LOCK_FILE_PATH="$TMPDIR/${AVD_PREFIX}${CONSOLE_PORT}.lock" | |
echo "[emulator-$CONSOLE_PORT] Killing emulator" | |
$ADB -s emulator-$CONSOLE_PORT emu kill || echo "Unable to kill emulator..." | |
rm $LOCK_FILE_PATH || echo "Lock file not found..." | |
} | |
# create the AVD | |
function deleteAVD { | |
local CONSOLE_PORT=$1 | |
echo "[emulator-$CONSOLE_PORT] Deleting emulator $AVD_PREFIX$CONSOLE_PORT" | |
echo no | ${ANDROID_HOME}/tools/bin/avdmanager delete avd --name $AVD_PREFIX$CONSOLE_PORT | |
} | |
# kill and delete one emulator instance | |
function killAndDeleteOneEmulatorInstance { | |
local CONSOLE_PORT=$1 | |
killEmulator $CONSOLE_PORT | |
deleteAVD $CONSOLE_PORT | |
} | |
# function to really, really check things are booted up | |
function wait_for_boot_complete { | |
local boot_property=$1 | |
local boot_property_test=$2 | |
echo "[emulator-$CONSOLE_PORT] Checking $boot_property..." | |
local ELAPSED=0 | |
until $ADB -s emulator-$CONSOLE_PORT shell $boot_property | grep "$boot_property_test"; do | |
sleep 1 | |
let "ELAPSED++" | |
if [ $ELAPSED -gt $WAIT_TIMEOUT_IN_SECONDS ] ; then | |
echo "[emulator-$CONSOLE_PORT] ERROR: \"$1\" timeout!" | |
killAndDeleteOneEmulatorInstance $CONSOLE_PORT | |
exit $ERROR_WAIT_FOR_BOOT_TIMEOUT | |
fi | |
done | |
echo "[emulator-$CONSOLE_PORT] \"$1\" succesful" | |
} | |
## The main function :) | |
function main { | |
# Get an array of free port numbers to use | |
findFreePorts | |
# Based on the port number found, create an instance of an emulator up to the EMULATOR_COUNT specified | |
for (( l=0, i=0 ; l < ${#ports[@]}, i < $EMULATOR_COUNT; i++, l=l+3 )) | |
{ | |
echo "ports for emulator $((i+1)): console=${ports[$l]}" | |
createOneEmulatorInstance ${ports[$l]} | |
} | |
echo Emulator startup complete! | |
export ANDROID_SERIAL="emulator-${ports[0]}" | |
CMD_TO_RUN=$@ | |
if [[ $CMD_TO_RUN == *"spoon"* ]]; then | |
CMD_TO_RUN="$CMD_TO_RUN -PspoonDevice=${ANDROID_SERIAL}" | |
fi | |
echo "Running \"$CMD_TO_RUN\"" | |
$CMD_TO_RUN | |
RET_CODE=$? | |
# Based on the port number found, create an instance of an emulator up to the EMULATOR_COUNT specified | |
for (( l=0, i=0 ; l < ${#ports[@]}, i < $EMULATOR_COUNT; i++, l=l+3 )) | |
{ | |
echo "killing and deleting emulator $((i+1)): console=${ports[$l]}" | |
killAndDeleteOneEmulatorInstance ${ports[$l]} | |
} | |
} | |
## Execute the script | |
main $@ | |
exit $RET_CODE |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment