Skip to content

Commit 82fa15f

Browse files
committed
Optimize API 35 emulator boot for CI
1 parent 128ffeb commit 82fa15f

File tree

2 files changed

+168
-66
lines changed

2 files changed

+168
-66
lines changed

.github/workflows/scripts-android.yml

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,32 @@ name: Test Android build scripts
1515
jobs:
1616
build-android:
1717
runs-on: ubuntu-latest
18+
timeout-minutes: 90
1819
steps:
1920
- uses: actions/checkout@v4
21+
- name: Free disk space for emulator
22+
run: |
23+
sudo rm -rf /usr/share/dotnet
24+
sudo rm -rf /opt/ghc
25+
sudo rm -rf /usr/local/share/boost
26+
sudo rm -rf "$AGENT_TOOLSDIRECTORY"
27+
df -h
28+
- name: Increase swap space for emulator
29+
run: |
30+
sudo swapoff -a
31+
sudo fallocate -l 8G /swapfile
32+
sudo chmod 600 /swapfile
33+
sudo mkswap /swapfile
34+
sudo swapon /swapfile
35+
free -h
36+
- name: Configure emulator timeouts
37+
run: |
38+
echo "EMULATOR_BOOT_TIMEOUT_SECONDS=1200" >> "$GITHUB_ENV"
39+
echo "PACKAGE_SERVICE_TIMEOUT_SECONDS=1200" >> "$GITHUB_ENV"
40+
echo "FRAMEWORK_READY_PRIMARY_TIMEOUT_SECONDS=300" >> "$GITHUB_ENV"
41+
echo "FRAMEWORK_READY_RESTART_TIMEOUT_SECONDS=240" >> "$GITHUB_ENV"
42+
echo "EMULATOR_POST_BOOT_GRACE_SECONDS=30" >> "$GITHUB_ENV"
43+
echo "UI_TEST_TIMEOUT_SECONDS=1200" >> "$GITHUB_ENV"
2044
- name: Setup workspace
2145
run: ./scripts/setup-workspace.sh -q -DskipTests
2246
- name: Build Android port

scripts/build-android-app.sh

