mirror of
git://code.qt.io/qt/qt5.git
synced 2026-01-09 08:26:34 +08:00
Allow the emulator launcher to take new options that are commonly
used:
* --window: shows the emulator window instead of running headless
* --avd: set the emulator name instead of using the env var, this
can be more intuitive and more expected than the env var.
* --help: to guide users how to use this script.
Also, the script now will print a list of available AVD names to
use instead of the less obvious error of no AVD name provided
which forces the user to manually find the names first.
This also, sets the COIN_CTEST_RESULTSDIR to CWD in case
it's not set, this is the case when running as a debug VM.
Pick-to: 6.8 6.5
Change-Id: Id90ca2fddda713645e9c1621e346d73f1dc85ea1
Reviewed-by: Dimitrios Apostolou <jimis@qt.io>
(cherry picked from commit 05f46d0e54)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
174 lines
5.7 KiB
Bash
Executable File
174 lines
5.7 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
|
|
|
|
function print_help {
|
|
echo "Usage: [ANDROID_EMULATOR=<name>] $0 [--avd <name>] [--window] [--help]"
|
|
echo ""
|
|
echo "This script launches the Android emulator on Qt CI."
|
|
echo ""
|
|
echo "Options:"
|
|
echo " --avd <name> Set the AVD name to launch (overrides ANDROID_EMULATOR env var)"
|
|
echo " --window Show the emulator window (default is headless via -no-window)"
|
|
echo " --help Show this help message"
|
|
echo ""
|
|
}
|
|
|
|
WINDOW_ARG="-no-window"
|
|
AVD_NAME_ARG=""
|
|
while [ $# -gt 0 ]; do
|
|
arg="$1"
|
|
case "$arg" in
|
|
--help)
|
|
print_help
|
|
exit 0
|
|
;;
|
|
--window)
|
|
WINDOW_ARG=""
|
|
shift
|
|
;;
|
|
--avd)
|
|
if [ -n "$2" ]; then
|
|
AVD_NAME_ARG="$2"
|
|
shift 2
|
|
else
|
|
echo "Error: --avd requires an argument"
|
|
exit 1
|
|
fi
|
|
;;
|
|
esac
|
|
done
|
|
|
|
EMULATOR_MAX_RETRIES=3
|
|
ADB_MAX_TIMEOUT=180
|
|
EMULATOR_EXEC="$ANDROID_SDK_ROOT/emulator/emulator"
|
|
ADB_EXEC="$ANDROID_SDK_ROOT/platform-tools/adb"
|
|
|
|
if [ -z "$COIN_CTEST_RESULTSDIR" ]; then
|
|
COIN_CTEST_RESULTSDIR="$(pwd)"
|
|
fi
|
|
|
|
LOGCAT_PATH="$COIN_CTEST_RESULTSDIR/emulator_logcat_%iter.txt"
|
|
EMULATOR_RUN_LOG_PATH="$COIN_CTEST_RESULTSDIR/emulator_run_log_%iter.txt"
|
|
|
|
if [ -n "$AVD_NAME_ARG" ]; then
|
|
AVD_NAME="$AVD_NAME_ARG"
|
|
else
|
|
AVD_NAME="$ANDROID_EMULATOR"
|
|
fi
|
|
|
|
if [ -z "${AVD_NAME}" ]; then
|
|
echo "No AVD name provided via --avd option or ANDROID_EMULATOR env variable. Aborting!"
|
|
echo "Available AVDs names:"
|
|
$EMULATOR_EXEC -list-avds | sed 's/^/ /'
|
|
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 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
|
|
# 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
|
|
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 "boot_completed=$boot_completed bootcomplete=$bootcomplete"
|
|
[ "$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 ${AVD_NAME}, try ${counter}/${EMULATOR_MAX_RETRIES}" \
|
|
| tee "${EMULATOR_RUN_LOG_PATH}"
|
|
$EMULATOR_EXEC -avd "$AVD_NAME" \
|
|
-gpu swiftshader_indirect -no-audio $WINDOW_ARG -no-boot-anim \
|
|
-cores 4 -memory 16000 -partition-size 4096 \
|
|
-detect-image-hang -restart-when-stalled -no-snapshot-save \
|
|
-no-nested-warnings -logcat '*:v' -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 start..."
|
|
timeout ${ADB_MAX_TIMEOUT} "$ADB_EXEC" wait-for-device
|
|
|
|
# Due to some bug in Coin/Go, we can't have the emulator command stream
|
|
# the output to the console while in the background, as Coin will continue
|
|
# waiting for it. So, rely on re-directing all output to a log file and
|
|
# then printing it out after the emulator is started.
|
|
echo "######## Printing out the emulator command logs ########"
|
|
cat "${EMULATOR_RUN_LOG_PATH}"
|
|
echo "########################################################"
|
|
|
|
echo "Waiting a few minutes for the emulator to fully boot..."
|
|
emulator_status=down
|
|
|
|
time_start=${SECONDS}
|
|
duration=0
|
|
|
|
while [ $duration -lt ${ADB_MAX_TIMEOUT} ]
|
|
do
|
|
sleep 1
|
|
|
|
if check_for_android_device && check_if_fully_booted
|
|
then
|
|
emulator_status=up
|
|
break
|
|
fi
|
|
duration=$(( SECONDS - time_start ))
|
|
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
|