Hook up more integrations to NativeAOT with Android RIDs - #10402

Closed
jkoritzinsky wants to merge 5 commits into
dotnet:mainfrom
jkoritzinsky:naot-android-rid
Closed

Hook up more integrations to NativeAOT with Android RIDs#10402
jkoritzinsky wants to merge 5 commits into
dotnet:mainfrom
jkoritzinsky:naot-android-rid

Conversation

@jkoritzinsky

Copy link
Copy Markdown
Member

Try hooking up the Android crypto stack, GC integration, and logging to NativeAOT correctly.

cc: @filipnavara@jtschuster

@jonathanpeppers

Copy link
Copy Markdown
Member

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

Comment threadsrc/native/clr/host/CMakeLists.txt Outdated
os-bridge.cc
runtime-util.cc
typemap.cc
xamarin_getifaddrs.cc

@filipnavarafilipnavaraAug 12, 2025

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This will produce conflict with #10385. Not a big deal, just wanted to avoid dragging unused code into newly supported runtimes.

@filipnavara

filipnavara commented Aug 12, 2025

Copy link
Copy Markdown
Member

I'll need to dig a bit deeper but the subset linking of the native lib is still not quite correct:

08-12 10:30:01.122 26235 26235 E AndroidRuntime: java.lang.UnsatisfiedLinkError: dlopen failed: cannot locate symbol "_monodroid_detect_cpu_and_architecture" referenced by "/data/app/~~grvY0oxLa6M-yS3DDLG0hg==/com.emclient.mailclient-XUnDyFyf6XZEZfGtl53aBg==/lib/x86_64/libMailClient.Mobile.Android.so"...
08-12 10:30:01.122 26235 26235 E AndroidRuntime: at java.lang.Runtime.loadLibrary0(Runtime.java:1090)
08-12 10:30:01.122 26235 26235 E AndroidRuntime: at java.lang.Runtime.loadLibrary0(Runtime.java:1012)
08-12 10:30:01.122 26235 26235 E AndroidRuntime: at java.lang.System.loadLibrary(System.java:1765)
08-12 10:30:01.122 26235 26235 E AndroidRuntime: at net.dot.jni.nativeaot.JavaInteropRuntime.<clinit>(JavaInteropRuntime.java:8)
08-12 10:30:01.122 26235 26235 E AndroidRuntime: at net.dot.jni.nativeaot.NativeAotRuntimeProvider.attachInfo(NativeAotRuntimeProvider.java:43)
08-12 10:30:01.122 26235 26235 E AndroidRuntime: at android.app.ActivityThread.installProvider(ActivityThread.java:8642)
08-12 10:30:01.122 26235 26235 E AndroidRuntime: at android.app.ActivityThread.installContentProviders(ActivityThread.java:8157)
08-12 10:30:01.122 26235 26235 E AndroidRuntime: at android.app.ActivityThread.handleBindApplication(ActivityThread.java:7814)
08-12 10:30:01.122 26235 26235 E AndroidRuntime: at android.app.ActivityThread.-$$Nest$mhandleBindApplication(Unknown Source:0)
08-12 10:30:01.122 26235 26235 E AndroidRuntime: at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2546)
08-12 10:30:01.122 26235 26235 E AndroidRuntime: at android.os.Handler.dispatchMessage(Handler.java:110)
08-12 10:30:01.122 26235 26235 E AndroidRuntime: at android.os.Looper.loopOnce(Looper.java:248)
08-12 10:30:01.122 26235 26235 E AndroidRuntime: at android.os.Looper.loop(Looper.java:338)
08-12 10:30:01.122 26235 26235 E AndroidRuntime: at android.app.ActivityThread.main(ActivityThread.java:9067)
08-12 10:30:01.122 26235 26235 E AndroidRuntime: at java.lang.reflect.Method.invoke(Native Method)
08-12 10:30:01.122 26235 26235 E AndroidRuntime: at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:593)
08-12 10:30:01.122 26235 26235 E AndroidRuntime: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:932)

...and even if it tried to link to the native library we are still missing some bits:

 ld.lld : error : undefined hidden symbol: xamarin::android::Helpers::abort_application(_LogCategories, char const*, bool, std::__ndk1::source_location)

UPD: Nvm, I was missing xa-shared-bits in the second attempt.

@filipnavara

filipnavara commented Aug 12, 2025

Copy link
Copy Markdown
Member

I have a heavily hacked up build locally that was able to pass startup of our app:

image

Aside from all the comments above and solving general linking breakage / undefined symbols, we will need to embrace GCUserPeerable because NativeAOT builds use different interop generation mode (XAJavaInterop1 vs JavaInterop1).

The garbage collection part seems to work but for some reason it's triggered way too often to the point of feeling like running all the time. It will need to be investigated, the startup takes literally minute[s] because of all the triggered collections. (UPD: Could be It is just uninitialized value for GREF threshold).

@filipnavara

Copy link
Copy Markdown
Member

Here's a rough commit with the changes I have locally to get this working: filipnavara@4a59c50

It still needs a lot of cleanup. We also need updated runtime packs to get it working end-to-end.

@jonathanpeppers

Copy link
Copy Markdown
Member

@jkoritzinsky FYI the latest Maestro bump, it seems like we need to make changes like:

This allows the NativeAOT runtime packs (with proper Android RIDs!) to work.

Do we need to add the two Android RIDs to this line:

That made things work for me locally, but CI is ongoing.

@jonathanpeppers

Copy link
Copy Markdown
Member

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@akoeplinger

Copy link
Copy Markdown
Member

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@jkoritzinsky

Copy link
Copy Markdown
MemberAuthor

I'm looking at the NAOT failures and it looks like it can't find the native files in the package even though they are present in the NativeAOT runtime package.

I did notice that the runtime package is built with a -ci version and the test expects it to have a stable version. Is that expected?

@jonathanpeppers

Copy link
Copy Markdown
Member

Ok, the data/RuntimeList.xml file looks OK:

<FileListTargetFrameworkIdentifier=".NETStandard"TargetFrameworkVersion="2.0"FrameworkName="Microsoft.Android.Runtimes"Name=".NET 10.0 - Microsoft.Android.Runtimes">
<FileType="Managed"Path="runtimes/android-arm64/lib/net10.0/Microsoft.Android.Runtime.NativeAOT.dll"AssemblyName="Microsoft.Android.Runtime.NativeAOT"PublicKeyToken="84e04ff9cfb79065"AssemblyVersion="1.0.0.0"FileVersion="1.0.0.0"Profile="Android" />
<FileType="Native"Path="runtimes/android-arm64/native/libnet-android-nativeaot-debug.a"FileVersion="0.0.0.0"Profile="Android" />
<FileType="Native"Path="runtimes/android-arm64/native/libnet-android-nativeaot-release.a"FileVersion="0.0.0.0"Profile="Android" />
<FileType="Native"Path="runtimes/android-arm64/native/libxa-shared-bits-debug.a"FileVersion="0.0.0.0"Profile="Android" />
<FileType="Native"Path="runtimes/android-arm64/native/libxa-shared-bits-release.a"FileVersion="0.0.0.0"Profile="Android" />
</FileList>

But then I noticed:

image

The arm and x86 packs are smaller, so they are missing the new files.

But we should probably just stop producing the arm and x86 packs completely, and then see if some of the failing tests were targeting x86 or something.

@jonathanpeppers

jonathanpeppers commented Aug 20, 2025

Copy link
Copy Markdown
Member

