Skip to content

Android emulator - #164

Merged
CedricGuillemet merged 25 commits into
BabylonJS:mainfrom
CedricGuillemet:AndroidEmulator
Apr 22, 2026
Merged

Android emulator#164
CedricGuillemet merged 25 commits into
BabylonJS:mainfrom
CedricGuillemet:AndroidEmulator

Conversation

@CedricGuillemet

@CedricGuillemetCedricGuillemet commented Apr 20, 2026

Copy link
Copy Markdown
Collaborator

Brings back Android Emulator tests.

CedricGuillemetand others added 24 commits April 20, 2026 15:13
- Creates Android AVD with system images stored in scripts/avd_home/
- Auto-detects installed system image ABI (arm64-v8a / x86_64) from SDK
- Uses ANDROID_AVD_HOME consistently for avdmanager + emulator commands
- Compiles hello_world/hello.c with latest NDK clang for detected ABI
- Pushes binary to emulator, runs it, verifies 'hello world' in logcat
- Polls logcat instead of fixed sleep for reliable verification
- Manages emulator lifecycle on fixed port 5554 to avoid killing unrelated instances
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Homebrew's avdmanager wrapper derives the Android SDK root from the
'com.android.sdkmanager.toolsdir' JVM property, which defaults to
its own Homebrew cellar directory and therefore cannot find installed
system images.
Fix: export AVDMANAGER_OPTS and SDKMANAGER_OPTS with toolsdir set to
$ANDROID_SDK/platform-tools so avdmanager computes the correct SDK root
(one level up from platform-tools = the ANDROID_HOME directory).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Three bugs fixed:
1. config.ini image path: Homebrew avdmanager writes image.sysdir.1
relative to dirname(ANDROID_SDK), producing 'sdk/system-images/...'
Post-patch strips the spurious 'sdk/' prefix so the emulator resolves
the path correctly against ANDROID_SDK_ROOT=ANDROID_SDK.
2. set -eo pipefail + adb during boot: adb shell/get-state return non-zero
transiently while the emulator is still initializing, silently killing
the script. All adb calls in wait loops now use '|| true' guards.
3. Device online check: replaced 'adb wait-for-device | grep' pipeline
(fragile under pipefail) with an explicit get-state polling loop that
also checks emulator process health.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…Logger
- Add scripts/android_unit_tests.sh: end-to-end pipeline that builds the
UnitTests Android project with gradlew, starts the AVD emulator, deploys
and runs the instrumented tests, and reports pass/fail.
Auto-detects the highest installed NDK to override the pinned ndkVersion
in build.gradle (NDK 23 lacks C++20 support needed by the codebase).
- Add patches/AndroidExtensions/StdoutLogger.cpp: fix an fdsan violation
that caused SIGABRT on Android API 29+.
StdoutLogger::Start() calls fdopen(fd[0]) which transfers fd ownership to
the FILE*. StdoutLogger::Stop() was then calling close(fd[0]) directly,
violating fdsan's ownership rules. Fix: only close the write ends (fd[1])
in Stop(); the reader threads close the read ends via fclose().
- Wire the patch into CMakeLists.txt via FetchContent_Declare PATCH_COMMAND
so clean builds automatically apply the fix after fetching AndroidExtensions.
Test results (Android 36, arm64-v8a):
136 JavaScript tests passing (3s)
[ PASSED ] 3 tests from 3 suites (JavaScript.All, Console.Log, AppRuntime.DestroyDoesNotDeadlock)
0 failures
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
scripts/android_emulator_test.sh and scripts/hello_world/hello.c are
removed. The UnitTests Android pipeline (scripts/android_unit_tests.sh)
is the sole test entry point.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Replace 'for xml in ... 2>/dev/null' (invalid shell syntax) with
'find | while read' which handles redirection correctly.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Start adb logcat capture (after boot, before tests) into scripts/logcat.log
- Stop capture and print the path in the cleanup trap
- On failure, print filtered logcat (StdoutLogger/TestRunner/crash lines)
inline so failures are immediately visible without extra commands
- gitignore scripts/logcat.log
Usage after a run:
grep StdoutLogger scripts/logcat.log # test output
cat scripts/logcat.log # everything
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Initialize LOGCAT_PID to empty string before the trap is registered so
set -u does not abort if the script exits before logcat capture starts.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Replace the local PATCH_COMMAND workaround with a direct reference to
the fix commit on the fork (PR: BabylonJS/AndroidExtensions#17).
Remove patches/AndroidExtensions/StdoutLogger.cpp.
Once the PR is merged upstream, revert GIT_REPOSITORY back to
BabylonJS/AndroidExtensions and update GIT_TAG to the merge commit.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
build-android.yml:
- Add 'Install NDK' step (sdkmanager ndk;28.2.13676358) so the pinned
NDK version is guaranteed to be present on the runner
- Add 'Build JS test bundle' step (npm install in Tests/) which triggers
the postinstall webpack build producing UnitTests/dist/tests.js
- Add -no-snapshot -no-window -no-boot-anim -no-audio to emulator-options
ci.yml:
- Enable Android_V8 job (removes the TODO comment block)
- Keep Android_JSC commented until verified
Remove scripts/android_unit_tests.sh (superseded by the workflow).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Each line of 'script:' is executed as a separate sh -c invocation,
so cd does not persist. Use full path + -p flag instead.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ion bug
android-emulator-runner runs each script line in a separate sh -c call,
so backslash line continuations are passed as literal args to Gradle,
causing 'Task backslash not found' and -PndkVersion never reaching Gradle.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Write a proper shell script before the emulator starts:
- Clear logcat before the test run
- Capture logcat to a file in background while tests run
- Preserve the gradlew exit code
- Upload logcat.txt as a downloadable artifact per engine
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
PR BabylonJS#17 (fix-fdsan-stdout-logger) has been merged into BabylonJS/AndroidExtensions.
Switch from fork to upstream at the merge commit 5fe60c8.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
v4 runs on Node.js 20 which is deprecated on GitHub Actions runners.
v5 uses node24. All other actions in this workflow already use node24.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The Android emulator routes traffic through QEMU NAT which adds
significant latency vs native. The single-connection test already
took 1741ms of the 2000ms budget; the multi-connection test (two
serial round trips) reliably exceeded it.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
setup-java@v4 and upload-artifact@v4 tagged releases still run on
node20. Set FORCE_JAVASCRIPT_ACTIONS_TO_NODE24=true to suppress the
deprecation warning until v5 releases are available.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Re-enables Android CI coverage by bringing back emulator-based connected tests and updating supporting build/dependency plumbing so Android unit tests can run reliably in GitHub Actions.

Changes:

  • Re-enabled Android (JSC/V8) jobs in the main CI workflow.
  • Updated the Android reusable workflow to install the NDK, build the JS test bundle, and run connectedAndroidTest via the emulator runner.
  • Minor supporting updates: bump actions/checkout version, update AndroidExtensions revision, adjust a WebSocket test timeout, and fix Android NDK log header include casing.

Reviewed changes

Copilot reviewed 10 out of 10 changed files in this pull request and generated 1 comment.

Show a summary per file
FileDescription
Tests/UnitTests/Scripts/tests.tsIncreases timeout for the multi-WebSocket test to reduce flakiness.
Tests/UnitTests/Android/app/src/main/cpp/JNI.cppFixes NDK header include casing (android/log.h).
CMakeLists.txtUpdates AndroidExtensions FetchContent GIT_TAG.
.github/workflows/ci.ymlRe-enables Android CI jobs (JSC and V8).
.github/workflows/build-win32.ymlBumps actions/checkout to v5.
.github/workflows/build-uwp.ymlBumps actions/checkout to v5.
.github/workflows/build-macos.ymlBumps actions/checkout to v5.
.github/workflows/build-linux.ymlBumps actions/checkout to v5.
.github/workflows/build-ios.ymlBumps actions/checkout to v5.
.github/workflows/build-android.ymlInstalls NDK, builds JS test bundle, and runs emulator connected tests; bumps actions/checkout to v5.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread.github/workflows/build-android.yml Outdated
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@CedricGuillemet
CedricGuillemet merged commit 7239f91 into BabylonJS:mainApr 22, 2026
44 of 45 checks passed
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@CedricGuillemet@bghgary