Skip to content

Conversation

jtschuster
Copy link
Member

@jtschuster jtschuster commented Jul 24, 2025

Adds a project to run a NativeAOT shared library on Android.

The android test builds a single native library that exports the methods that are expected by the monodroid tests (InitRuntime, SetEnv, ExecEntryPoint, FreeUnmanagedResources). JNI struct definitions are copied to get arg strings from the JNIEnv object.

ApkBuilder no longer needs to compile the monodroid native library, but it does need to add the java .jar from the cryptography library to the apk bundle in order to run crypto operations.

Build targets were updated to account for the new NativeAOT tests, and a new job was added for NativeAOT on android tests.

Copy link
Contributor

Tagging subscribers to this area: @akoeplinger, @matouskozak, @simonrozsival
See info in area-owners.md if you want to be subscribed.

Copy link
Contributor

Tagging subscribers to this area: @agocke, @MichalStrehovsky, @jkotas
See info in area-owners.md if you want to be subscribed.

@risc-vv
Copy link

risc-vv commented Jul 25, 2025

@dotnet/samsung Could you please take a look? These changes may be related to riscv64.

@jtschuster
Copy link
Member Author

/azp run runtime-androidemulator

Copy link

Azure Pipelines successfully started running 1 pipeline(s).

- Don't use BundleDir for android bundle dir: This is PublishDir when TestSingleFile=true (which it is). Android deletes this dir before packaging, deleting the files that were just published.

- Don't add the singleFileTestRunner.cs when the test sets IsFunctionalTest=true

- Don't run regular nativeaot smoke tests on android yet.

- Enable android tests to publish as libs when TestSingleFile=true (default when TestNativeAOT=true)
@jtschuster
Copy link
Member Author

/azp run runtime-androidemulator

Copy link

Azure Pipelines successfully started running 1 pipeline(s).

@jtschuster jtschuster marked this pull request as ready for review August 5, 2025 17:41
@Copilot Copilot AI review requested due to automatic review settings August 5, 2025 17:41
@jtschuster jtschuster requested a review from vitek-karas as a code owner August 5, 2025 17:41
Copy link
Contributor

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR adds support for running NativeAOT (Native Ahead-of-Time) compiled applications on Android. The implementation creates a shared library that exports the required JNI methods expected by the Android test infrastructure, eliminating the need for the monodroid runtime while maintaining compatibility with existing test frameworks.

Key changes include:

  • Added NativeAOT-specific Android test project and JNI interop layer
  • Updated build infrastructure to support NativeAOT runtime flavor
  • Modified Android app builder to handle NativeAOT library generation and packaging

Reviewed Changes

Copilot reviewed 16 out of 16 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
src/tests/FunctionalTests/Android/Device_Emulator/NativeAOT/Program.cs Simple test program that validates console output and cryptography functionality
src/tests/FunctionalTests/Android/Device_Emulator/NativeAOT/Android.Device_Emulator.NativeAOT.Test.csproj Project file configuring NativeAOT compilation with required JNI template inclusion
src/tasks/AndroidAppBuilder/Templates/monodroid-nativeaot.cs JNI interop layer implementing required Android runtime interface methods
src/tasks/AndroidAppBuilder/Templates/MonoRunner.java Updated Java template to support dynamic library loading statements
src/tasks/AndroidAppBuilder/ApkBuilder.cs Enhanced APK builder with NativeAOT runtime support and library packaging
src/mono/msbuild/android/build/AndroidBuild.targets Updated build targets to handle NativeAOT runtime flavor and dependencies
src/mono/msbuild/android/build/AndroidBuild.props Added Android NDK toolchain configuration and NativeAOT build dependencies
src/libraries/tests.proj Modified test project inclusion logic for NativeAOT Android tests
src/coreclr/nativeaot/Runtime/interoplibinterface_java.cpp Added missing thread.inl include for Java interop
src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.Unix.targets Extended cross-compilation support for android- RID prefix
src/coreclr/nativeaot/BuildIntegration/Microsoft.DotNet.ILCompiler.SingleEntry.targets Added Android bionic libc flavor detection
eng/testing/tests.singlefile.targets Conditional OutputType and compilation adjustments for Android NativeAOT
eng/testing/tests.android.targets Removed redundant AndroidBundleDir property assignment
eng/pipelines/extra-platforms/runtime-extra-platforms-androidemulator.yml Added CI pipeline job for NativeAOT Android emulator testing
eng/pipelines/extra-platforms/runtime-extra-platforms-android.yml Added CI pipeline job for NativeAOT Android device testing

@jtschuster
Copy link
Member Author

/azp run runtime-androidemulator

Copy link

Azure Pipelines successfully started running 1 pipeline(s).

@filipnavara
Copy link
Member

filipnavara commented Aug 6, 2025

There's one thing that we should still fix:

--- a/src/coreclr/tools/aot/ILCompiler.Build.Tasks/ComputeManagedAssembliesToCompileToNative.cs
+++ b/src/coreclr/tools/aot/ILCompiler.Build.Tasks/ComputeManagedAssembliesToCompileToNative.cs
@@ -130,7 +130,9 @@ public override bool Execute()
                     continue;
                 }

-                if (isFromRuntimePack && taskItem.GetMetadata("AssetType")?.Equals("native", StringComparison.OrdinalIgnoreCase) == true)
+                if (isFromRuntimePack && taskItem.GetMetadata("AssetType")?.Equals("native", StringComparison.OrdinalIgnoreCase) == true &&
+                    !assemblyFileName.EndsWith(".jar", StringComparison.OrdinalIgnoreCase) &&
+                    !assemblyFileName.EndsWith(".dex", StringComparison.OrdinalIgnoreCase))
                 {
                     // Skip the native components of the runtime pack, we don't need them for NativeAOT.
                     assembliesToSkipPublish.Add(taskItem);

The native assets of the Android runtime files now contain the .jar/.dex files for libSystem.Security.Cryptography.Android. We should not strip them in ComputeManagedAssembliesToCompileToNative build target to keep the HTTP stack working.

Copy link
Member

@filipnavara filipnavara left a comment

Choose a reason for hiding this comment

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

I tested that it makes the Android runtime pack into functional state that can be consumed on the workload side and used to build a whole app. Obviously there's still work that has to be done on the consumption side (dotnet/android) but having an end-to-end scenrio running is a good start:

image

One thing that still needs to be resolved is who is responsible for exporting the JNI symbol for Java_net_dot_android_crypto_DotnetProxyTrustManager_verifyRemoteCertificate in case of the builds that link the crypto libraries statically. Presumably that can and will be done on the Android workload side with something like <IlcArg Include="--export-dynamic-symbol:Java_net_dot_android_crypto_DotnetProxyTrustManager_verifyRemoteCertificate" />.

@vitek-karas
Copy link
Member

@filipnavara maybe this will solve the JNI export problem for crypto: #108513

@filipnavara
Copy link
Member

@filipnavara maybe this will solve the JNI export problem for crypto: #108513

Yes, that's part of the solution. There's an issue for CoreCLR integration filed at dotnet/android#10324 that has a bit more context.

@jtschuster
Copy link
Member Author

/azp run runtime-androidemulator

Copy link

Azure Pipelines successfully started running 1 pipeline(s).

@jtschuster jtschuster requested a review from agocke August 8, 2025 18:05
@jtschuster
Copy link
Member Author

/ba-g failures are unrelated

@jtschuster jtschuster merged commit 1e322fd into dotnet:main Aug 11, 2025
154 of 162 checks passed
@github-project-automation github-project-automation bot moved this to Done in AppModel Aug 11, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: Done
Development

Successfully merging this pull request may close these issues.