I tried to push a change (says I can't push to jkoritzinsky/dotnet-android), but I sent a different PR for main:

@jkoritzinsky

Copy link
Copy Markdown
MemberAuthor

You should be able to push to my fork (I have the "allow edits by maintainers" checkbox checked), weird. Thanks for looking into this for me.

@jonathanpeppers

Copy link
Copy Markdown
Member

#10432 is good but may not fully fix this -- basically nothing broke when I removed the x86 and arm packs.

So, I'll try building this locally when I can.

Comment threadbuild-tools/create-packs/Microsoft.Android.Runtime.proj Outdated
@grendello

Copy link
Copy Markdown
Contributor

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

Comment threadsrc/native/native.targets Outdated
@jkoritzinsky
jkoritzinsky marked this pull request as ready for review September 16, 2025 19:17

namespace Microsoft.Android.Runtime;

struct DiagnosticSettings {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

So, I think we'll want to restore the GrefLog and LrefLog logs or we'll have no way to get these in NativeAOT.

Long term, we were going to use some EventSource API, but maybe we can just leave the simple thing in here for now.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

Removing this infra is basically the last part of this PR that wasn't subsumed by the other PR that already went in.

I'll close this PR as there's really nothing in it at this point.

Comment on lines -19 to -23
static LogcatTextWriter ()
{
Console.SetOut (new LogcatTextWriter (AndroidLogLevel.Info));
Console.SetError (new LogcatTextWriter (AndroidLogLevel.Error));
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@jkoritzinsky I think this part is useful, so maybe I can do this part in a different PR.

This was here originally, because Console.WriteLine() didn't output to logcat.

@github-actionsgithub-actionsBot locked and limited conversation to collaborators Oct 17, 2025
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants

@jkoritzinsky@jonathanpeppers@filipnavara@akoeplinger@grendello
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Hook up more integrations to NativeAOT with Android RIDs - #10402

Closed
jkoritzinsky wants to merge 5 commits into
dotnet:mainfrom
jkoritzinsky:naot-android-rid
Closed

Hook up more integrations to NativeAOT with Android RIDs#10402
jkoritzinsky wants to merge 5 commits into
dotnet:mainfrom
jkoritzinsky:naot-android-rid

Conversation

@jkoritzinsky

Copy link
Copy Markdown
Member

Try hooking up the Android crypto stack, GC integration, and logging to NativeAOT correctly.

cc: @filipnavara@jtschuster

@jonathanpeppers

Copy link
Copy Markdown
Member

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

Comment threadsrc/native/clr/host/CMakeLists.txt Outdated
os-bridge.cc
runtime-util.cc
typemap.cc
xamarin_getifaddrs.cc

@filipnavarafilipnavaraAug 12, 2025

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This will produce conflict with #10385. Not a big deal, just wanted to avoid dragging unused code into newly supported runtimes.

@filipnavara

filipnavara commented Aug 12, 2025

Copy link
Copy Markdown
Member

I'll need to dig a bit deeper but the subset linking of the native lib is still not quite correct:

08-12 10:30:01.122 26235 26235 E AndroidRuntime: java.lang.UnsatisfiedLinkError: dlopen failed: cannot locate symbol "_monodroid_detect_cpu_and_architecture" referenced by "/data/app/~~grvY0oxLa6M-yS3DDLG0hg==/com.emclient.mailclient-XUnDyFyf6XZEZfGtl53aBg==/lib/x86_64/libMailClient.Mobile.Android.so"...
08-12 10:30:01.122 26235 26235 E AndroidRuntime: at java.lang.Runtime.loadLibrary0(Runtime.java:1090)
08-12 10:30:01.122 26235 26235 E AndroidRuntime: at java.lang.Runtime.loadLibrary0(Runtime.java:1012)
08-12 10:30:01.122 26235 26235 E AndroidRuntime: at java.lang.System.loadLibrary(System.java:1765)
08-12 10:30:01.122 26235 26235 E AndroidRuntime: at net.dot.jni.nativeaot.JavaInteropRuntime.<clinit>(JavaInteropRuntime.java:8)
08-12 10:30:01.122 26235 26235 E AndroidRuntime: at net.dot.jni.nativeaot.NativeAotRuntimeProvider.attachInfo(NativeAotRuntimeProvider.java:43)
08-12 10:30:01.122 26235 26235 E AndroidRuntime: at android.app.ActivityThread.installProvider(ActivityThread.java:8642)
08-12 10:30:01.122 26235 26235 E AndroidRuntime: at android.app.ActivityThread.installContentProviders(ActivityThread.java:8157)
08-12 10:30:01.122 26235 26235 E AndroidRuntime: at android.app.ActivityThread.handleBindApplication(ActivityThread.java:7814)
08-12 10:30:01.122 26235 26235 E AndroidRuntime: at android.app.ActivityThread.-$$Nest$mhandleBindApplication(Unknown Source:0)
08-12 10:30:01.122 26235 26235 E AndroidRuntime: at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2546)
08-12 10:30:01.122 26235 26235 E AndroidRuntime: at android.os.Handler.dispatchMessage(Handler.java:110)
08-12 10:30:01.122 26235 26235 E AndroidRuntime: at android.os.Looper.loopOnce(Looper.java:248)
08-12 10:30:01.122 26235 26235 E AndroidRuntime: at android.os.Looper.loop(Looper.java:338)
08-12 10:30:01.122 26235 26235 E AndroidRuntime: at android.app.ActivityThread.main(ActivityThread.java:9067)
08-12 10:30:01.122 26235 26235 E AndroidRuntime: at java.lang.reflect.Method.invoke(Native Method)
08-12 10:30:01.122 26235 26235 E AndroidRuntime: at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:593)
08-12 10:30:01.122 26235 26235 E AndroidRuntime: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:932)

...and even if it tried to link to the native library we are still missing some bits:

 ld.lld : error : undefined hidden symbol: xamarin::android::Helpers::abort_application(_LogCategories, char const*, bool, std::__ndk1::source_location)

UPD: Nvm, I was missing xa-shared-bits in the second attempt.

@filipnavara

filipnavara commented Aug 12, 2025

Copy link
Copy Markdown
Member

I have a heavily hacked up build locally that was able to pass startup of our app:

image

Aside from all the comments above and solving general linking breakage / undefined symbols, we will need to embrace GCUserPeerable because NativeAOT builds use different interop generation mode (XAJavaInterop1 vs JavaInterop1).

The garbage collection part seems to work but for some reason it's triggered way too often to the point of feeling like running all the time. It will need to be investigated, the startup takes literally minute[s] because of all the triggered collections. (UPD: Could be It is just uninitialized value for GREF threshold).

@filipnavara

Copy link
Copy Markdown
Member

Here's a rough commit with the changes I have locally to get this working: filipnavara@4a59c50

It still needs a lot of cleanup. We also need updated runtime packs to get it working end-to-end.

@jonathanpeppers

Copy link
Copy Markdown
Member

@jkoritzinsky FYI the latest Maestro bump, it seems like we need to make changes like:

This allows the NativeAOT runtime packs (with proper Android RIDs!) to work.

Do we need to add the two Android RIDs to this line:

That made things work for me locally, but CI is ongoing.

@jonathanpeppers

Copy link
Copy Markdown
Member

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@akoeplinger

Copy link
Copy Markdown
Member

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@jkoritzinsky

Copy link
Copy Markdown
MemberAuthor

I'm looking at the NAOT failures and it looks like it can't find the native files in the package even though they are present in the NativeAOT runtime package.

I did notice that the runtime package is built with a -ci version and the test expects it to have a stable version. Is that expected?

@jonathanpeppers

Copy link
Copy Markdown
Member

Ok, the data/RuntimeList.xml file looks OK:

<FileListTargetFrameworkIdentifier=".NETStandard"TargetFrameworkVersion="2.0"FrameworkName="Microsoft.Android.Runtimes"Name=".NET 10.0 - Microsoft.Android.Runtimes">
<FileType="Managed"Path="runtimes/android-arm64/lib/net10.0/Microsoft.Android.Runtime.NativeAOT.dll"AssemblyName="Microsoft.Android.Runtime.NativeAOT"PublicKeyToken="84e04ff9cfb79065"AssemblyVersion="1.0.0.0"FileVersion="1.0.0.0"Profile="Android" />
<FileType="Native"Path="runtimes/android-arm64/native/libnet-android-nativeaot-debug.a"FileVersion="0.0.0.0"Profile="Android" />
<FileType="Native"Path="runtimes/android-arm64/native/libnet-android-nativeaot-release.a"FileVersion="0.0.0.0"Profile="Android" />
<FileType="Native"Path="runtimes/android-arm64/native/libxa-shared-bits-debug.a"FileVersion="0.0.0.0"Profile="Android" />
<FileType="Native"Path="runtimes/android-arm64/native/libxa-shared-bits-release.a"FileVersion="0.0.0.0"Profile="Android" />
</FileList>

But then I noticed:

image

The arm and x86 packs are smaller, so they are missing the new files.

But we should probably just stop producing the arm and x86 packs completely, and then see if some of the failing tests were targeting x86 or something.

@jonathanpeppers

jonathanpeppers commented Aug 20, 2025

Copy link
Copy Markdown
Member

