Skip to content

Commit

Permalink
ci: Adjust for occasional emulator startup issues that cause retries.
Browse files Browse the repository at this point in the history
- Don't assume the order of ANR process reporting
- Terminate the system UI preemptively in order to restart clean after boot
  • Loading branch information
jeromelaban committed Dec 8, 2024
1 parent e552ec8 commit 8eebe19
Show file tree
Hide file tree
Showing 4 changed files with 141 additions and 15 deletions.
2 changes: 1 addition & 1 deletion azure-pipelines.yml
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ stages:
displayName: 'WebAssembly'
dependsOn: []
jobs:
- job: Linux
- job: WebAssembly
timeoutInMinutes: 60
pool:
vmImage: ubuntu-latest
Expand Down
45 changes: 35 additions & 10 deletions build/scripts/android-uitest-run.sh
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ export UNO_UITEST_BINARY=$BUILD_SOURCESDIRECTORY/Uno.Gallery.UITests/bin/Release
export UNO_EMULATOR_INSTALLED=$BUILD_SOURCESDIRECTORY/build/.emulator_started
export UITEST_TEST_TIMEOUT=60m
export UNO_UITEST_ANDROIDAPK_PATH=$UNO_UITEST_ANDROIDAPK_BASEPATH/com.nventive.uno.ui.demo-Signed.apk
export ANDROID_SIMULATOR_APILEVEL=28

AVD_NAME=xamarin_android_emulator
AVD_CONFIG_FILE=~/.android/avd/$AVD_NAME.avd/config.ini

