Files
qt5/coin/provisioning/common/linux/android_emulator_launcher.sh
Assam Boudjelthia 1c27f95d01 COIN/Android: improvements to Android Emulator launcher script
* Don't fail silently if the AVD name is not provided.

* Add the following flags to the emulator:
    * -no-window: since we don't really interact with emulator is CI
    * -no-boot-anim: no need to run the boot animation
    * -no-snapshot-load: removed because it serves nothing
    * -detect-image-hang -restart-when-stalled: helps recover the
      emulator from freezes during execution
    * Disable warning dialog about nested virtualization.

* Terminate the emulator instance if the script expects it to not be
  running, i.e. save time by attempting to terminate and move on with the
  script execution instead of simply failing and doing nothing.

* Add a timeout to the blocking call 'adb wait-for-device'
* Save logcat output to a file for quick access to the logs,
  and put both emulator and logcat files under testresults folder,
  which would them available in cases of failure without needing to
  create a VM for debugging to get the logs.

Task-number: QTQAINFRA-5596
Fixes: QTQAINFRA-4628
Change-Id: I751bbec14980a452e02066f4e79d76fe6f3c018f
Reviewed-by: Simo Fält <simo.falt@qt.io>
2023-08-01 10:43:42 +03:00

113 lines
4.1 KiB
Bash
Executable File

#!/bin/bash
# Copyright (C) 2023 The Qt Company Ltd.
# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
# This util launches the Android emulator and ensures it doesn't stuck/freeze
# by detecting that and restarting it
set -e
EMULATOR_MAX_RETRIES=5
ADB_MAX_TIMEOUT=300
EMULATOR_EXEC="$ANDROID_SDK_ROOT/emulator/emulator"
ADB_EXEC="$ANDROID_SDK_ROOT/platform-tools/adb"
LOGCAT_PATH="$COIN_CTEST_RESULTSDIR/emulator_logcat_%iter.txt"
EMULATOR_RUN_LOG_PATH="$COIN_CTEST_RESULTSDIR/emulator_run_log_%iter.txt"
if [ -z "${ANDROID_EMULATOR}" ]; then
echo "No AVD name provided via ANDROID_EMULATOR env variable. Aborting!"
exit 1
fi
function check_for_android_device
{
$ADB_EXEC devices | awk 'NR==2{print $2}' | grep -qE '^(online|device)$'
}
# WARNING: On the very first boot of the emulator it happens that the device
# "finishes" booting and getprop shows bootanim=stopped and
# boot_completed=1. But sometimes not all packages have been installed (`pm
# list packages` shows only 16 packages installed), and after around half a
# minute the boot animation starts spinning (bootanim=running) again despite
# boot_completed=1 all the time. After some minutes the boot animation stops
# again and the list of packages contains 80 packages. Only then the device is
# fully booted, and only then is dev.bootcomplete=1.
#
# To reproduce the emulator booting as the first time, you have to delete the
# cached images found inside $HOME/.android/avd/{avd_name}.avd/ especially the
# "userdata-qemu.img.qcow2" file.
function check_if_fully_booted
{
# The "getprop" command separates lines with \r\n so we trim them
bootanim=` timeout 1 $ADB_EXEC shell getprop init.svc.bootanim | tr -d '\r\n'`
boot_completed=`timeout 1 $ADB_EXEC shell getprop sys.boot_completed | tr -d '\r\n'`
bootcomplete=` timeout 1 $ADB_EXEC shell getprop dev.bootcomplete | tr -d '\r\n'`
echo "bootanim=$bootanim boot_completed=$boot_completed bootcomplete=$bootcomplete"
[ "$bootanim" = stopped ] && [ "$boot_completed" = 1 ] && [ "$bootcomplete" = 1 ]
}
for counter in `seq ${EMULATOR_MAX_RETRIES}`
do
$ADB_EXEC kill-server
$ADB_EXEC start-server
if check_for_android_device
then
echo "Emulator is already running but it shouldn't be. Terminating it now..."
pkill '^qemu-system-' || true
sleep 5
fi
LOGCAT_PATH=${LOGCAT_PATH//%iter/${counter}}
EMULATOR_RUN_LOG_PATH=${EMULATOR_RUN_LOG_PATH//%iter/${counter}}
echo "Starting emulator ${ANDROID_EMULATOR}, try ${counter}/${EMULATOR_MAX_RETRIES}" \
| tee ${EMULATOR_RUN_LOG_PATH}
$EMULATOR_EXEC -avd $ANDROID_EMULATOR \
-gpu swiftshader_indirect -no-audio -no-window -no-boot-anim \
-cores 4 -memory 16000 -partition-size 4096 \
-detect-image-hang -restart-when-stalled -no-snapshot-save \
-no-nested-warnings -logcat-output ${LOGCAT_PATH} \
</dev/null >${EMULATOR_RUN_LOG_PATH} 2>&1 &
emulator_pid=$!
disown $emulator_pid
echo "Waiting ${ADB_MAX_TIMEOUT} seconds for emulated device to appear..."
timeout ${ADB_MAX_TIMEOUT} $ADB_EXEC wait-for-device
echo "Waiting a few minutes for the emulator to fully boot..."
emulator_status=down
for i in `seq ${ADB_MAX_TIMEOUT}`
do
sleep 1
if check_for_android_device && check_if_fully_booted
then
emulator_status=up
break
fi
done
# If emulator status is still offline after timeout period,
# we can assume it's stuck, and we must restart it
if [ $emulator_status = up ]
then
echo "Emulator started successfully"
break
else
if [ $counter -lt $EMULATOR_MAX_RETRIES ]
then
echo "Emulator failed to start," \
"forcefully killing current instance and re-starting emulator"
kill $emulator_pid || true
sleep 5
elif [ $counter -eq $EMULATOR_MAX_RETRIES ]
then
echo "Emulator failed to start, reached maximum number of retries. Aborting\!"
exit 2
fi
fi
done
exit 0