I tried to push a change (says I can't push to jkoritzinsky/dotnet-android), but I sent a different PR for main:

@jkoritzinsky

Copy link
Copy Markdown
MemberAuthor

You should be able to push to my fork (I have the "allow edits by maintainers" checkbox checked), weird. Thanks for looking into this for me.

@jonathanpeppers

Copy link
Copy Markdown
Member

#10432 is good but may not fully fix this -- basically nothing broke when I removed the x86 and arm packs.

So, I'll try building this locally when I can.

Comment threadbuild-tools/create-packs/Microsoft.Android.Runtime.proj Outdated
@grendello

Copy link
Copy Markdown
Contributor

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

Comment threadsrc/native/native.targets Outdated
@jkoritzinsky
jkoritzinsky marked this pull request as ready for review September 16, 2025 19:17

namespace Microsoft.Android.Runtime;

struct DiagnosticSettings {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

So, I think we'll want to restore the GrefLog and LrefLog logs or we'll have no way to get these in NativeAOT.

Long term, we were going to use some EventSource API, but maybe we can just leave the simple thing in here for now.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

Removing this infra is basically the last part of this PR that wasn't subsumed by the other PR that already went in.

I'll close this PR as there's really nothing in it at this point.

Comment on lines -19 to -23
static LogcatTextWriter ()
{
Console.SetOut (new LogcatTextWriter (AndroidLogLevel.Info));
Console.SetError (new LogcatTextWriter (AndroidLogLevel.Error));
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@jkoritzinsky I think this part is useful, so maybe I can do this part in a different PR.

This was here originally, because Console.WriteLine() didn't output to logcat.

@github-actionsgithub-actionsBot locked and limited conversation to collaborators Oct 17, 2025
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants

@jkoritzinsky@jonathanpeppers@filipnavara@akoeplinger@grendello
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Hook up more integrations to NativeAOT with Android RIDs - #10402

Closed
jkoritzinsky wants to merge 5 commits into
dotnet:mainfrom
jkoritzinsky:naot-android-rid
Closed

Hook up more integrations to NativeAOT with Android RIDs#10402
jkoritzinsky wants to merge 5 commits into
dotnet:mainfrom
jkoritzinsky:naot-android-rid

Conversation

@jkoritzinsky

Copy link
Copy Markdown
Member

Try hooking up the Android crypto stack, GC integration, and logging to NativeAOT correctly.

cc: @filipnavara@jtschuster

@jonathanpeppers

Copy link
Copy Markdown
Member

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

Comment threadsrc/native/clr/host/CMakeLists.txt Outdated
os-bridge.cc
runtime-util.cc
typemap.cc
xamarin_getifaddrs.cc

@filipnavarafilipnavaraAug 12, 2025

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This will produce conflict with #10385. Not a big deal, just wanted to avoid dragging unused code into newly supported runtimes.

@filipnavara

filipnavara commented Aug 12, 2025

Copy link
Copy Markdown
Member

I'll need to dig a bit deeper but the subset linking of the native lib is still not quite correct:

08-12 10:30:01.122 26235 26235 E AndroidRuntime: java.lang.UnsatisfiedLinkError: dlopen failed: cannot locate symbol "_monodroid_detect_cpu_and_architecture" referenced by "/data/app/~~grvY0oxLa6M-yS3DDLG0hg==/com.emclient.mailclient-XUnDyFyf6XZEZfGtl53aBg==/lib/x86_64/libMailClient.Mobile.Android.so"...
08-12 10:30:01.122 26235 26235 E AndroidRuntime: at java.lang.Runtime.loadLibrary0(Runtime.java:1090)
08-12 10:30:01.122 26235 26235 E AndroidRuntime: at java.lang.Runtime.loadLibrary0(Runtime.java:1012)
08-12 10:30:01.122 26235 26235 E AndroidRuntime: at java.lang.System.loadLibrary(System.java:1765)
08-12 10:30:01.122 26235 26235 E AndroidRuntime: at net.dot.jni.nativeaot.JavaInteropRuntime.<clinit>(JavaInteropRuntime.java:8)
08-12 10:30:01.122 26235 26235 E AndroidRuntime: at net.dot.jni.nativeaot.NativeAotRuntimeProvider.attachInfo(NativeAotRuntimeProvider.java:43)
08-12 10:30:01.122 26235 26235 E AndroidRuntime: at android.app.ActivityThread.installProvider(ActivityThread.java:8642)
08-12 10:30:01.122 26235 26235 E AndroidRuntime: at android.app.ActivityThread.installContentProviders(ActivityThread.java:8157)
08-12 10:30:01.122 26235 26235 E AndroidRuntime: at android.app.ActivityThread.handleBindApplication(ActivityThread.java:7814)
08-12 10:30:01.122 26235 26235 E AndroidRuntime: at android.app.ActivityThread.-$$Nest$mhandleBindApplication(Unknown Source:0)
08-12 10:30:01.122 26235 26235 E AndroidRuntime: at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2546)
08-12 10:30:01.122 26235 26235 E AndroidRuntime: at android.os.Handler.dispatchMessage(Handler.java:110)
08-12 10:30:01.122 26235 26235 E AndroidRuntime: at android.os.Looper.loopOnce(Looper.java:248)
08-12 10:30:01.122 26235 26235 E AndroidRuntime: at android.os.Looper.loop(Looper.java:338)
08-12 10:30:01.122 26235 26235 E AndroidRuntime: at android.app.ActivityThread.main(ActivityThread.java:9067)
08-12 10:30:01.122 26235 26235 E AndroidRuntime: at java.lang.reflect.Method.invoke(Native Method)
08-12 10:30:01.122 26235 26235 E AndroidRuntime: at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:593)
08-12 10:30:01.122 26235 26235 E AndroidRuntime: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:932)

...and even if it tried to link to the native library we are still missing some bits:

 ld.lld : error : undefined hidden symbol: xamarin::android::Helpers::abort_application(_LogCategories, char const*, bool, std::__ndk1::source_location)

UPD: Nvm, I was missing xa-shared-bits in the second attempt.

@filipnavara

filipnavara commented Aug 12, 2025

Copy link
Copy Markdown
Member

I have a heavily hacked up build locally that was able to pass startup of our app:

image

Aside from all the comments above and solving general linking breakage / undefined symbols, we will need to embrace GCUserPeerable because NativeAOT builds use different interop generation mode (XAJavaInterop1 vs JavaInterop1).

The garbage collection part seems to work but for some reason it's triggered way too often to the point of feeling like running all the time. It will need to be investigated, the startup takes literally minute[s] because of all the triggered collections. (UPD: Could be It is just uninitialized value for GREF threshold).

@filipnavara

Copy link
Copy Markdown
Member

Here's a rough commit with the changes I have locally to get this working: filipnavara@4a59c50

It still needs a lot of cleanup. We also need updated runtime packs to get it working end-to-end.

@jonathanpeppers

Copy link
Copy Markdown
Member

@jkoritzinsky FYI the latest Maestro bump, it seems like we need to make changes like:

This allows the NativeAOT runtime packs (with proper Android RIDs!) to work.

Do we need to add the two Android RIDs to this line:

That made things work for me locally, but CI is ongoing.

@jonathanpeppers

Copy link
Copy Markdown
Member

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@akoeplinger

Copy link
Copy Markdown
Member

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@jkoritzinsky

Copy link
Copy Markdown
MemberAuthor

I'm looking at the NAOT failures and it looks like it can't find the native files in the package even though they are present in the NativeAOT runtime package.

I did notice that the runtime package is built with a -ci version and the test expects it to have a stable version. Is that expected?

@jonathanpeppers

Copy link
Copy Markdown
Member

Ok, the data/RuntimeList.xml file looks OK:

<FileListTargetFrameworkIdentifier=".NETStandard"TargetFrameworkVersion="2.0"FrameworkName="Microsoft.Android.Runtimes"Name=".NET 10.0 - Microsoft.Android.Runtimes">
<FileType="Managed"Path="runtimes/android-arm64/lib/net10.0/Microsoft.Android.Runtime.NativeAOT.dll"AssemblyName="Microsoft.Android.Runtime.NativeAOT"PublicKeyToken="84e04ff9cfb79065"AssemblyVersion="1.0.0.0"FileVersion="1.0.0.0"Profile="Android" />
<FileType="Native"Path="runtimes/android-arm64/native/libnet-android-nativeaot-debug.a"FileVersion="0.0.0.0"Profile="Android" />
<FileType="Native"Path="runtimes/android-arm64/native/libnet-android-nativeaot-release.a"FileVersion="0.0.0.0"Profile="Android" />
<FileType="Native"Path="runtimes/android-arm64/native/libxa-shared-bits-debug.a"FileVersion="0.0.0.0"Profile="Android" />
<FileType="Native"Path="runtimes/android-arm64/native/libxa-shared-bits-release.a"FileVersion="0.0.0.0"Profile="Android" />
</FileList>

But then I noticed:

image

The arm and x86 packs are smaller, so they are missing the new files.

But we should probably just stop producing the arm and x86 packs completely, and then see if some of the failing tests were targeting x86 or something.

@jonathanpeppers

jonathanpeppers commented Aug 20, 2025

Copy link
Copy Markdown
Member