# Override Android SDK tooling
export ANDROID_HOME=$BUILD_SOURCESDIRECTORY/build/android-sdk
Expand All @@ -30,28 +34,47 @@ then
mv $ANDROID_HOME/platform-tools/platform-tools/* $ANDROID_HOME/platform-tools
fi

AVD_NAME=xamarin_android_emulator
AVD_CONFIG_FILE=~/.android/avd/$AVD_NAME.avd/config.ini

# Install Android SDK emulators and SDKs
if [ ! -f "$UNO_EMULATOR_INSTALLED" ];
then
echo "y" | $ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager --sdk_root=${ANDROID_HOME} --install 'tools'| tr '\r' '\n' | uniq
echo "y" | $ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager --sdk_root=${ANDROID_HOME} --install 'platform-tools' | tr '\r' '\n' | uniq
echo "y" | $ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager --sdk_root=${ANDROID_HOME} --install 'build-tools;35.0.0' | tr '\r' '\n' | uniq
echo "y" | $ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager --sdk_root=${ANDROID_HOME} --install 'platforms;android-28' | tr '\r' '\n' | uniq
echo "y" | $ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager --sdk_root=${ANDROID_HOME} --install 'platforms;android-34' | tr '\r' '\n' | uniq
echo "y" | $ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager --sdk_root=${ANDROID_HOME} --install 'extras;android;m2repository' | tr '\r' '\n' | uniq
echo "y" | $ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager --sdk_root=${ANDROID_HOME} --install "tools"| tr '\r' '\n' | uniq
echo "y" | $ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager --sdk_root=${ANDROID_HOME} --install "platform-tools" | tr '\r' '\n' | uniq
echo "y" | $ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager --sdk_root=${ANDROID_HOME} --install "build-tools;35.0.0" | tr '\r' '\n' | uniq
echo "y" | $ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager --sdk_root=${ANDROID_HOME} --install "platforms;android-$ANDROID_SIMULATOR_APILEVEL" | tr '\r' '\n' | uniq
echo "y" | $ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager --sdk_root=${ANDROID_HOME} --install "extras;android;m2repository" | tr '\r' '\n' | uniq

# Install AVD files
echo "y" | $ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager --sdk_root=${ANDROID_HOME} --install 'system-images;android-28;google_apis_playstore;x86_64'
echo "y" | $ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager --sdk_root=${ANDROID_HOME} --install "system-images;android-$ANDROID_SIMULATOR_APILEVEL;google_apis_playstore;x86_64"

# Create emulator
echo "no" | $ANDROID_HOME/cmdline-tools/latest/bin/avdmanager create avd -n xamarin_android_emulator --abi "x86_64" -k 'system-images;android-28;google_apis_playstore;x86_64' --force
echo "no" | $ANDROID_HOME/cmdline-tools/latest/bin/avdmanager create avd -n $AVD_NAME --abi "x86_64" -k "system-images;android-$ANDROID_SIMULATOR_APILEVEL;google_apis_playstore;x86_64" --sdcard 128M --force

# based on https://docs.microsoft.com/en-us/azure/devops/pipelines/agents/hosted?view=azure-devops&tabs=yaml#hardware
# >> Agents that run macOS images are provisioned on Mac pros with a 3 core CPU, 14 GB of RAM, and 14 GB of SSD disk space.
echo "hw.cpu.ncore=3" >> $AVD_CONFIG_FILE

# Bump the heap size as the tests are stressing the application
echo "vm.heapSize=256M" >> $AVD_CONFIG_FILE

echo $ANDROID_HOME/emulator/emulator -list-avds

echo "Starting emulator"

# Start emulator in background
nohup $ANDROID_HOME/emulator/emulator -avd xamarin_android_emulator -skin 1280x800 -memory 4096 -no-window -gpu swiftshader_indirect -no-snapshot -noaudio -no-boot-anim > /dev/null 2>&1 &
nohup $ANDROID_HOME/emulator/emulator \
-avd $AVD_NAME \
-skin 1280x800 \
-memory 4096 \
-no-window \
-gpu swiftshader_indirect \
-no-snapshot \
-noaudio \
-no-boot-anim \
-prop ro.debuggable=1 \
> $BUILD_ARTIFACTSTAGINGDIRECTORY/android-emulator-log.txt 2>&1 &

touch "$UNO_EMULATOR_INSTALLED"
fi
Expand All @@ -61,7 +84,7 @@ mkdir -p $UNO_UITEST_SCREENSHOT_PATH
cp $UNO_UITEST_ANDROIDAPK_PATH $UNO_UITEST_SCREENSHOT_PATH

# Wait for the emulator to finish booting
$ANDROID_HOME/platform-tools/adb wait-for-device shell 'while [[ -z $(getprop sys.boot_completed | tr -d '\r') ]]; do sleep 1; done; input keyevent 82'
source $BUILD_SOURCESDIRECTORY/build/scripts/android-uitest-wait-systemui.sh 500

$ANDROID_HOME/platform-tools/adb devices

Expand All @@ -79,3 +102,5 @@ dotnet test \

## Dump the emulator's system log
$ANDROID_HOME/platform-tools/adb shell logcat -d > $BUILD_ARTIFACTSTAGINGDIRECTORY/android-device-log.txt

$ANDROID_HOME/platform-tools/adb exec-out screencap -p > $BUILD_ARTIFACTSTAGINGDIRECTORY/android-end-run.png
102 changes: 102 additions & 0 deletions build/scripts/android-uitest-wait-systemui.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
#!/usr/bin/env bash
BOOT_TIMEOUT=$1
retry() {
local -r -i max_attempts="$1";shift 1
local -i attempt_num=1
local -a COMMANDS=( timeout $BOOT_TIMEOUT )

while (( "$#" )); do
local arg="$1";
if [[ "$arg" = *" "* ]]; then
COMMANDS+=( $( printf "\''%s'\'" "$arg" ) )
else
COMMANDS+=( "$arg" )
fi
shift
done

until "${COMMANDS[@]}"
do
if ((attempt_num==max_attempts))
then
echo "Last attempt $attempt_num failed, exiting."
return 1
else
echo "Attempt $attempt_num failed! Waiting $attempt_num seconds..."
sleep $((attempt_num++))
fi
done
}

echo ""
echo "[Waiting for device to boot] timeout $BOOT_TIMEOUT sec"

if [ $ANDROID_SIMULATOR_APILEVEL -gt 25 ];
then
retry 3 "$ANDROID_HOME/platform-tools/adb" wait-for-device shell 'echo "emulator is attached, wait for boot completion"; while [[ -z $(getprop sys.boot_completed | tr -d '\r') ]] && [[ "$SECONDS" -lt 300 ]]; do sleep 1; done; input keyevent 82; echo "boot is complete."'
else
retry 3 "$ANDROID_HOME/platform-tools/adb" wait-for-device shell 'echo "emulator is attached, wait for boot completion"; while [[ -z $(getprop sys.boot_completed) ]] && [[ "$SECONDS" -lt 300 ]]; do sleep 1; done; input keyevent 82; echo "boot is complete."'
fi

# Wait for com.android.systemui to become available,
# as the CPU of the build machine may be slow
# See: https://stackoverflow.com/questions/52410440/error-system-ui-isnt-responding-while-running-aosp-build-on-emulator
#

echo "boot_completed after $SECONDS"
echo "[Waiting for launcher to start]"
LAUNCHER_READY=
MAX_START_TIME=300
START_TIME=$SECONDS
while [[ -z ${LAUNCHER_READY} ]]; do

if [ $ANDROID_SIMULATOR_APILEVEL -ge 29 ];
then
UI_FOCUS=`$ANDROID_HOME/platform-tools/adb shell dumpsys window 2>/dev/null | grep -E 'mCurrentFocus|mFocusedApp' || true`
else
UI_FOCUS=`$ANDROID_HOME/platform-tools/adb shell dumpsys window windows 2>/dev/null | grep -i mCurrentFocus || true`
fi

ELAPSED_TIME=$(( SECONDS - START_TIME ))
if [ ${ELAPSED_TIME} -gt ${MAX_START_TIME} ];
then
echo "(FAIL) Emulator failed to start properly after $MAX_START_TIME"
exit 1
fi

echo "(DEBUG $SECONDS) Current focus: ${UI_FOCUS}"

case $UI_FOCUS in
*"Not Responding"*)
echo "Detected an ANR! Dismissing..."
$ANDROID_HOME/platform-tools/adb shell input keyevent KEYCODE_DPAD_RIGHT
$ANDROID_HOME/platform-tools/adb shell input keyevent KEYCODE_ENTER
;;
*"Launcher"*)
LAUNCHER_READY=true
;;
"")
echo "Waiting for window service..."
sleep 3
;;
*)
echo "Waiting for launcher..."
sleep 3

# For some reason the messaging app can be brought up in front
# (DEBUG) Current focus: mCurrentFocus=Window{1170051 u0 com.google.android.apps.messaging/com.google.android.apps.messaging.ui.ConversationListActivity}
# Try bringing back the home screen to check on the launcher.
$ANDROID_HOME/platform-tools/adb shell input keyevent KEYCODE_HOME
;;
esac
done

# Force terminate system UI to restart clean
adb shell am force-stop com.android.systemui

adb shell settings put global animator_duration_scale 0
adb shell settings put global transition_animation_scale 0
adb shell settings put global window_animation_scale 0

echo "Launcher is ready!"

7 changes: 3 additions & 4 deletions build/stage-uitests-android.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@
clean: true

- template: templates/dotnet-install-mac.yml
parameters:
UnoCheckParameters: '--tfm net9.0-android'

- template: templates/canary-updater.yml

- task: PowerShell@2
Expand Down Expand Up @@ -59,10 +62,6 @@
- download: current
artifact: Android_UITest

- template: templates/dotnet-install-mac.yml
parameters:
UnoCheckParameters: '--tfm net9.0-android'

- template: templates/canary-updater.yml

- bash: |
Expand Down

0 comments on commit 8eebe19

Please sign in to comment.