44# Usage:
55# ./setup-android-emulator.sh [num_devices]
66#
7- # Boots `num_devices` (default 1) emulator instances backed by the same AVD
8- # (extra instances start with -read-only). Prints:
7+ # Boots `num_devices` (default 1) independent emulators.
8+ # Prints:
99# DEVICE_ID=<first serial>
1010# DEVICE_IDS=<comma-separated serials>
1111set -euo pipefail
2222fi
2323TAG=" google_apis_playstore"
2424SYSTEM_IMAGE=" system-images;android-${API_LEVEL} ;${TAG} ;${ABI} "
25- AVD_NAME =" Pixel9-API${API_LEVEL} -Enriched"
25+ AVD_BASE =" Pixel9-API${API_LEVEL} -Enriched"
2626BASE_PORT=5570
2727
2828if [ -z " ${ANDROID_HOME:- } " ]; then
@@ -49,44 +49,51 @@ if ! avdmanager list device -c | grep -qx "$DEVICE_ID"; then
4949 exit 1
5050fi
5151
52- if ! avdmanager list avd -c | grep -qx " ${AVD_NAME} " ; then
53- echo " Creating AVD '$AVD_NAME '..."
54- echo " no" | avdmanager create avd \
55- --name " $AVD_NAME " \
56- --device " $DEVICE_ID " \
57- --package " $SYSTEM_IMAGE " \
58- --skin " $DEVICE_ID "
59- fi
60-
61- AVD_CONFIG=" $HOME /.android/avd/${AVD_NAME} .avd/config.ini"
62- if [ -f " $AVD_CONFIG " ]; then
63- sed -i ' ' ' s/^hw\.keyboard=.*/hw.keyboard=yes/' " $AVD_CONFIG "
64- grep -q " ^hw.keyboard=" " $AVD_CONFIG " || echo " hw.keyboard=yes" >> " $AVD_CONFIG "
65- sed -i ' ' ' s/^hw\.mainKeys=.*/hw.mainKeys=yes/' " $AVD_CONFIG "
66- grep -q " ^hw.mainKeys=" " $AVD_CONFIG " || echo " hw.mainKeys=yes" >> " $AVD_CONFIG "
67- fi
52+ configure_avd () {
53+ local avd_name=" $1 "
54+ local avd_config=" $HOME /.android/avd/${avd_name} .avd/config.ini"
55+ if [ -f " $avd_config " ]; then
56+ sed -i ' ' ' s/^hw\.keyboard=.*/hw.keyboard=yes/' " $avd_config "
57+ grep -q " ^hw.keyboard=" " $avd_config " || echo " hw.keyboard=yes" >> " $avd_config "
58+ sed -i ' ' ' s/^hw\.mainKeys=.*/hw.mainKeys=yes/' " $avd_config "
59+ grep -q " ^hw.mainKeys=" " $avd_config " || echo " hw.mainKeys=yes" >> " $avd_config "
60+ fi
61+ }
6862
6963SERIALS=()
64+ AVD_NAMES=()
7065i=0
7166while [ " $i " -lt " $NUM_DEVICES " ]; do
67+ # Each shard gets its own numbered AVD so they boot fully independently.
68+ AVD_NAME=" ${AVD_BASE} -$(( i + 1 )) "
7269 PORT=$(( BASE_PORT + 2 * i))
7370 SERIAL=" emulator-${PORT} "
7471 SERIALS+=(" $SERIAL " )
72+ AVD_NAMES+=(" $AVD_NAME " )
73+
74+ if ! avdmanager list avd -c | grep -qx " $AVD_NAME " ; then
75+ echo " Creating AVD '$AVD_NAME '..."
76+ echo " no" | avdmanager create avd \
77+ --name " $AVD_NAME " \
78+ --device " $DEVICE_ID " \
79+ --package " $SYSTEM_IMAGE " \
80+ --skin " $DEVICE_ID "
81+ fi
82+ configure_avd " $AVD_NAME "
7583
7684 if adb -s " $SERIAL " get-state > /dev/null 2>&1 ; then
7785 echo " Emulator already running: $AVD_NAME ($SERIAL )"
7886 else
7987 echo " Starting emulator '$AVD_NAME ' ($SERIAL )..."
80- # Extra instances share the same AVD, which requires -read-only.
81- READ_ONLY=" "
82- [ " $i " -gt 0 ] && READ_ONLY=" -read-only"
83- # shellcheck disable=SC2086
84- emulator " @${AVD_NAME} " -port " $PORT " -no-boot-anim -no-snapshot-save $READ_ONLY > /dev/null 2>&1 &
88+ emulator " @${AVD_NAME} " -port " $PORT " -no-boot-anim -no-snapshot-save > /dev/null 2>&1 &
8589 fi
8690 i=$(( i + 1 ))
8791done
8892
89- for SERIAL in " ${SERIALS[@]} " ; do
93+ for idx in " ${! SERIALS[@]} " ; do
94+ SERIAL=" ${SERIALS[$idx]} "
95+ AVD_NAME=" ${AVD_NAMES[$idx]} "
96+
9097 echo " Waiting for emulator ($SERIAL ) to connect to ADB..."
9198 if ! timeout 120 adb -s " $SERIAL " wait-for-device; then
9299 echo " Error: Emulator $SERIAL did not connect to ADB after 120s."
0 commit comments