I tried to push a change (says I can't push to jkoritzinsky/dotnet-android), but I sent a different PR for main:

@jkoritzinsky

Copy link
Copy Markdown
MemberAuthor

You should be able to push to my fork (I have the "allow edits by maintainers" checkbox checked), weird. Thanks for looking into this for me.

@jonathanpeppers

Copy link
Copy Markdown
Member

#10432 is good but may not fully fix this -- basically nothing broke when I removed the x86 and arm packs.

So, I'll try building this locally when I can.

Comment threadbuild-tools/create-packs/Microsoft.Android.Runtime.proj Outdated
@grendello

Copy link
Copy Markdown
Contributor

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

Comment threadsrc/native/native.targets Outdated
@jkoritzinsky
jkoritzinsky marked this pull request as ready for review September 16, 2025 19:17

namespace Microsoft.Android.Runtime;

struct DiagnosticSettings {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

So, I think we'll want to restore the GrefLog and LrefLog logs or we'll have no way to get these in NativeAOT.

Long term, we were going to use some EventSource API, but maybe we can just leave the simple thing in here for now.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

Removing this infra is basically the last part of this PR that wasn't subsumed by the other PR that already went in.

I'll close this PR as there's really nothing in it at this point.

Comment on lines -19 to -23
static LogcatTextWriter ()
{
Console.SetOut (new LogcatTextWriter (AndroidLogLevel.Info));
Console.SetError (new LogcatTextWriter (AndroidLogLevel.Error));
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@jkoritzinsky I think this part is useful, so maybe I can do this part in a different PR.

This was here originally, because Console.WriteLine() didn't output to logcat.

@github-actionsgithub-actionsBot locked and limited conversation to collaborators Oct 17, 2025
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants

@jkoritzinsky@jonathanpeppers@filipnavara@akoeplinger@grendello
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Hook up more integrations to NativeAOT with Android RIDs - #10402

Closed
jkoritzinsky wants to merge 5 commits into
dotnet:mainfrom
jkoritzinsky:naot-android-rid
Closed

Hook up more integrations to NativeAOT with Android RIDs#10402
jkoritzinsky wants to merge 5 commits into
dotnet:mainfrom
jkoritzinsky:naot-android-rid

Conversation

@jkoritzinsky

Copy link
Copy Markdown
Member

Try hooking up the Android crypto stack, GC integration, and logging to NativeAOT correctly.

cc: @filipnavara@jtschuster

@jonathanpeppers

Copy link
Copy Markdown
Member

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

Comment threadsrc/native/clr/host/CMakeLists.txt Outdated
os-bridge.cc
runtime-util.cc
typemap.cc
xamarin_getifaddrs.cc

@filipnavarafilipnavaraAug 12, 2025

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This will produce conflict with #10385. Not a big deal, just wanted to avoid dragging unused code into newly supported runtimes.

@filipnavara

filipnavara commented Aug 12, 2025

Copy link
Copy Markdown
Member

I'll need to dig a bit deeper but the subset linking of the native lib is still not quite correct:

08-12 10:30:01.122 26235 26235 E AndroidRuntime: java.lang.UnsatisfiedLinkError: dlopen failed: cannot locate symbol "_monodroid_detect_cpu_and_architecture" referenced by "/data/app/~~grvY0oxLa6M-yS3DDLG0hg==/com.emclient.mailclient-XUnDyFyf6XZEZfGtl53aBg==/lib/x86_64/libMailClient.Mobile.Android.so"...
08-12 10:30:01.122 26235 26235 E AndroidRuntime: at java.lang.Runtime.loadLibrary0(Runtime.java:1090)
08-12 10:30:01.122 26235 26235 E AndroidRuntime: at java.lang.Runtime.loadLibrary0(Runtime.java:1012)
08-12 10:30:01.122 26235 26235 E AndroidRuntime: at java.lang.System.loadLibrary(System.java:1765)
08-12 10:30:01.122 26235 26235 E AndroidRuntime: at net.dot.jni.nativeaot.JavaInteropRuntime.<clinit>(JavaInteropRuntime.java:8)
08-12 10:30:01.122 26235 26235 E AndroidRuntime: at net.dot.jni.nativeaot.NativeAotRuntimeProvider.attachInfo(NativeAotRuntimeProvider.java:43)
08-12 10:30:01.122 26235 26235 E AndroidRuntime: at android.app.ActivityThread.installProvider(ActivityThread.java:8642)
08-12 10:30:01.122 26235 26235 E AndroidRuntime: at android.app.ActivityThread.installContentProviders(ActivityThread.java:8157)
08-12 10:30:01.122 26235 26235 E AndroidRuntime: at android.app.ActivityThread.handleBindApplication(ActivityThread.java:7814)
08-12 10:30:01.122 26235 26235 E AndroidRuntime: at android.app.ActivityThread.-$$Nest$mhandleBindApplication(Unknown Source:0)
08-12 10:30:01.122 26235 26235 E AndroidRuntime: at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2546)
08-12 10:30:01.122 26235 26235 E AndroidRuntime: at android.os.Handler.dispatchMessage(Handler.java:110)
08-12 10:30:01.122 26235 26235 E AndroidRuntime: at android.os.Looper.loopOnce(Looper.java:248)
08-12 10:30:01.122 26235 26235 E AndroidRuntime: at android.os.Looper.loop(Looper.java:338)
08-12 10:30:01.122 26235 26235 E AndroidRuntime: at android.app.ActivityThread.main(ActivityThread.java:9067)
08-12 10:30:01.122 26235 26235 E AndroidRuntime: at java.lang.reflect.Method.invoke(Native Method)
08-12 10:30:01.122 26235 26235 E AndroidRuntime: at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:593)
08-12 10:30:01.122 26235 26235 E AndroidRuntime: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:932)

...and even if it tried to link to the native library we are still missing some bits:

 ld.lld : error : undefined hidden symbol: xamarin::android::Helpers::abort_application(_LogCategories, char const*, bool, std::__ndk1::source_location)

UPD: Nvm, I was missing xa-shared-bits in the second attempt.

@filipnavara

filipnavara commented Aug 12, 2025

Copy link
Copy Markdown
Member

I have a heavily hacked up build locally that was able to pass startup of our app:

image

Aside from all the comments above and solving general linking breakage / undefined symbols, we will need to embrace GCUserPeerable because NativeAOT builds use different interop generation mode (XAJavaInterop1 vs JavaInterop1).

The garbage collection part seems to work but for some reason it's triggered way too often to the point of feeling like running all the time. It will need to be investigated, the startup takes literally minute[s] because of all the triggered collections. (UPD: Could be It is just uninitialized value for GREF threshold).

@filipnavara

Copy link
Copy Markdown
Member

Here's a rough commit with the changes I have locally to get this working: filipnavara@4a59c50

It still needs a lot of cleanup. We also need updated runtime packs to get it working end-to-end.

@jonathanpeppers

Copy link
Copy Markdown
Member

@jkoritzinsky FYI the latest Maestro bump, it seems like we need to make changes like:

This allows the NativeAOT runtime packs (with proper Android RIDs!) to work.

Do we need to add the two Android RIDs to this line:

That made things work for me locally, but CI is ongoing.

@jonathanpeppers

Copy link
Copy Markdown
Member

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@akoeplinger

Copy link
Copy Markdown
Member

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@jkoritzinsky

Copy link
Copy Markdown
MemberAuthor

I'm looking at the NAOT failures and it looks like it can't find the native files in the package even though they are present in the NativeAOT runtime package.

I did notice that the runtime package is built with a -ci version and the test expects it to have a stable version. Is that expected?

@jonathanpeppers

Copy link
Copy Markdown
Member

Ok, the data/RuntimeList.xml file looks OK:

<FileListTargetFrameworkIdentifier=".NETStandard"TargetFrameworkVersion="2.0"FrameworkName="Microsoft.Android.Runtimes"Name=".NET 10.0 - Microsoft.Android.Runtimes">
<FileType="Managed"Path="runtimes/android-arm64/lib/net10.0/Microsoft.Android.Runtime.NativeAOT.dll"AssemblyName="Microsoft.Android.Runtime.NativeAOT"PublicKeyToken="84e04ff9cfb79065"AssemblyVersion="1.0.0.0"FileVersion="1.0.0.0"Profile="Android" />
<FileType="Native"Path="runtimes/android-arm64/native/libnet-android-nativeaot-debug.a"FileVersion="0.0.0.0"Profile="Android" />
<FileType="Native"Path="runtimes/android-arm64/native/libnet-android-nativeaot-release.a"FileVersion="0.0.0.0"Profile="Android" />
<FileType="Native"Path="runtimes/android-arm64/native/libxa-shared-bits-debug.a"FileVersion="0.0.0.0"Profile="Android" />
<FileType="Native"Path="runtimes/android-arm64/native/libxa-shared-bits-release.a"FileVersion="0.0.0.0"Profile="Android" />
</FileList>

But then I noticed:

image

The arm and x86 packs are smaller, so they are missing the new files.

But we should probably just stop producing the arm and x86 packs completely, and then see if some of the failing tests were targeting x86 or something.

@jonathanpeppers

jonathanpeppers commented Aug 20, 2025

Copy link
Copy Markdown
Member