Lines changed: 144 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -746,17 +746,34 @@ configure_avd() {
746746
return
747747
fi
748748
declare -A settings=(
749-
["hw.ramSize"]=2048
750-
["disk.dataPartition.size"]=8192M
749+
["hw.ramSize"]=6144
750+
["disk.dataPartition.size"]=12288M
751751
["fastboot.forceColdBoot"]=yes
752752
["hw.bluetooth"]=no
753753
["hw.camera.back"]=none
754754
["hw.camera.front"]=none
755755
["hw.audioInput"]=no
756756
["hw.audioOutput"]=no
757-
["hw.cpu.ncore"]=2
757+
["hw.cpu.ncore"]=4
758758
["hw.cpu.arch"]="x86_64"
759759
["abi.type"]="x86_64"
760+
["hw.gpu.enabled"]=yes
761+
["hw.gpu.mode"]=auto
762+
["hw.keyboard"]=yes
763+
["hw.sensors.proximity"]=no
764+
["hw.sensors.magnetic_field"]=no
765+
["hw.sensors.orientation"]=no
766+
["hw.sensors.temperature"]=no
767+
["hw.sensors.light"]=no
768+
["hw.sensors.pressure"]=no
769+
["hw.sensors.humidity"]=no
770+
["hw.gps"]=no
771+
["showDeviceFrame"]=no
772+
["skin.dynamic"]=yes
773+
["hw.lcd.density"]=320
774+
["hw.lcd.width"]=720
775+
["hw.lcd.height"]=1280
776+
["vm.heapSize"]=512
760777
)
761778
local key value
762779
for key in "${!settings[@]}"; do
@@ -771,119 +788,181 @@ configure_avd() {
771788

772789
wait_for_emulator() {
773790
local serial="$1"
791+
774792
"$ADB_BIN" start-server >/dev/null
775793
"$ADB_BIN" -s "$serial" wait-for-device
776794

777-
local boot_timeout="${EMULATOR_BOOT_TIMEOUT_SECONDS:-900}"
795+
local boot_timeout="${EMULATOR_BOOT_TIMEOUT_SECONDS:-1200}"
778796
if ! [[ "$boot_timeout" =~ ^[0-9]+$ ]] || [ "$boot_timeout" -le 0 ]; then
779-
ba_log "Invalid EMULATOR_BOOT_TIMEOUT_SECONDS=$boot_timeout provided; falling back to 900"
780-
boot_timeout=900
781-
fi
782-
local poll_interval="${EMULATOR_BOOT_POLL_INTERVAL_SECONDS:-5}"
783-
if ! [[ "$poll_interval" =~ ^[0-9]+$ ]] || [ "$poll_interval" -le 0 ]; then
784-
poll_interval=5
797+
boot_timeout=1200
785798
fi
786-
local status_log_interval="${EMULATOR_BOOT_STATUS_LOG_INTERVAL_SECONDS:-30}"
787-
if ! [[ "$status_log_interval" =~ ^[0-9]+$ ]] || [ "$status_log_interval" -le 0 ]; then
788-
status_log_interval=30
799+
800+
local log_interval="${EMULATOR_BOOT_STATUS_LOG_INTERVAL_SECONDS:-15}"
801+
if ! [[ "$log_interval" =~ ^[0-9]+$ ]] || [ "$log_interval" -le 0 ]; then
802+
log_interval=15
789803
fi
790804

791805
local deadline=$((SECONDS + boot_timeout))
792806
local last_log=$SECONDS
793-
local boot_completed="0"
794-
local dev_boot_completed="0"
795-
local bootanim=""
796-
local bootanim_exit=""
797-
local device_state=""
798-
local boot_ready=0
799807

808+
# Stage 1: wait for device to report "device"
809+
ba_log "Stage 1: waiting for emulator $serial to report device state"
810+
local device_online=0
800811
while [ $SECONDS -lt $deadline ]; do
801-
device_state="$($ADB_BIN -s "$serial" get-state 2>/dev/null | tr -d '\r')"
802-
if [ "$device_state" != "device" ]; then
803-
if [ $((SECONDS - last_log)) -ge $status_log_interval ]; then
804-
ba_log "Waiting for emulator $serial to become ready (state=$device_state)"
805-
last_log=$SECONDS
806-
fi
807-
sleep "$poll_interval"
808-
continue
812+
local state
813+
state="$($ADB_BIN -s "$serial" get-state 2>/dev/null | tr -d '\r')"
814+
if [ "$state" = "device" ]; then
815+
device_online=1
816+
break
817+
fi
818+
if [ $((SECONDS - last_log)) -ge $log_interval ]; then
819+
ba_log "Waiting for emulator $serial to come online (state=${state:-<unknown>})"
820+
last_log=$SECONDS
809821
fi
822+
sleep 3
823+
done
810824

811-
boot_completed="$($ADB_BIN -s "$serial" shell getprop sys.boot_completed 2>/dev/null | tr -d '\r')"
812-
dev_boot_completed="$($ADB_BIN -s "$serial" shell getprop dev.bootcomplete 2>/dev/null | tr -d '\r')"
813-
bootanim="$($ADB_BIN -s "$serial" shell getprop init.svc.bootanim 2>/dev/null | tr -d '\r')"
814-
bootanim_exit="$($ADB_BIN -s "$serial" shell getprop service.bootanim.exit 2>/dev/null | tr -d '\r')"
825+
if [ $device_online -ne 1 ]; then
826+
ba_log "Emulator $serial did not report device state within ${boot_timeout}s" >&2
827+
return 1
828+
fi
815829

816-
if { [ "$boot_completed" = "1" ] || [ "$boot_completed" = "true" ]; } \
817-
&& { [ -z "$dev_boot_completed" ] || [ "$dev_boot_completed" = "1" ] || [ "$dev_boot_completed" = "true" ]; }; then
818-
boot_ready=1
830+
# Stage 2: wait for boot properties to indicate readiness
831+
ba_log "Stage 2: waiting for core system properties on $serial"
832+
local system_ready=0
833+
last_log=$SECONDS
834+
while [ $SECONDS -lt $deadline ]; do
835+
local sys_boot dev_boot bootanim bootanim_exit
836+
sys_boot="$($ADB_BIN -s "$serial" shell getprop sys.boot_completed 2>/dev/null | tr -d '\r\n')"
837+
dev_boot="$($ADB_BIN -s "$serial" shell getprop dev.bootcomplete 2>/dev/null | tr -d '\r\n')"
838+
bootanim="$($ADB_BIN -s "$serial" shell getprop init.svc.bootanim 2>/dev/null | tr -d '\r\n')"
839+
bootanim_exit="$($ADB_BIN -s "$serial" shell getprop service.bootanim.exit 2>/dev/null | tr -d '\r\n')"
840+
841+
if { [ "$sys_boot" = "1" ] || [ "$sys_boot" = "true" ]; } && {
842+
[ "$dev_boot" = "1" ] || [ "$dev_boot" = "true" ];
843+
}; then
844+
system_ready=1
819845
break
820846
fi
821847

822848
if [ "$bootanim" = "stopped" ] || [ "$bootanim_exit" = "1" ]; then
823-
boot_ready=2
849+
system_ready=1
850+
ba_log "Emulator $serial reported boot animation stopped; continuing despite unset bootcomplete"
824851
break
825852
fi
826853

827-
if [ $((SECONDS - last_log)) -ge $status_log_interval ]; then
828-
ba_log "Waiting for emulator $serial to boot (sys.boot_completed=${boot_completed:-<unset>} dev.bootcomplete=${dev_boot_completed:-<unset>} bootanim=${bootanim:-<unset>} bootanim_exit=${bootanim_exit:-<unset>})"
854+
if [ $((SECONDS - last_log)) -ge $log_interval ]; then
855+
ba_log "Waiting for system services on $serial (sys.boot_completed=${sys_boot:-<unset>} dev.bootcomplete=${dev_boot:-<unset>} bootanim=${bootanim:-<unset>} bootanim_exit=${bootanim_exit:-<unset>})"
829856
last_log=$SECONDS
830857
fi
831-
sleep "$poll_interval"
858+
sleep 3
832859
done
833860

834-
if [ $boot_ready -eq 0 ]; then
835-
ba_log "Emulator $serial failed to boot within ${boot_timeout}s (sys.boot_completed=${boot_completed:-<unset>} dev.bootcomplete=${dev_boot_completed:-<unset>} bootanim=${bootanim:-<unset>} bootanim_exit=${bootanim_exit:-<unset>} state=${device_state:-<unset>})" >&2
861+
if [ $system_ready -ne 1 ]; then
862+
ba_log "Emulator $serial failed to finish boot sequence within ${boot_timeout}s" >&2
836863
return 1
837-
elif [ $boot_ready -eq 2 ]; then
838-
ba_log "Emulator $serial reported boot animation stopped; proceeding without bootcomplete properties"
839864
fi
840865

866+
# Stage 3: baseline device configuration
867+
ba_log "Stage 3: configuring emulator $serial for UI testing"
841868
"$ADB_BIN" -s "$serial" shell settings put global window_animation_scale 0 >/dev/null 2>&1 || true
842869
"$ADB_BIN" -s "$serial" shell settings put global transition_animation_scale 0 >/dev/null 2>&1 || true
843870
"$ADB_BIN" -s "$serial" shell settings put global animator_duration_scale 0 >/dev/null 2>&1 || true
844871
"$ADB_BIN" -s "$serial" shell input keyevent 82 >/dev/null 2>&1 || true
845872
"$ADB_BIN" -s "$serial" shell wm dismiss-keyguard >/dev/null 2>&1 || true
873+
846874
return 0
847875
}
848876

849877
wait_for_package_service() {
850878
local serial="$1"
851-
local timeout="${PACKAGE_SERVICE_TIMEOUT_SECONDS:-${PACKAGE_SERVICE_TIMEOUT:-600}}"
852-
local per_try="${PACKAGE_SERVICE_PER_TRY_TIMEOUT_SECONDS:-${PACKAGE_SERVICE_PER_TRY_TIMEOUT:-5}}"
879+
local timeout="${PACKAGE_SERVICE_TIMEOUT_SECONDS:-1200}"
880+
local per_try="${PACKAGE_SERVICE_PER_TRY_TIMEOUT_SECONDS:-15}"
853881
if ! [[ "$timeout" =~ ^[0-9]+$ ]] || [ "$timeout" -le 0 ]; then
854-
timeout=600
882+
timeout=1200
855883
fi
856884
if ! [[ "$per_try" =~ ^[0-9]+$ ]] || [ "$per_try" -le 0 ]; then
857-
per_try=5
885+
per_try=15
858886
fi
859887

860888
local deadline=$((SECONDS + timeout))
861889
local last_log=$SECONDS
890+
local restart_count=0
891+
local max_restarts=5
892+
893+
ba_log "Waiting for package manager service on $serial"
862894

863895
while [ $SECONDS -lt $deadline ]; do
864-
local boot_ok ce_ok
865-
boot_ok="$($ADB_BIN -s "$serial" shell getprop sys.boot_completed 2>/dev/null | tr -d '\r')"
866-
ce_ok="$($ADB_BIN -s "$serial" shell getprop sys.user.0.ce_available 2>/dev/null | tr -d '\r')"
896+
local sys_boot system_server pm_ready pm_list
867897

868-
if timeout "$per_try" "$ADB_BIN" -s "$serial" shell cmd package path android >/dev/null 2>&1 \
869-
|| timeout "$per_try" "$ADB_BIN" -s "$serial" shell pm path android >/dev/null 2>&1 \
870-
|| timeout "$per_try" "$ADB_BIN" -s "$serial" shell cmd package list packages >/dev/null 2>&1 \
871-
|| timeout "$per_try" "$ADB_BIN" -s "$serial" shell pm list packages >/dev/null 2>&1 \
872-
|| timeout "$per_try" "$ADB_BIN" -s "$serial" shell dumpsys package >/dev/null 2>&1; then
898+
sys_boot="$($ADB_BIN -s "$serial" shell getprop sys.boot_completed 2>/dev/null | tr -d '\r')"
899+
system_server="$(run_with_timeout "$per_try" "$ADB_BIN" -s "$serial" shell pidof system_server 2>/dev/null | tr -d '\r' || true)"
900+
901+
pm_ready=0
902+
if run_with_timeout "$per_try" "$ADB_BIN" -s "$serial" shell pm path android >/dev/null 2>&1 \
903+
|| run_with_timeout "$per_try" "$ADB_BIN" -s "$serial" shell cmd package path android >/dev/null 2>&1; then
904+
pm_ready=1
905+
fi
906+
907+
pm_list=0
908+
if run_with_timeout "$per_try" "$ADB_BIN" -s "$serial" shell pm list packages >/dev/null 2>&1; then
909+
pm_list=1
910+
fi
911+
912+
if [ $pm_ready -eq 1 ] && [ $pm_list -eq 1 ] && [ -n "$system_server" ]; then
913+
ba_log "Package manager ready on $serial (system_server=$system_server)"
873914
return 0
874915
fi
875916

876-
if [ $((SECONDS - last_log)) -ge 10 ]; then
877-
ba_log "Waiting for package manager service on $serial (boot_ok=${boot_ok:-?} ce_ok=${ce_ok:-?})"
917+
local service_status
918+
service_status="$(run_with_timeout "$per_try" "$ADB_BIN" -s "$serial" shell service check package 2>/dev/null | tr -d '\r' | tr -d '\n' || true)"
919+
if [ -n "$service_status" ] && printf '%s' "$service_status" | grep -q "found"; then
920+
if [ $pm_ready -eq 1 ] && [ -n "$system_server" ]; then
921+
ba_log "Package service responding despite limited signals; continuing"
922+
return 0
923+
fi
924+
fi
925+
926+
if [ $((SECONDS - last_log)) -ge 20 ]; then
927+
ba_log "PM status on $serial: boot=${sys_boot:-?} system_server=${system_server:-<none>} pm_ready=$pm_ready pm_list=$pm_list"
878928
last_log=$SECONDS
879929
fi
880-
sleep 2
930+
931+
local elapsed=$((SECONDS - (deadline - timeout)))
932+
if [ "$sys_boot" = "1" ] && [ $pm_ready -eq 0 ] && [ $elapsed -gt 0 ] && [ $((elapsed % 180)) -eq 0 ] \
933+
&& [ $restart_count -lt $max_restarts ]; then
934+
restart_count=$((restart_count + 1))
935+
ba_log "Package manager not ready after ${elapsed}s; restarting framework (attempt ${restart_count}/${max_restarts})"
936+
"$ADB_BIN" -s "$serial" shell stop >/dev/null 2>&1 || true
937+
sleep 5
938+
"$ADB_BIN" -s "$serial" shell start >/dev/null 2>&1 || true
939+
sleep 15
940+
continue
941+
fi
942+
943+
sleep 3
881944
done
882945

883946
ba_log "Package manager service not ready on $serial after ${timeout}s" >&2
884947
return 1
885948
}
886949

950+
optimize_api35_after_boot() {
951+
local serial="$1"
952+
ba_log "Optimizing emulator $serial for headless testing"
953+
954+
run_with_timeout 30 "$ADB_BIN" -s "$serial" shell pm disable-user com.google.android.googlequicksearchbox >/dev/null 2>&1 || true
955+
run_with_timeout 30 "$ADB_BIN" -s "$serial" shell pm disable-user com.android.vending >/dev/null 2>&1 || true
956+
run_with_timeout 30 "$ADB_BIN" -s "$serial" shell pm disable-user com.google.android.gms >/dev/null 2>&1 || true
957+
run_with_timeout 30 "$ADB_BIN" -s "$serial" shell cmd package bg-dexopt-job >/dev/null 2>&1 || true
958+
run_with_timeout 30 "$ADB_BIN" -s "$serial" shell logcat -c >/dev/null 2>&1 || true
959+
run_with_timeout 30 "$ADB_BIN" -s "$serial" shell locksettings set-disabled true >/dev/null 2>&1 || true
960+
run_with_timeout 30 "$ADB_BIN" -s "$serial" shell svc power stayon true >/dev/null 2>&1 || true
961+
run_with_timeout 30 "$ADB_BIN" -s "$serial" shell wm dismiss-keyguard >/dev/null 2>&1 || true
962+
run_with_timeout 30 "$ADB_BIN" -s "$serial" shell am kill-all >/dev/null 2>&1 || true
963+
sleep 10
964+
}
965+
887966
wait_for_api_level() {
888967
local serial="$1"
889968
local timeout="${API_LEVEL_TIMEOUT_SECONDS:-600}"
@@ -1184,12 +1263,16 @@ EMULATOR_SERIAL="emulator-$EMULATOR_PORT"
11841263

11851264
EMULATOR_LOG="$GRADLE_PROJECT_DIR/emulator.log"
11861265
ba_log "Starting headless Android emulator $AVD_NAME on port $EMULATOR_PORT"
1266+
export ANDROID_EMULATOR_WAIT_TIME_BEFORE_KILL="${ANDROID_EMULATOR_WAIT_TIME_BEFORE_KILL:-120}"
1267+
export ANDROID_EMULATOR_KVM_DISABLE_CHECK=1
1268+
export ANDROID_SDK_ROOT_NO_SETTINGS=1
11871269
ANDROID_AVD_HOME="$AVD_HOME" "$EMULATOR_BIN" -avd "$AVD_NAME" -port "$EMULATOR_PORT" \
11881270
-no-window -no-snapshot -no-snapshot-load -no-snapshot-save -wipe-data \
1189-
-gpu swiftshader_indirect -no-audio -no-boot-anim \
1271+
-gpu auto -no-audio -no-boot-anim \
11901272
-accel off -no-metrics -camera-back none -camera-front none -skip-adb-auth \
1191-
-feature -Vulkan -netfast -skin 1080x1920 -memory 2048 -cores 2 \
1192-
-partition-size 4096 >"$EMULATOR_LOG" 2>&1 &
1273+
-feature -Vulkan -feature -GLDMA -feature -GLDirectMem -no-passive-gps \
1274+
-netdelay none -netspeed full -skin 720x1280 -memory 6144 -cores 4 \
1275+
-partition-size 12288 -delay-adb >"$EMULATOR_LOG" 2>&1 &
11931276
EMULATOR_PID=$!
11941277
trap stop_emulator EXIT
11951278

@@ -1284,12 +1367,7 @@ if ! wait_for_package_service "$EMULATOR_SERIAL"; then
12841367
exit 1
12851368
fi
12861369

1287-
"$ADB_BIN" -s "$EMULATOR_SERIAL" shell locksettings set-disabled true >/dev/null 2>&1 || true
1288-
"$ADB_BIN" -s "$EMULATOR_SERIAL" shell svc power stayon true >/dev/null 2>&1 || true
1289-
"$ADB_BIN" -s "$EMULATOR_SERIAL" shell wm dismiss-keyguard >/dev/null 2>&1 || true
1290-
"$ADB_BIN" -s "$EMULATOR_SERIAL" shell settings put global window_animation_scale 0 >/dev/null 2>&1 || true
1291-
"$ADB_BIN" -s "$EMULATOR_SERIAL" shell settings put global transition_animation_scale 0 >/dev/null 2>&1 || true
1292-
"$ADB_BIN" -s "$EMULATOR_SERIAL" shell settings put global animator_duration_scale 0 >/dev/null 2>&1 || true
1370+
optimize_api35_after_boot "$EMULATOR_SERIAL"
12931371
"$ADB_BIN" -s "$EMULATOR_SERIAL" shell am get-current-user >/dev/null 2>&1 || true
12941372

12951373
if ! wait_for_api_level "$EMULATOR_SERIAL"; then

0 commit comments

Comments
 (0)