@@ -275,6 +275,30 @@ jobs:
275275 # below remains the authoritative, unmasked failure boundary.
276276 yes | "$SDKMANAGER" --licenses \
277277 >"$PYBLE_ANDROID_LOG_DIR/sdk-licenses.log" 2>&1 || true
278+
279+ # API 34 first boot enforces a 6 GiB userdata minimum and also
280+ # requires 20 percent free-space headroom. GitHub's runner carries
281+ # several side-by-side NDKs, while PyBLE intentionally builds with
282+ # exactly one pinned revision. Remove only the unused NDK packages
283+ # before installing the pinned SDK set so the AVD has honest space.
284+ df -h "$SDK_ROOT" \
285+ | tee "$PYBLE_ANDROID_LOG_DIR/disk-before-prune.log"
286+ "$SDKMANAGER" --list_installed \
287+ | tee "$PYBLE_ANDROID_LOG_DIR/sdk-list-installed.log"
288+ mapfile -t PYBLE_UNUSED_NDKS < <(
289+ awk -F '|' -v keep="$PYBLE_ANDROID_NDK" '
290+ {
291+ package = $1
292+ gsub(/^[[:space:]]+|[[:space:]]+$/, "", package)
293+ }
294+ package ~ /^ndk;/ && package != keep { print package }
295+ ' "$PYBLE_ANDROID_LOG_DIR/sdk-list-installed.log"
296+ )
297+ if [ "${#PYBLE_UNUSED_NDKS[@]}" -gt 0 ]; then
298+ "$SDKMANAGER" --uninstall "${PYBLE_UNUSED_NDKS[@]}" \
299+ | tee "$PYBLE_ANDROID_LOG_DIR/sdk-prune.log"
300+ fi
301+
278302 "$SDKMANAGER" --channel=0 \
279303 platform-tools \
280304 emulator \
@@ -284,11 +308,30 @@ jobs:
284308 "$PYBLE_ANDROID_IMAGE" \
285309 | tee "$PYBLE_ANDROID_LOG_DIR/sdk-install.log"
286310
311+ PYBLE_PINNED_NDK_VERSION="${PYBLE_ANDROID_NDK##*;}"
312+ PYBLE_PINNED_NDK_ROOT="$SDK_ROOT/ndk/$PYBLE_PINNED_NDK_VERSION"
313+ if [ ! -d "$PYBLE_PINNED_NDK_ROOT" ]; then
314+ echo "Pinned Android NDK is unavailable at $PYBLE_PINNED_NDK_ROOT" >&2
315+ exit 1
316+ fi
317+ export ANDROID_NDK="$PYBLE_PINNED_NDK_ROOT"
318+ export ANDROID_NDK_HOME="$PYBLE_PINNED_NDK_ROOT"
319+ export ANDROID_NDK_ROOT="$PYBLE_PINNED_NDK_ROOT"
320+ export ANDROID_NDK_PATH="$PYBLE_PINNED_NDK_ROOT"
321+ export ANDROID_NDK_LATEST_HOME="$PYBLE_PINNED_NDK_ROOT"
322+ df -h "$SDK_ROOT" \
323+ | tee "$PYBLE_ANDROID_LOG_DIR/disk-after-install.log"
324+
287325 printf '%s\n' \
288326 "PYBLE_ANDROID_SDK_ROOT=$SDK_ROOT" \
289327 "PYBLE_ANDROID_ADB=$SDK_ROOT/platform-tools/adb" \
290328 "PYBLE_ANDROID_EMULATOR=$SDK_ROOT/emulator/emulator" \
291329 "PYBLE_ANDROID_AVDMANAGER=$AVDMANAGER" \
330+ "ANDROID_NDK=$ANDROID_NDK" \
331+ "ANDROID_NDK_HOME=$ANDROID_NDK_HOME" \
332+ "ANDROID_NDK_ROOT=$ANDROID_NDK_ROOT" \
333+ "ANDROID_NDK_PATH=$ANDROID_NDK_PATH" \
334+ "ANDROID_NDK_LATEST_HOME=$ANDROID_NDK_LATEST_HOME" \
292335 >> "$GITHUB_ENV"
293336 - name : Create API 34 Google APIs x86_64 tablet AVD
294337 shell : bash
@@ -307,15 +350,15 @@ jobs:
307350 fi
308351 # Pixel Tablet at 2560x1600 / 320 dpi gives a deterministic
309352 # 1280x800 logical tablet surface, matching the Android test geometry.
310- # Keep userdata at 2 GiB so the complete API 34 image fits the hosted
311- # runner after its pinned SDK, build-tools, and NDK are installed .
353+ # API 34 first boot enforces a 6 GiB userdata minimum; state that
354+ # requirement explicitly after reclaiming unused runner NDKs above .
312355 # avdmanager pre-populates these keys. Upsert them so the emulator
313356 # cannot select an earlier device-profile value from a duplicate.
314357 python3 ../tools/ci/android_avd_config.py "$AVD_CONFIG" \
315358 --set 'hw.ramSize=3072' \
316359 --set 'hw.cpu.ncore=2' \
317360 --set 'vm.heapSize=512' \
318- --set 'disk.dataPartition.size=2048M ' \
361+ --set 'disk.dataPartition.size=6144M ' \
319362 --set 'hw.lcd.width=2560' \
320363 --set 'hw.lcd.height=1600' \
321364 --set 'hw.lcd.density=320' \
@@ -336,7 +379,7 @@ jobs:
336379
337380 nohup "$PYBLE_ANDROID_EMULATOR" \
338381 -avd "$PYBLE_ANDROID_AVD" \
339- -partition-size 2048 \
382+ -partition-size 6144 \
340383 -port 5554 \
341384 -no-window \
342385 -no-audio \
@@ -430,6 +473,9 @@ jobs:
430473 done
431474 echo
432475 "$PYBLE_ANDROID_ADB" devices -l
476+ echo
477+ echo "Runner disk usage:"
478+ df -h "$PYBLE_ANDROID_SDK_ROOT"
433479 } >"$PYBLE_ANDROID_LOG_DIR/ci-context.txt" 2>&1
434480
435481 if "$PYBLE_ANDROID_ADB" -s "$PYBLE_ANDROID_SERIAL" get-state \
@@ -447,7 +493,7 @@ jobs:
447493 fi
448494 AVD_CONFIG="$ANDROID_AVD_HOME/$PYBLE_ANDROID_AVD.avd/config.ini"
449495 if [ -f "$AVD_CONFIG" ]; then
450- grep -E '^(AvdId|PlayStore.enabled|abi.type|disk\.dataPartition\.size|hw\.(cpu\.ncore|device\.name|gpu\.(enabled|mode)|initialOrientation|lcd\.(density|height|width)|ramSize)|image\.sysdir\.1|tag\.(display|id)|vm\.heapSize)= ' \
496+ grep -E '^(AvdId|PlayStore.enabled|abi.type|disk\.dataPartition\.size|hw\.(cpu\.ncore|device\.name|gpu\.(enabled|mode)|initialOrientation|lcd\.(density|height|width)|ramSize)|image\.sysdir\.1|tag\.(display|id)|vm\.heapSize)[[:space:]]*=[[:space:]]* ' \
451497 "$AVD_CONFIG" >"$PYBLE_ANDROID_LOG_DIR/avd-config.txt"
452498 fi
453499 exit 0
0 commit comments