I tried to push a change (says I can't push to jkoritzinsky/dotnet-android), but I sent a different PR for main:

@jkoritzinsky

Copy link
Copy Markdown
MemberAuthor

You should be able to push to my fork (I have the "allow edits by maintainers" checkbox checked), weird. Thanks for looking into this for me.

@jonathanpeppers

Copy link
Copy Markdown
Member

#10432 is good but may not fully fix this -- basically nothing broke when I removed the x86 and arm packs.

So, I'll try building this locally when I can.

Comment threadbuild-tools/create-packs/Microsoft.Android.Runtime.proj Outdated
@grendello

Copy link
Copy Markdown
Contributor

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

Comment threadsrc/native/native.targets Outdated
@jkoritzinsky
jkoritzinsky marked this pull request as ready for review September 16, 2025 19:17

namespace Microsoft.Android.Runtime;

struct DiagnosticSettings {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

So, I think we'll want to restore the GrefLog and LrefLog logs or we'll have no way to get these in NativeAOT.

Long term, we were going to use some EventSource API, but maybe we can just leave the simple thing in here for now.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

Removing this infra is basically the last part of this PR that wasn't subsumed by the other PR that already went in.

I'll close this PR as there's really nothing in it at this point.

Comment on lines -19 to -23
static LogcatTextWriter ()
{
Console.SetOut (new LogcatTextWriter (AndroidLogLevel.Info));
Console.SetError (new LogcatTextWriter (AndroidLogLevel.Error));
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@jkoritzinsky I think this part is useful, so maybe I can do this part in a different PR.

This was here originally, because Console.WriteLine() didn't output to logcat.

@github-actionsgithub-actionsBot locked and limited conversation to collaborators Oct 17, 2025
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants

@jkoritzinsky@jonathanpeppers@filipnavara@akoeplinger@grendello
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Hook up more integrations to NativeAOT with Android RIDs - #10402

Closed
jkoritzinsky wants to merge 5 commits into
dotnet:mainfrom
jkoritzinsky:naot-android-rid
Closed

Hook up more integrations to NativeAOT with Android RIDs#10402
jkoritzinsky wants to merge 5 commits into
dotnet:mainfrom
jkoritzinsky:naot-android-rid

Conversation

@jkoritzinsky

Copy link
Copy Markdown
Member

Try hooking up the Android crypto stack, GC integration, and logging to NativeAOT correctly.

cc: @filipnavara@jtschuster

@jonathanpeppers

Copy link
Copy Markdown
Member

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

Comment threadsrc/native/clr/host/CMakeLists.txt Outdated
os-bridge.cc
runtime-util.cc
typemap.cc
xamarin_getifaddrs.cc

@filipnavarafilipnavaraAug 12, 2025

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This will produce conflict with #10385. Not a big deal, just wanted to avoid dragging unused code into newly supported runtimes.

@filipnavara

filipnavara commented Aug 12, 2025

Copy link
Copy Markdown
Member

I'll need to dig a bit deeper but the subset linking of the native lib is still not quite correct:

08-12 10:30:01.122 26235 26235 E AndroidRuntime: java.lang.UnsatisfiedLinkError: dlopen failed: cannot locate symbol "_monodroid_detect_cpu_and_architecture" referenced by "/data/app/~~grvY0oxLa6M-yS3DDLG0hg==/com.emclient.mailclient-XUnDyFyf6XZEZfGtl53aBg==/lib/x86_64/libMailClient.Mobile.Android.so"...
08-12 10:30:01.122 26235 26235 E AndroidRuntime: at java.lang.Runtime.loadLibrary0(Runtime.java:1090)
08-12 10:30:01.122 26235 26235 E AndroidRuntime: at java.lang.Runtime.loadLibrary0(Runtime.java:1012)
08-12 10:30:01.122 26235 26235 E AndroidRuntime: at java.lang.System.loadLibrary(System.java:1765)
08-12 10:30:01.122 26235 26235 E AndroidRuntime: at net.dot.jni.nativeaot.JavaInteropRuntime.<clinit>(JavaInteropRuntime.java:8)
08-12 10:30:01.122 26235 26235 E AndroidRuntime: at net.dot.jni.nativeaot.NativeAotRuntimeProvider.attachInfo(NativeAotRuntimeProvider.java:43)
08-12 10:30:01.122 26235 26235 E AndroidRuntime: at android.app.ActivityThread.installProvider(ActivityThread.java:8642)
08-12 10:30:01.122 26235 26235 E AndroidRuntime: at android.app.ActivityThread.installContentProviders(ActivityThread.java:8157)
08-12 10:30:01.122 26235 26235 E AndroidRuntime: at android.app.ActivityThread.handleBindApplication(ActivityThread.java:7814)
08-12 10:30:01.122 26235 26235 E AndroidRuntime: at android.app.ActivityThread.-$$Nest$mhandleBindApplication(Unknown Source:0)
08-12 10:30:01.122 26235 26235 E AndroidRuntime: at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2546)
08-12 10:30:01.122 26235 26235 E AndroidRuntime: at android.os.Handler.dispatchMessage(Handler.java:110)
08-12 10:30:01.122 26235 26235 E AndroidRuntime: at android.os.Looper.loopOnce(Looper.java:248)
08-12 10:30:01.122 26235 26235 E AndroidRuntime: at android.os.Looper.loop(Looper.java:338)
08-12 10:30:01.122 26235 26235 E AndroidRuntime: at android.app.ActivityThread.main(ActivityThread.java:9067)
08-12 10:30:01.122 26235 26235 E AndroidRuntime: at java.lang.reflect.Method.invoke(Native Method)
08-12 10:30:01.122 26235 26235 E AndroidRuntime: at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:593)
08-12 10:30:01.122 26235 26235 E AndroidRuntime: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:932)

...and even if it tried to link to the native library we are still missing some bits:

 ld.lld : error : undefined hidden symbol: xamarin::android::Helpers::abort_application(_LogCategories, char const*, bool, std::__ndk1::source_location)

UPD: Nvm, I was missing xa-shared-bits in the second attempt.

@filipnavara

filipnavara commented Aug 12, 2025

Copy link
Copy Markdown
Member

I have a heavily hacked up build locally that was able to pass startup of our app:

image

Aside from all the comments above and solving general linking breakage / undefined symbols, we will need to embrace GCUserPeerable because NativeAOT builds use different interop generation mode (XAJavaInterop1 vs JavaInterop1).

The garbage collection part seems to work but for some reason it's triggered way too often to the point of feeling like running all the time. It will need to be investigated, the startup takes literally minute[s] because of all the triggered collections. (UPD: Could be It is just uninitialized value for GREF threshold).

@filipnavara

Copy link
Copy Markdown
Member

Here's a rough commit with the changes I have locally to get this working: filipnavara@4a59c50

It still needs a lot of cleanup. We also need updated runtime packs to get it working end-to-end.

@jonathanpeppers

Copy link
Copy Markdown
Member

@jkoritzinsky FYI the latest Maestro bump, it seems like we need to make changes like:

This allows the NativeAOT runtime packs (with proper Android RIDs!) to work.

Do we need to add the two Android RIDs to this line:

That made things work for me locally, but CI is ongoing.

@jonathanpeppers

Copy link
Copy Markdown
Member

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@akoeplinger

Copy link
Copy Markdown
Member

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@jkoritzinsky

Copy link
Copy Markdown
MemberAuthor

I'm looking at the NAOT failures and it looks like it can't find the native files in the package even though they are present in the NativeAOT runtime package.

I did notice that the runtime package is built with a -ci version and the test expects it to have a stable version. Is that expected?

@jonathanpeppers

Copy link
Copy Markdown
Member

Ok, the data/RuntimeList.xml file looks OK:

<FileListTargetFrameworkIdentifier=".NETStandard"TargetFrameworkVersion="2.0"FrameworkName="Microsoft.Android.Runtimes"Name=".NET 10.0 - Microsoft.Android.Runtimes">
<FileType="Managed"Path="runtimes/android-arm64/lib/net10.0/Microsoft.Android.Runtime.NativeAOT.dll"AssemblyName="Microsoft.Android.Runtime.NativeAOT"PublicKeyToken="84e04ff9cfb79065"AssemblyVersion="1.0.0.0"FileVersion="1.0.0.0"Profile="Android" />
<FileType="Native"Path="runtimes/android-arm64/native/libnet-android-nativeaot-debug.a"FileVersion="0.0.0.0"Profile="Android" />
<FileType="Native"Path="runtimes/android-arm64/native/libnet-android-nativeaot-release.a"FileVersion="0.0.0.0"Profile="Android" />
<FileType="Native"Path="runtimes/android-arm64/native/libxa-shared-bits-debug.a"FileVersion="0.0.0.0"Profile="Android" />
<FileType="Native"Path="runtimes/android-arm64/native/libxa-shared-bits-release.a"FileVersion="0.0.0.0"Profile="Android" />
</FileList>

But then I noticed:

image

The arm and x86 packs are smaller, so they are missing the new files.

But we should probably just stop producing the arm and x86 packs completely, and then see if some of the failing tests were targeting x86 or something.

@jonathanpeppers

jonathanpeppers commented Aug 20, 2025

Copy link
Copy Markdown
Member

