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>
This commit is contained in:
Assam Boudjelthia
2023-07-10 15:19:27 +03:00
parent f7f7c9f915
commit 1c27f95d01

View File

@@ -1,26 +1,27 @@
#!/bin/bash
# Copyright (C) 2021 The Qt Company Ltd.
# 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"
if [ -z "${ANDROID_EMULATOR}" ]
then
EMULATOR_NAME="emulator_x86_api_23"
else
EMULATOR_NAME="$ANDROID_EMULATOR"
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)$'
$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
@@ -33,48 +34,54 @@ function check_for_android_device
# 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 especially 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=` $ADB_EXEC shell getprop init.svc.bootanim | tr -d '\r\n'`
boot_completed=`$ADB_EXEC shell getprop sys.boot_completed | tr -d '\r\n'`
bootcomplete=` $ADB_EXEC shell getprop dev.bootcomplete | tr -d '\r\n'`
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. Aborting\!"
exit 3
echo "Emulator is already running but it shouldn't be. Terminating it now..."
pkill '^qemu-system-' || true
sleep 5
fi
echo "Starting emulator, try ${counter}/${EMULATOR_MAX_RETRIES}"
$EMULATOR_EXEC -avd $EMULATOR_NAME \
-gpu swiftshader_indirect -no-audio -partition-size 4096 \
-cores 4 -memory 16000 -no-snapshot-load -no-snapshot-save \
</dev/null >$HOME/emulator.log 2>&1 &
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 for emulated device to appear..."
$ADB_EXEC wait-for-device
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 300`
for i in `seq ${ADB_MAX_TIMEOUT}`
do
sleep 1
if check_for_android_device && check_if_fully_booted
if check_for_android_device && check_if_fully_booted
then
emulator_status=up
break
@@ -90,7 +97,8 @@ do
else
if [ $counter -lt $EMULATOR_MAX_RETRIES ]
then
echo "Emulator failed to start, forcefully killing current instance and re-starting emulator"
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 ]
@@ -101,5 +109,4 @@ do
fi
done
exit 0