-
Notifications
You must be signed in to change notification settings - Fork 538
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'main' into dev/grendel/clr-host
* main: [NativeAOT] add sample that runs successfully (#9636)
- Loading branch information
Showing
34 changed files
with
521 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
<?xml version="1.0" encoding="utf-8"?> | ||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"> | ||
<application android:allowBackup="true" android:icon="@mipmap/appicon" android:label="@string/app_name" android:roundIcon="@mipmap/appicon_round" android:supportsRtl="true"> | ||
<!-- Temporary, to eventually be included in .NET Android infrastructure --> | ||
<provider | ||
android:name="net.dot.jni.nativeaot.NativeAotRuntimeProvider" | ||
android:exported="false" | ||
android:initOrder="1999999999" | ||
android:authorities="net.dot.jni.nativeaot.NativeAotRuntimeProvider.__init__" | ||
/> | ||
</application> | ||
<uses-permission android:name="android.permission.INTERNET" /> | ||
</manifest> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
using Android.Runtime; | ||
using Java.Interop; | ||
using System.Runtime.InteropServices; | ||
|
||
namespace NativeAOT; | ||
|
||
static class JavaInteropRuntime | ||
{ | ||
static JniRuntime? runtime; | ||
|
||
[UnmanagedCallersOnly (EntryPoint="JNI_OnLoad")] | ||
static int JNI_OnLoad (IntPtr vm, IntPtr reserved) | ||
{ | ||
try { | ||
AndroidLog.Print (AndroidLogLevel.Info, "JavaInteropRuntime", "JNI_OnLoad()"); | ||
LogcatTextWriter.Init (); | ||
return (int) JniVersion.v1_6; | ||
} | ||
catch (Exception e) { | ||
AndroidLog.Print (AndroidLogLevel.Error, "JavaInteropRuntime", $"JNI_OnLoad() failed: {e}"); | ||
return 0; | ||
} | ||
} | ||
|
||
[UnmanagedCallersOnly (EntryPoint="JNI_OnUnload")] | ||
static void JNI_OnUnload (IntPtr vm, IntPtr reserved) | ||
{ | ||
AndroidLog.Print(AndroidLogLevel.Info, "JavaInteropRuntime", "JNI_OnUnload"); | ||
runtime?.Dispose (); | ||
} | ||
|
||
// symbol name from `$(IntermediateOutputPath)obj/Release/osx-arm64/h-classes/net_dot_jni_hello_JavaInteropRuntime.h` | ||
[UnmanagedCallersOnly (EntryPoint="Java_net_dot_jni_nativeaot_JavaInteropRuntime_init")] | ||
static void init (IntPtr jnienv, IntPtr klass) | ||
{ | ||
try { | ||
var options = new JreRuntimeOptions { | ||
EnvironmentPointer = jnienv, | ||
TypeManager = new NativeAotTypeManager (), | ||
ValueManager = new NativeAotValueManager (), | ||
UseMarshalMemberBuilder = false, | ||
JniGlobalReferenceLogWriter = new LogcatTextWriter (AndroidLogLevel.Debug, "NativeAot:GREF"), | ||
JniLocalReferenceLogWriter = new LogcatTextWriter (AndroidLogLevel.Debug, "NativeAot:LREF"), | ||
}; | ||
runtime = options.CreateJreVM (); | ||
|
||
// Entry point into Mono.Android.dll | ||
JNIEnvInit.InitializeJniRuntime (runtime); | ||
} | ||
catch (Exception e) { | ||
AndroidLog.Print (AndroidLogLevel.Error, "JavaInteropRuntime", $"JavaInteropRuntime.init: error: {e}"); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
package net.dot.jni.nativeaot; | ||
|
||
import android.util.Log; | ||
|
||
public class JavaInteropRuntime { | ||
static { | ||
Log.d("JavaInteropRuntime", "Loading NativeAOT.so..."); | ||
System.loadLibrary("NativeAOT"); | ||
} | ||
|
||
private JavaInteropRuntime() { | ||
} | ||
|
||
public static native void init(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
// NOTE: logging methods below are need temporarily due to: | ||
// 1) linux-bionic BCL doesn't redirect stdout/stderr to logcat | ||
// 2) Android.Util.Log won't work until we initialize the Java.Interop.JreRuntime | ||
|
||
using System.IO; | ||
using System.Runtime.InteropServices; | ||
using System.Text; | ||
|
||
namespace NativeAOT; | ||
|
||
internal sealed class LogcatTextWriter : TextWriter { | ||
|
||
public static void Init () | ||
{ | ||
// This method is a no-op, but it's necessary to ensure the static | ||
// constructor is executed. | ||
} | ||
|
||
static LogcatTextWriter () | ||
{ | ||
Console.SetOut (new LogcatTextWriter (AndroidLogLevel.Info)); | ||
Console.SetError (new LogcatTextWriter (AndroidLogLevel.Error)); | ||
} | ||
|
||
AndroidLogLevel Level; | ||
string Tag; | ||
|
||
internal LogcatTextWriter (AndroidLogLevel level, string tag = "NativeAotFromAndroid") | ||
{ | ||
Level = level; | ||
Tag = tag; | ||
} | ||
|
||
public override Encoding Encoding => Encoding.UTF8; | ||
public override string NewLine => "\n"; | ||
|
||
public override void WriteLine (string? value) | ||
{ | ||
if (value == null) { | ||
AndroidLog.Print (Level, Tag, ""); | ||
return; | ||
} | ||
ReadOnlySpan<char> span = value; | ||
while (!span.IsEmpty) { | ||
if (span.IndexOf ('\n') is int n && n < 0) { | ||
break; | ||
} | ||
var line = span.Slice (0, n); | ||
AndroidLog.Print (Level, Tag, line.ToString ()); | ||
span = span.Slice (n + 1); | ||
} | ||
AndroidLog.Print (Level, Tag, span.ToString ()); | ||
} | ||
} | ||
|
||
static class AndroidLog { | ||
|
||
[DllImport ("log", EntryPoint = "__android_log_print", CallingConvention = CallingConvention.Cdecl)] | ||
private static extern void __android_log_print(AndroidLogLevel level, string? tag, string format, string args, IntPtr ptr); | ||
|
||
internal static void Print(AndroidLogLevel level, string? tag, string message) => | ||
__android_log_print(level, tag, "%s", message, IntPtr.Zero); | ||
|
||
} | ||
|
||
internal enum AndroidLogLevel | ||
{ | ||
Unknown = 0x00, | ||
Default = 0x01, | ||
Verbose = 0x02, | ||
Debug = 0x03, | ||
Info = 0x04, | ||
Warn = 0x05, | ||
Error = 0x06, | ||
Fatal = 0x07, | ||
Silent = 0x08 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
using Android.Runtime; | ||
using System.Reflection; | ||
using System.Runtime.InteropServices; | ||
|
||
namespace NativeAOT; | ||
|
||
[Register("my/MainActivity")] // Required for typemap in NativeAotTypeManager | ||
[Activity(Label = "@string/app_name", MainLauncher = true)] | ||
public class MainActivity : Activity | ||
{ | ||
protected override void OnCreate(Bundle? savedInstanceState) | ||
{ | ||
base.OnCreate(savedInstanceState); | ||
|
||
// Set our view from the "main" layout resource | ||
SetContentView(Resource.Layout.activity_main); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
<Project Sdk="Microsoft.NET.Sdk"> | ||
<PropertyGroup> | ||
<TargetFramework>$(DotNetAndroidTargetFramework)</TargetFramework> | ||
<SupportedOSPlatformVersion>21</SupportedOSPlatformVersion> | ||
<OutputType>Exe</OutputType> | ||
<Nullable>enable</Nullable> | ||
<ImplicitUsings>enable</ImplicitUsings> | ||
<ApplicationId>net.dot.hellonativeaot</ApplicationId> | ||
<ApplicationVersion>1</ApplicationVersion> | ||
<ApplicationDisplayVersion>1.0</ApplicationDisplayVersion> | ||
<AndroidPackageFormat>apk</AndroidPackageFormat> | ||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> | ||
<!-- Temporary for InternalsVisibleTo --> | ||
<SignAssembly>true</SignAssembly> | ||
<AssemblyOriginatorKeyFile>..\..\product.snk</AssemblyOriginatorKeyFile> | ||
<!-- Default to arm64 device --> | ||
<RuntimeIdentifier>android-arm64</RuntimeIdentifier> | ||
<!-- Current required properties for NativeAOT --> | ||
<PublishAot>true</PublishAot> | ||
<PublishAotUsingRuntimePack>true</PublishAotUsingRuntimePack> | ||
</PropertyGroup> | ||
|
||
<!-- Settings for CI --> | ||
<PropertyGroup Condition=" '$(RunningOnCI)' == 'true' "> | ||
<!-- x86_64 emulator --> | ||
<RuntimeIdentifier>android-x64</RuntimeIdentifier> | ||
<_NuGetFolderOnCI>..\..\bin\Build$(Configuration)\nuget-unsigned</_NuGetFolderOnCI> | ||
<RestoreAdditionalProjectSources Condition="Exists('$(_NuGetFolderOnCI)')">$(_NuGetFolderOnCI)</RestoreAdditionalProjectSources> | ||
<_FastDeploymentDiagnosticLogging>true</_FastDeploymentDiagnosticLogging> | ||
</PropertyGroup> | ||
|
||
<ItemGroup> | ||
<AndroidJavaSource Update="*.java" Bind="false" /> | ||
<ProjectReference Include="..\..\external\Java.Interop\src\Java.Runtime.Environment\Java.Runtime.Environment.csproj" /> | ||
</ItemGroup> | ||
</Project> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
package net.dot.jni.nativeaot; | ||
|
||
import android.util.Log; | ||
|
||
public class NativeAotRuntimeProvider | ||
extends android.content.ContentProvider | ||
{ | ||
private static final String TAG = "NativeAotRuntimeProvider"; | ||
|
||
public NativeAotRuntimeProvider() { | ||
Log.d(TAG, "NativeAotRuntimeProvider()"); | ||
} | ||
|
||
@Override | ||
public boolean onCreate() { | ||
Log.d(TAG, "NativeAotRuntimeProvider.onCreate()"); | ||
return true; | ||
} | ||
|
||
@Override | ||
public void attachInfo(android.content.Context context, android.content.pm.ProviderInfo info) { | ||
Log.d(TAG, "NativeAotRuntimeProvider.attachInfo(): calling JavaInteropRuntime.init()…"); | ||
JavaInteropRuntime.init(); | ||
super.attachInfo (context, info); | ||
} | ||
|
||
@Override | ||
public android.database.Cursor query(android.net.Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { | ||
throw new RuntimeException ("This operation is not supported."); | ||
} | ||
|
||
@Override | ||
public String getType(android.net.Uri uri) { | ||
throw new RuntimeException ("This operation is not supported."); | ||
} | ||
|
||
@Override | ||
public android.net.Uri insert(android.net.Uri uri, android.content.ContentValues initialValues) { | ||
throw new RuntimeException ("This operation is not supported."); | ||
} | ||
|
||
@Override | ||
public int delete(android.net.Uri uri, String where, String[] whereArgs) { | ||
throw new RuntimeException ("This operation is not supported."); | ||
} | ||
|
||
@Override | ||
public int update(android.net.Uri uri, android.content.ContentValues values, String where, String[] whereArgs) { | ||
throw new RuntimeException ("This operation is not supported."); | ||
} | ||
} |
Oops, something went wrong.