I tried to push a change (says I can't push to jkoritzinsky/dotnet-android), but I sent a different PR for main:

@jkoritzinsky

Copy link
Copy Markdown
MemberAuthor

You should be able to push to my fork (I have the "allow edits by maintainers" checkbox checked), weird. Thanks for looking into this for me.

@jonathanpeppers

Copy link
Copy Markdown
Member

#10432 is good but may not fully fix this -- basically nothing broke when I removed the x86 and arm packs.

So, I'll try building this locally when I can.

Comment threadbuild-tools/create-packs/Microsoft.Android.Runtime.proj Outdated
@grendello

Copy link
Copy Markdown
Contributor

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

Comment threadsrc/native/native.targets Outdated
@jkoritzinsky
jkoritzinsky marked this pull request as ready for review September 16, 2025 19:17

namespace Microsoft.Android.Runtime;

struct DiagnosticSettings {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

So, I think we'll want to restore the GrefLog and LrefLog logs or we'll have no way to get these in NativeAOT.

Long term, we were going to use some EventSource API, but maybe we can just leave the simple thing in here for now.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

Removing this infra is basically the last part of this PR that wasn't subsumed by the other PR that already went in.

I'll close this PR as there's really nothing in it at this point.

Comment on lines -19 to -23
static LogcatTextWriter ()
{
Console.SetOut (new LogcatTextWriter (AndroidLogLevel.Info));
Console.SetError (new LogcatTextWriter (AndroidLogLevel.Error));
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@jkoritzinsky I think this part is useful, so maybe I can do this part in a different PR.

This was here originally, because Console.WriteLine() didn't output to logcat.

@github-actionsgithub-actionsBot locked and limited conversation to collaborators Oct 17, 2025
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants

@jkoritzinsky@jonathanpeppers@filipnavara@akoeplinger@grendello
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Hook up more integrations to NativeAOT with Android RIDs - #10402

Closed
jkoritzinsky wants to merge 5 commits into
dotnet:mainfrom
jkoritzinsky:naot-android-rid
Closed

Hook up more integrations to NativeAOT with Android RIDs#10402
jkoritzinsky wants to merge 5 commits into
dotnet:mainfrom
jkoritzinsky:naot-android-rid

Conversation

@jkoritzinsky

Copy link
Copy Markdown
Member

Try hooking up the Android crypto stack, GC integration, and logging to NativeAOT correctly.

cc: @filipnavara@jtschuster

@jonathanpeppers

Copy link
Copy Markdown
Member

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

Comment threadsrc/native/clr/host/CMakeLists.txt Outdated
os-bridge.cc
runtime-util.cc
typemap.cc
xamarin_getifaddrs.cc

@filipnavarafilipnavaraAug 12, 2025

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This will produce conflict with #10385. Not a big deal, just wanted to avoid dragging unused code into newly supported runtimes.

@filipnavara

filipnavara commented Aug 12, 2025

Copy link
Copy Markdown
Member

I'll need to dig a bit deeper but the subset linking of the native lib is still not quite correct:

08-12 10:30:01.122 26235 26235 E AndroidRuntime: java.lang.UnsatisfiedLinkError: dlopen failed: cannot locate symbol "_monodroid_detect_cpu_and_architecture" referenced by "/data/app/~~grvY0oxLa6M-yS3DDLG0hg==/com.emclient.mailclient-XUnDyFyf6XZEZfGtl53aBg==/lib/x86_64/libMailClient.Mobile.Android.so"...
08-12 10:30:01.122 26235 26235 E AndroidRuntime: at java.lang.Runtime.loadLibrary0(Runtime.java:1090)
08-12 10:30:01.122 26235 26235 E AndroidRuntime: at java.lang.Runtime.loadLibrary0(Runtime.java:1012)
08-12 10:30:01.122 26235 26235 E AndroidRuntime: at java.lang.System.loadLibrary(System.java:1765)
08-12 10:30:01.122 26235 26235 E AndroidRuntime: at net.dot.jni.nativeaot.JavaInteropRuntime.<clinit>(JavaInteropRuntime.java:8)
08-12 10:30:01.122 26235 26235 E AndroidRuntime: at net.dot.jni.nativeaot.NativeAotRuntimeProvider.attachInfo(NativeAotRuntimeProvider.java:43)
08-12 10:30:01.122 26235 26235 E AndroidRuntime: at android.app.ActivityThread.installProvider(ActivityThread.java:8642)
08-12 10:30:01.122 26235 26235 E AndroidRuntime: at android.app.ActivityThread.installContentProviders(ActivityThread.java:8157)
08-12 10:30:01.122 26235 26235 E AndroidRuntime: at android.app.ActivityThread.handleBindApplication(ActivityThread.java:7814)
08-12 10:30:01.122 26235 26235 E AndroidRuntime: at android.app.ActivityThread.-$$Nest$mhandleBindApplication(Unknown Source:0)
08-12 10:30:01.122 26235 26235 E AndroidRuntime: at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2546)
08-12 10:30:01.122 26235 26235 E AndroidRuntime: at android.os.Handler.dispatchMessage(Handler.java:110)
08-12 10:30:01.122 26235 26235 E AndroidRuntime: at android.os.Looper.loopOnce(Looper.java:248)
08-12 10:30:01.122 26235 26235 E AndroidRuntime: at android.os.Looper.loop(Looper.java:338)
08-12 10:30:01.122 26235 26235 E AndroidRuntime: at android.app.ActivityThread.main(ActivityThread.java:9067)
08-12 10:30:01.122 26235 26235 E AndroidRuntime: at java.lang.reflect.Method.invoke(Native Method)
08-12 10:30:01.122 26235 26235 E AndroidRuntime: at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:593)
08-12 10:30:01.122 26235 26235 E AndroidRuntime: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:932)

...and even if it tried to link to the native library we are still missing some bits:

 ld.lld : error : undefined hidden symbol: xamarin::android::Helpers::abort_application(_LogCategories, char const*, bool, std::__ndk1::source_location)

UPD: Nvm, I was missing xa-shared-bits in the second attempt.

@filipnavara

filipnavara commented Aug 12, 2025

Copy link
Copy Markdown
Member

I have a heavily hacked up build locally that was able to pass startup of our app:

image

Aside from all the comments above and solving general linking breakage / undefined symbols, we will need to embrace GCUserPeerable because NativeAOT builds use different interop generation mode (XAJavaInterop1 vs JavaInterop1).

The garbage collection part seems to work but for some reason it's triggered way too often to the point of feeling like running all the time. It will need to be investigated, the startup takes literally minute[s] because of all the triggered collections. (UPD: Could be It is just uninitialized value for GREF threshold).

@filipnavara

Copy link
Copy Markdown
Member

Here's a rough commit with the changes I have locally to get this working: filipnavara@4a59c50

It still needs a lot of cleanup. We also need updated runtime packs to get it working end-to-end.

@jonathanpeppers

Copy link
Copy Markdown
Member

@jkoritzinsky FYI the latest Maestro bump, it seems like we need to make changes like:

This allows the NativeAOT runtime packs (with proper Android RIDs!) to work.

Do we need to add the two Android RIDs to this line:

That made things work for me locally, but CI is ongoing.

@jonathanpeppers

Copy link
Copy Markdown
Member

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@akoeplinger

Copy link
Copy Markdown
Member

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@jkoritzinsky

Copy link
Copy Markdown
MemberAuthor

I'm looking at the NAOT failures and it looks like it can't find the native files in the package even though they are present in the NativeAOT runtime package.

I did notice that the runtime package is built with a -ci version and the test expects it to have a stable version. Is that expected?

@jonathanpeppers

Copy link
Copy Markdown
Member

Ok, the data/RuntimeList.xml file looks OK:

<FileListTargetFrameworkIdentifier=".NETStandard"TargetFrameworkVersion="2.0"FrameworkName="Microsoft.Android.Runtimes"Name=".NET 10.0 - Microsoft.Android.Runtimes">
<FileType="Managed"Path="runtimes/android-arm64/lib/net10.0/Microsoft.Android.Runtime.NativeAOT.dll"AssemblyName="Microsoft.Android.Runtime.NativeAOT"PublicKeyToken="84e04ff9cfb79065"AssemblyVersion="1.0.0.0"FileVersion="1.0.0.0"Profile="Android" />
<FileType="Native"Path="runtimes/android-arm64/native/libnet-android-nativeaot-debug.a"FileVersion="0.0.0.0"Profile="Android" />
<FileType="Native"Path="runtimes/android-arm64/native/libnet-android-nativeaot-release.a"FileVersion="0.0.0.0"Profile="Android" />
<FileType="Native"Path="runtimes/android-arm64/native/libxa-shared-bits-debug.a"FileVersion="0.0.0.0"Profile="Android" />
<FileType="Native"Path="runtimes/android-arm64/native/libxa-shared-bits-release.a"FileVersion="0.0.0.0"Profile="Android" />
</FileList>

But then I noticed:

image

The arm and x86 packs are smaller, so they are missing the new files.

But we should probably just stop producing the arm and x86 packs completely, and then see if some of the failing tests were targeting x86 or something.

@jonathanpeppers

jonathanpeppers commented Aug 20, 2025

Copy link
Copy Markdown
Member

I tried to push a change (says I can't push to jkoritzinsky/dotnet-android), but I sent a different PR for main:

@jkoritzinsky

Copy link
Copy Markdown
MemberAuthor

You should be able to push to my fork (I have the "allow edits by maintainers" checkbox checked), weird. Thanks for looking into this for me.

@jonathanpeppers

Copy link
Copy Markdown
Member

#10432 is good but may not fully fix this -- basically nothing broke when I removed the x86 and arm packs.

So, I'll try building this locally when I can.

Comment threadbuild-tools/create-packs/Microsoft.Android.Runtime.proj Outdated
@grendello

Copy link
Copy Markdown
Contributor

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

Comment threadsrc/native/native.targets Outdated
@jkoritzinsky
jkoritzinsky marked this pull request as ready for review September 16, 2025 19:17

namespace Microsoft.Android.Runtime;

struct DiagnosticSettings {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

So, I think we'll want to restore the GrefLog and LrefLog logs or we'll have no way to get these in NativeAOT.

Long term, we were going to use some EventSource API, but maybe we can just leave the simple thing in here for now.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

Removing this infra is basically the last part of this PR that wasn't subsumed by the other PR that already went in.

I'll close this PR as there's really nothing in it at this point.

Comment on lines -19 to -23
static LogcatTextWriter ()
{
Console.SetOut (new LogcatTextWriter (AndroidLogLevel.Info));
Console.SetError (new LogcatTextWriter (AndroidLogLevel.Error));
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@jkoritzinsky I think this part is useful, so maybe I can do this part in a different PR.

This was here originally, because Console.WriteLine() didn't output to logcat.

@github-actionsgithub-actionsBot locked and limited conversation to collaborators Oct 17, 2025
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants

@jkoritzinsky@jonathanpeppers@filipnavara@akoeplinger@grendello
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Hook up more integrations to NativeAOT with Android RIDs - #10402

Closed
jkoritzinsky wants to merge 5 commits into
dotnet:mainfrom
jkoritzinsky:naot-android-rid
Closed

Hook up more integrations to NativeAOT with Android RIDs#10402
jkoritzinsky wants to merge 5 commits into
dotnet:mainfrom
jkoritzinsky:naot-android-rid

Conversation

@jkoritzinsky

Copy link
Copy Markdown
Member

Try hooking up the Android crypto stack, GC integration, and logging to NativeAOT correctly.

cc: @filipnavara@jtschuster

@jonathanpeppers

Copy link
Copy Markdown
Member

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

Comment threadsrc/native/clr/host/CMakeLists.txt Outdated
os-bridge.cc
runtime-util.cc
typemap.cc
xamarin_getifaddrs.cc

@filipnavarafilipnavaraAug 12, 2025

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This will produce conflict with #10385. Not a big deal, just wanted to avoid dragging unused code into newly supported runtimes.

@filipnavara

filipnavara commented Aug 12, 2025

Copy link
Copy Markdown
Member

I'll need to dig a bit deeper but the subset linking of the native lib is still not quite correct:

08-12 10:30:01.122 26235 26235 E AndroidRuntime: java.lang.UnsatisfiedLinkError: dlopen failed: cannot locate symbol "_monodroid_detect_cpu_and_architecture" referenced by "/data/app/~~grvY0oxLa6M-yS3DDLG0hg==/com.emclient.mailclient-XUnDyFyf6XZEZfGtl53aBg==/lib/x86_64/libMailClient.Mobile.Android.so"...
08-12 10:30:01.122 26235 26235 E AndroidRuntime: at java.lang.Runtime.loadLibrary0(Runtime.java:1090)
08-12 10:30:01.122 26235 26235 E AndroidRuntime: at java.lang.Runtime.loadLibrary0(Runtime.java:1012)
08-12 10:30:01.122 26235 26235 E AndroidRuntime: at java.lang.System.loadLibrary(System.java:1765)
08-12 10:30:01.122 26235 26235 E AndroidRuntime: at net.dot.jni.nativeaot.JavaInteropRuntime.<clinit>(JavaInteropRuntime.java:8)
08-12 10:30:01.122 26235 26235 E AndroidRuntime: at net.dot.jni.nativeaot.NativeAotRuntimeProvider.attachInfo(NativeAotRuntimeProvider.java:43)
08-12 10:30:01.122 26235 26235 E AndroidRuntime: at android.app.ActivityThread.installProvider(ActivityThread.java:8642)
08-12 10:30:01.122 26235 26235 E AndroidRuntime: at android.app.ActivityThread.installContentProviders(ActivityThread.java:8157)
08-12 10:30:01.122 26235 26235 E AndroidRuntime: at android.app.ActivityThread.handleBindApplication(ActivityThread.java:7814)
08-12 10:30:01.122 26235 26235 E AndroidRuntime: at android.app.ActivityThread.-$$Nest$mhandleBindApplication(Unknown Source:0)
08-12 10:30:01.122 26235 26235 E AndroidRuntime: at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2546)
08-12 10:30:01.122 26235 26235 E AndroidRuntime: at android.os.Handler.dispatchMessage(Handler.java:110)
08-12 10:30:01.122 26235 26235 E AndroidRuntime: at android.os.Looper.loopOnce(Looper.java:248)
08-12 10:30:01.122 26235 26235 E AndroidRuntime: at android.os.Looper.loop(Looper.java:338)
08-12 10:30:01.122 26235 26235 E AndroidRuntime: at android.app.ActivityThread.main(ActivityThread.java:9067)
08-12 10:30:01.122 26235 26235 E AndroidRuntime: at java.lang.reflect.Method.invoke(Native Method)
08-12 10:30:01.122 26235 26235 E AndroidRuntime: at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:593)
08-12 10:30:01.122 26235 26235 E AndroidRuntime: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:932)

...and even if it tried to link to the native library we are still missing some bits:

 ld.lld : error : undefined hidden symbol: xamarin::android::Helpers::abort_application(_LogCategories, char const*, bool, std::__ndk1::source_location)

UPD: Nvm, I was missing xa-shared-bits in the second attempt.

@filipnavara

filipnavara commented Aug 12, 2025

Copy link
Copy Markdown
Member

I have a heavily hacked up build locally that was able to pass startup of our app:

image

Aside from all the comments above and solving general linking breakage / undefined symbols, we will need to embrace GCUserPeerable because NativeAOT builds use different interop generation mode (XAJavaInterop1 vs JavaInterop1).

The garbage collection part seems to work but for some reason it's triggered way too often to the point of feeling like running all the time. It will need to be investigated, the startup takes literally minute[s] because of all the triggered collections. (UPD: Could be It is just uninitialized value for GREF threshold).

@filipnavara

Copy link
Copy Markdown
Member

Here's a rough commit with the changes I have locally to get this working: filipnavara@4a59c50

It still needs a lot of cleanup. We also need updated runtime packs to get it working end-to-end.

@jonathanpeppers

Copy link
Copy Markdown
Member

@jkoritzinsky FYI the latest Maestro bump, it seems like we need to make changes like:

This allows the NativeAOT runtime packs (with proper Android RIDs!) to work.

Do we need to add the two Android RIDs to this line:

That made things work for me locally, but CI is ongoing.

@jonathanpeppers

Copy link
Copy Markdown
Member

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@akoeplinger

Copy link
Copy Markdown
Member

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@jkoritzinsky

Copy link
Copy Markdown
MemberAuthor

I'm looking at the NAOT failures and it looks like it can't find the native files in the package even though they are present in the NativeAOT runtime package.

I did notice that the runtime package is built with a -ci version and the test expects it to have a stable version. Is that expected?

@jonathanpeppers

Copy link
Copy Markdown
Member

Ok, the data/RuntimeList.xml file looks OK:

<FileListTargetFrameworkIdentifier=".NETStandard"TargetFrameworkVersion="2.0"FrameworkName="Microsoft.Android.Runtimes"Name=".NET 10.0 - Microsoft.Android.Runtimes">
<FileType="Managed"Path="runtimes/android-arm64/lib/net10.0/Microsoft.Android.Runtime.NativeAOT.dll"AssemblyName="Microsoft.Android.Runtime.NativeAOT"PublicKeyToken="84e04ff9cfb79065"AssemblyVersion="1.0.0.0"FileVersion="1.0.0.0"Profile="Android" />
<FileType="Native"Path="runtimes/android-arm64/native/libnet-android-nativeaot-debug.a"FileVersion="0.0.0.0"Profile="Android" />
<FileType="Native"Path="runtimes/android-arm64/native/libnet-android-nativeaot-release.a"FileVersion="0.0.0.0"Profile="Android" />
<FileType="Native"Path="runtimes/android-arm64/native/libxa-shared-bits-debug.a"FileVersion="0.0.0.0"Profile="Android" />
<FileType="Native"Path="runtimes/android-arm64/native/libxa-shared-bits-release.a"FileVersion="0.0.0.0"Profile="Android" />
</FileList>

But then I noticed:

image

The arm and x86 packs are smaller, so they are missing the new files.

But we should probably just stop producing the arm and x86 packs completely, and then see if some of the failing tests were targeting x86 or something.

@jonathanpeppers

jonathanpeppers commented Aug 20, 2025

Copy link
Copy Markdown
Member

I tried to push a change (says I can't push to jkoritzinsky/dotnet-android), but I sent a different PR for main:

@jkoritzinsky

Copy link
Copy Markdown
MemberAuthor

You should be able to push to my fork (I have the "allow edits by maintainers" checkbox checked), weird. Thanks for looking into this for me.

@jonathanpeppers

Copy link
Copy Markdown
Member

#10432 is good but may not fully fix this -- basically nothing broke when I removed the x86 and arm packs.

So, I'll try building this locally when I can.

Comment threadbuild-tools/create-packs/Microsoft.Android.Runtime.proj Outdated
@grendello

Copy link
Copy Markdown
Contributor

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

Comment threadsrc/native/native.targets Outdated
@jkoritzinsky
jkoritzinsky marked this pull request as ready for review September 16, 2025 19:17

namespace Microsoft.Android.Runtime;

struct DiagnosticSettings {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

So, I think we'll want to restore the GrefLog and LrefLog logs or we'll have no way to get these in NativeAOT.

Long term, we were going to use some EventSource API, but maybe we can just leave the simple thing in here for now.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

Removing this infra is basically the last part of this PR that wasn't subsumed by the other PR that already went in.

I'll close this PR as there's really nothing in it at this point.

Comment on lines -19 to -23
static LogcatTextWriter ()
{
Console.SetOut (new LogcatTextWriter (AndroidLogLevel.Info));
Console.SetError (new LogcatTextWriter (AndroidLogLevel.Error));
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@jkoritzinsky I think this part is useful, so maybe I can do this part in a different PR.

This was here originally, because Console.WriteLine() didn't output to logcat.

@github-actionsgithub-actionsBot locked and limited conversation to collaborators Oct 17, 2025
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants

@jkoritzinsky@jonathanpeppers@filipnavara@akoeplinger@grendello
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Hook up more integrations to NativeAOT with Android RIDs - #10402

Closed
jkoritzinsky wants to merge 5 commits into
dotnet:mainfrom
jkoritzinsky:naot-android-rid
Closed

Hook up more integrations to NativeAOT with Android RIDs#10402
jkoritzinsky wants to merge 5 commits into
dotnet:mainfrom
jkoritzinsky:naot-android-rid

Conversation

@jkoritzinsky

Copy link
Copy Markdown
Member

Try hooking up the Android crypto stack, GC integration, and logging to NativeAOT correctly.

cc: @filipnavara@jtschuster

@jonathanpeppers

Copy link
Copy Markdown
Member

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

Comment threadsrc/native/clr/host/CMakeLists.txt Outdated
os-bridge.cc
runtime-util.cc
typemap.cc
xamarin_getifaddrs.cc

@filipnavarafilipnavaraAug 12, 2025

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This will produce conflict with #10385. Not a big deal, just wanted to avoid dragging unused code into newly supported runtimes.

@filipnavara

filipnavara commented Aug 12, 2025

Copy link
Copy Markdown
Member

I'll need to dig a bit deeper but the subset linking of the native lib is still not quite correct:

08-12 10:30:01.122 26235 26235 E AndroidRuntime: java.lang.UnsatisfiedLinkError: dlopen failed: cannot locate symbol "_monodroid_detect_cpu_and_architecture" referenced by "/data/app/~~grvY0oxLa6M-yS3DDLG0hg==/com.emclient.mailclient-XUnDyFyf6XZEZfGtl53aBg==/lib/x86_64/libMailClient.Mobile.Android.so"...
08-12 10:30:01.122 26235 26235 E AndroidRuntime: at java.lang.Runtime.loadLibrary0(Runtime.java:1090)
08-12 10:30:01.122 26235 26235 E AndroidRuntime: at java.lang.Runtime.loadLibrary0(Runtime.java:1012)
08-12 10:30:01.122 26235 26235 E AndroidRuntime: at java.lang.System.loadLibrary(System.java:1765)
08-12 10:30:01.122 26235 26235 E AndroidRuntime: at net.dot.jni.nativeaot.JavaInteropRuntime.<clinit>(JavaInteropRuntime.java:8)
08-12 10:30:01.122 26235 26235 E AndroidRuntime: at net.dot.jni.nativeaot.NativeAotRuntimeProvider.attachInfo(NativeAotRuntimeProvider.java:43)
08-12 10:30:01.122 26235 26235 E AndroidRuntime: at android.app.ActivityThread.installProvider(ActivityThread.java:8642)
08-12 10:30:01.122 26235 26235 E AndroidRuntime: at android.app.ActivityThread.installContentProviders(ActivityThread.java:8157)
08-12 10:30:01.122 26235 26235 E AndroidRuntime: at android.app.ActivityThread.handleBindApplication(ActivityThread.java:7814)
08-12 10:30:01.122 26235 26235 E AndroidRuntime: at android.app.ActivityThread.-$$Nest$mhandleBindApplication(Unknown Source:0)
08-12 10:30:01.122 26235 26235 E AndroidRuntime: at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2546)
08-12 10:30:01.122 26235 26235 E AndroidRuntime: at android.os.Handler.dispatchMessage(Handler.java:110)
08-12 10:30:01.122 26235 26235 E AndroidRuntime: at android.os.Looper.loopOnce(Looper.java:248)
08-12 10:30:01.122 26235 26235 E AndroidRuntime: at android.os.Looper.loop(Looper.java:338)
08-12 10:30:01.122 26235 26235 E AndroidRuntime: at android.app.ActivityThread.main(ActivityThread.java:9067)
08-12 10:30:01.122 26235 26235 E AndroidRuntime: at java.lang.reflect.Method.invoke(Native Method)
08-12 10:30:01.122 26235 26235 E AndroidRuntime: at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:593)
08-12 10:30:01.122 26235 26235 E AndroidRuntime: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:932)

...and even if it tried to link to the native library we are still missing some bits:

 ld.lld : error : undefined hidden symbol: xamarin::android::Helpers::abort_application(_LogCategories, char const*, bool, std::__ndk1::source_location)

UPD: Nvm, I was missing xa-shared-bits in the second attempt.

@filipnavara

filipnavara commented Aug 12, 2025

Copy link
Copy Markdown
Member

I have a heavily hacked up build locally that was able to pass startup of our app:

image

Aside from all the comments above and solving general linking breakage / undefined symbols, we will need to embrace GCUserPeerable because NativeAOT builds use different interop generation mode (XAJavaInterop1 vs JavaInterop1).

The garbage collection part seems to work but for some reason it's triggered way too often to the point of feeling like running all the time. It will need to be investigated, the startup takes literally minute[s] because of all the triggered collections. (UPD: Could be It is just uninitialized value for GREF threshold).

@filipnavara

Copy link
Copy Markdown
Member

Here's a rough commit with the changes I have locally to get this working: filipnavara@4a59c50

It still needs a lot of cleanup. We also need updated runtime packs to get it working end-to-end.

@jonathanpeppers

Copy link
Copy Markdown
Member

@jkoritzinsky FYI the latest Maestro bump, it seems like we need to make changes like:

This allows the NativeAOT runtime packs (with proper Android RIDs!) to work.

Do we need to add the two Android RIDs to this line:

That made things work for me locally, but CI is ongoing.

@jonathanpeppers

Copy link
Copy Markdown
Member

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@akoeplinger

Copy link
Copy Markdown
Member

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@jkoritzinsky

Copy link
Copy Markdown
MemberAuthor

I'm looking at the NAOT failures and it looks like it can't find the native files in the package even though they are present in the NativeAOT runtime package.

I did notice that the runtime package is built with a -ci version and the test expects it to have a stable version. Is that expected?

@jonathanpeppers

Copy link
Copy Markdown
Member

Ok, the data/RuntimeList.xml file looks OK:

<FileListTargetFrameworkIdentifier=".NETStandard"TargetFrameworkVersion="2.0"FrameworkName="Microsoft.Android.Runtimes"Name=".NET 10.0 - Microsoft.Android.Runtimes">
<FileType="Managed"Path="runtimes/android-arm64/lib/net10.0/Microsoft.Android.Runtime.NativeAOT.dll"AssemblyName="Microsoft.Android.Runtime.NativeAOT"PublicKeyToken="84e04ff9cfb79065"AssemblyVersion="1.0.0.0"FileVersion="1.0.0.0"Profile="Android" />
<FileType="Native"Path="runtimes/android-arm64/native/libnet-android-nativeaot-debug.a"FileVersion="0.0.0.0"Profile="Android" />
<FileType="Native"Path="runtimes/android-arm64/native/libnet-android-nativeaot-release.a"FileVersion="0.0.0.0"Profile="Android" />
<FileType="Native"Path="runtimes/android-arm64/native/libxa-shared-bits-debug.a"FileVersion="0.0.0.0"Profile="Android" />
<FileType="Native"Path="runtimes/android-arm64/native/libxa-shared-bits-release.a"FileVersion="0.0.0.0"Profile="Android" />
</FileList>

But then I noticed:

image

The arm and x86 packs are smaller, so they are missing the new files.

But we should probably just stop producing the arm and x86 packs completely, and then see if some of the failing tests were targeting x86 or something.

@jonathanpeppers

jonathanpeppers commented Aug 20, 2025

Copy link
Copy Markdown
Member

I tried to push a change (says I can't push to jkoritzinsky/dotnet-android), but I sent a different PR for main:

@jkoritzinsky

Copy link
Copy Markdown
MemberAuthor

You should be able to push to my fork (I have the "allow edits by maintainers" checkbox checked), weird. Thanks for looking into this for me.

@jonathanpeppers

Copy link
Copy Markdown
Member

#10432 is good but may not fully fix this -- basically nothing broke when I removed the x86 and arm packs.

So, I'll try building this locally when I can.

Comment threadbuild-tools/create-packs/Microsoft.Android.Runtime.proj Outdated
@grendello

Copy link
Copy Markdown
Contributor

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

Comment threadsrc/native/native.targets Outdated
@jkoritzinsky
jkoritzinsky marked this pull request as ready for review September 16, 2025 19:17

namespace Microsoft.Android.Runtime;

struct DiagnosticSettings {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

So, I think we'll want to restore the GrefLog and LrefLog logs or we'll have no way to get these in NativeAOT.

Long term, we were going to use some EventSource API, but maybe we can just leave the simple thing in here for now.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

Removing this infra is basically the last part of this PR that wasn't subsumed by the other PR that already went in.

I'll close this PR as there's really nothing in it at this point.

Comment on lines -19 to -23
static LogcatTextWriter ()
{
Console.SetOut (new LogcatTextWriter (AndroidLogLevel.Info));
Console.SetError (new LogcatTextWriter (AndroidLogLevel.Error));
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@jkoritzinsky I think this part is useful, so maybe I can do this part in a different PR.

This was here originally, because Console.WriteLine() didn't output to logcat.

@github-actionsgithub-actionsBot locked and limited conversation to collaborators Oct 17, 2025
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants

@jkoritzinsky@jonathanpeppers@filipnavara@akoeplinger@grendello