Skip to content

Commit

Permalink
Enable marshal methods support by default (xamarin#7351)
Browse files Browse the repository at this point in the history
Context: 5271f3e
Context: e1af958
Context: 186a9fc
Context: 903ba37
Context: a760281
Context: https://github.com/xamarin/xamarin-android/wiki/Blueprint#java-type-registration

Complete the LLVM Marshal Methods effort sketched out in e1af958.

LLVM Marshal Methods are only supported in .NET Android, *not*
Xamarin.Android.

A *Marshal Method* is a JNI Callable C function (pointer) which has
[parameter types and return types which comply with the JNI ABI][0].
[`generator`][1] emits marshal methods as part of the binding, which
are turned into Delegate instances at runtime as part of
[Java Type Registration][2].

*LLVM Marshal Methods* turn this runtime operation -- looking up
`generator`-emitted marshal methods and registering those methods
with Java -- into a *build-time* operation, using LLVM-IR to generate
[JNI Native Method Names][3] which will then be contained within
`libxamarin-app.so`.  LLVM Marshal Methods will also *remove* the
previous Reflection-based infrastructure from relevant types.

LLVM Marshal Methods are *enabled by default* for ***Release***
configuration builds in .NET 8, and disabled by default for Debug
builds. The new `$(AndroidEnableMarshalMethods)` MSBuild property
explicitly controls whether or not LLVM Marshal Methods are used.

LLVM Marshal Methods are *not* available in Classic Xamarin.Android.


~~ Build Phase: Scanning for Compatible Types ~~

During the application build, all `Java.Lang.Object` and
`Java.Lang.Throwable` subclasses are scanned as part of
[Java Callable Wrapper generation][4], looking for "un-bound"
(user-written) types which override `abstract` or `virtual`
methods, or implement interface members.  This is done to emit
Java Callable Wrappers, Java code which "mirrors" the C# code with
an appropriate base class, interface implementation list, and
Java `native` method declarations for "virtual" member overrides.

This scanning process is updated for LLVM Marshal Methods to classify
each type to see if it requires the legacy Delegate-based
registration mechanism, as constructs such as
`[Java.Interop.ExportAttribute]` cannot (yet) be used with
LLVM Marshal Methods.


~~ Build Phase: Java Callable Wrapper Generation ~~

For example, given the C# type:

    // C#
    public partial class MainActivity : Activity {
        protected override void OnCreate (Bundle? state) => …
    }

Then the resulting Java Callable Wrapper *without* LLVM Marshal
Methods enabled will be:

    // Java + No LLVM Marshal Methods
    public /* partial */ class MainActivity extends Activity {
        static {
            String __md_methods =
                "n_onCreate:(Landroid/os/Bundle;)V:GetOnCreate_Landroid_os_Bundle_Handler\n";
            mono.android.Runtime.register ("Example.MainActivity, ExampleAssembly", MainActivity.class, __md_methods);
        }
        public void onCreate (android.os.Bundle p0) {n_onCreate(p0);}
        private native void n_onCreate (android.os.Bundle p0);
    }

When LLVM Marshal Methods are enabled, the Java Callable Wrapper
has no static constructor, nor any call to `Runtime.register()`.


~~ Build Phase: Marshal Method Wrapper ~~

Consider the binding infrastructure code that `generator` emits for
`Android.App.Activity.OnCreate()`:

	namespace Android.App {
	    public partial class Activity {
	        static Delegate? cb_onCreate_Landroid_os_Bundle_;
	#pragma warning disable 0169
	        static Delegate GetOnCreate_Landroid_os_Bundle_Handler ()
	        {
	            if (cb_onCreate_Landroid_os_Bundle_ == null)
	                cb_onCreate_Landroid_os_Bundle_ = JNINativeWrapper.CreateDelegate ((_JniMarshal_PPL_V) n_OnCreate_Landroid_os_Bundle_);
	            return cb_onCreate_Landroid_os_Bundle_;
	        }

	        static void n_OnCreate_Landroid_os_Bundle_ (IntPtr jnienv, IntPtr native__this, IntPtr native_savedInstanceState)
	        {
	            var __this = global::Java.Lang.Object.GetObject<Android.App.Activity> (jnienv, native__this, JniHandleOwnership.DoNotTransfer)!;
	            var savedInstanceState = global::Java.Lang.Object.GetObject<Android.OS.Bundle> (native_savedInstanceState, JniHandleOwnership.DoNotTransfer);
	            __this.OnCreate (savedInstanceState);
	        }
	#pragma warning restore 0169

	        [Register ("onCreate", "(Landroid/os/Bundle;)V", "GetOnCreate_Landroid_os_Bundle_Handler")]
	        protected virtual unsafe void OnCreate (Android.OS.Bundle? savedInstanceState)
	        {
	            const string __id = "onCreate.(Landroid/os/Bundle;)V";
	            try {
	                JniArgumentValue* __args = stackalloc JniArgumentValue [1];
	                __args [0] = new JniArgumentValue ((savedInstanceState == null) ? IntPtr.Zero : ((global::Java.Lang.Object) savedInstanceState).Handle);
	                _members.InstanceMethods.InvokeVirtualVoidMethod (__id, this, __args);
	            } finally {
	                global::System.GC.KeepAlive (savedInstanceState);
	            }
	        }
	    }
	}

When LLVM Marshal Methods are enabled, the following IL
transformations are performed:

  * The `static Delegate? cb_…` field is removed.
  * The `static Delegate Get…Handler()` method is removed.
  * A new `static … n_…_mm_wrapper()` method is added.

The `n_…_mm_wrapper()` method is responsible for exception marshaling
and for `bool` marshaling.  The `n_…_mm_wrapper()` method has the
[`UnmanagedCallersOnlyAttribute`][5], and works by calling the
existing `n_…()` method:

	namespace Android.App {
	    public partial class Activity {

	        // Added
	        [UnmanagedCallersOnly]
	        static void n_OnCreate_Landroid_os_Bundle__mm_wrapper (IntPtr jnienv, IntPtr native__this, IntPtr native_savedInstanceState)
	        {
	            try {
	                n_OnCreate_Landroid_os_Bundle_ (jnienv, native__this, native_savedInstanceState);
	            }
	            catch (Exception __e) {
	                Android.Runtime.AndroidEnvironmentInternal.UnhandledException (__e);
	            }
	        }
	    }
	}


~~ Build Phase: LLVM-IR Marshal Method Generation ~~

For each Java `native` method declaration contained in Java Callable
Wrappers which support LLVM Marshal Methods, LLVM-IR is used to
generate the JNI Native Method with the `Java_…` symbol name:

	using android_app_activity_on_create_bundle_fn = void (*) (JNIEnv *env, jclass klass, jobject savedInstanceState);
	static android_app_activity_on_create_bundle_fn android_app_activity_on_create_bundle = nullptr;

	extern "C" JNIEXPORT void
	JNICALL Java_helloandroid_MainActivity_n_1onCreate__Landroid_os_Bundle_2 (JNIEnv *env, jclass klass, jobject savedInstanceState) noexcept
	{
	  if (android_app_activity_on_create_bundle == nullptr) {
	    get_function_pointer (
	        16,                                                               // mono image index; computed at build time
	        0,                                                                // class index; computed at build time
	        0x0600055B,                                                       // method token; computed at build time
	        reinterpret_cast<void*&>(android_app_activity_on_create_bundle)   // target pointer
	    );
	  }

	  android_app_activity_on_create_bundle (env, klass, savedInstanceState);
	}


~~ Other Changes ~~

The new `Android.Runtime.JNIEnvInit` type was split out of the
`Android.Runtime.JNIEnv` type to further reduce startup overhead, as
there are fewer fields to initialize.

The `Mono.Android.Runtime.dll` assembly is added because the
Marshal Method Wrapper needs to be able to invoke what *was*
`AndroidEnvironment.UnhandledException()`, *while also* updating
`Mono.Android.dll`!  `Mono.Android.Runtime.dll` allows the marshal
method wrappers to reliably use
`Android.Runtime.AndroidEnvironmentInternal.UnhandledException()`,
which will *never* be changed by the marshal method wrapper
infrastructure.


~~ Results ~~

Marshal methods make application startup around 3.2% faster (the
bigger the app the  more performance gains), with a bit room for
future improvements (by eliminating wrapper methods and other
optimizations):

[.NET Podcasts][6] app test results:

| Before  | After   | Δ        | Notes                                          |
| ------- | ------- | -------- | ---------------------------------------------- |
| 868.500 | 840.400 | -3.24% ✓ | preload disabled; 32-bit build; no compression |
| 863.700 | 837.600 | -3.02% ✓ | preload disabled; 64-bit build; no compression |
| 872.500 | 850.100 | -2.57% ✓ | preload enabled; 64-bit build                  |
| 877.000 | 854.800 | -2.53% ✓ | preload disabled; 64-bit build                 |
| 859.300 | 839.800 | -2.27% ✓ | preload enabled; 64-bit build; no compression  |
| 871.700 | 853.100 | -2.13% ✓ | preload enabled; 32-bit build                  |
| 860.600 | 842.300 | -2.13% ✓ | preload enabled; 32-bit build; no compression  |
| 869.500 | 852.500 | -1.96% ✓ | preload disabled; 32-bit build                 |

Maui Hello World app test results:

| Before  | After   | Δ        | Notes                                          |
| ------- | ------- | -------- | ---------------------------------------------- |
| 374.800 | 365.500 | -2.48% ✓ | preload disabled; 64-bit build                 |
| 374.100 | 365.600 | -2.27% ✓ | preload disabled; 32-bit build                 |
| 369.100 | 364.400 | -1.27% ✓ | preload enabled; 32-bit build                  |
| 364.300 | 360.600 | -1.02% ✓ | preload enabled; 32-bit build; no compression  |
| 368.900 | 365.400 | -0.95% ✓ | preload enabled; 64-bit build                  |
| 362.500 | 359.400 | -0.86% ✓ | preload disabled; 32-bit build; no compression |
| 361.100 | 361.600 | +0.14% ✗ | preload enabled; 64-bit build; no compression  |
| 359.200 | 368.000 | +2.39% ✗ | preload disabled; 64-bit build; no compression |


[0]: https://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/design.html#native_method_arguments
[1]: https://github.com/xamarin/xamarin-android/wiki/Blueprint#generator
[2]: https://github.com/xamarin/xamarin-android/wiki/Blueprint#java-type-registration
[3]: https://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/design.html#resolving_native_method_names
[4]: https://github.com/xamarin/xamarin-android/wiki/Blueprint#java-callable-wrapper-generator
[5]: https://learn.microsoft.com/en-us/dotnet/api/system.runtime.interopservices.unmanagedcallersonlyattribute?view=net-7.0
[6]: https://github.com/microsoft/dotnet-podcasts/tree/net7.0
  • Loading branch information
grendello committed Oct 10, 2022
1 parent 2c7d72d commit 8bc7a3e
Show file tree
Hide file tree
Showing 79 changed files with 2,585 additions and 1,098 deletions.
4 changes: 0 additions & 4 deletions Directory.Build.props
Expand Up @@ -27,10 +27,6 @@
<DisableTransitiveFrameworkReferenceDownloads>true</DisableTransitiveFrameworkReferenceDownloads>
</PropertyGroup>

<PropertyGroup Condition=" '$(MSBuildRuntimeType)' == 'Core' ">
<_EnableMarshalMethods>NoThanks</_EnableMarshalMethods> <!-- set to YesPlease to enable -->
</PropertyGroup>

<PropertyGroup>
<ProductVersion>13.1.99</ProductVersion>
<!-- NuGet package version numbers. See Documentation/guides/OneDotNet.md.
Expand Down
9 changes: 9 additions & 0 deletions Documentation/guides/building-apps/build-properties.md
Expand Up @@ -424,6 +424,15 @@ not wish to run those checks.

Added in Xamarin.Android 9.4.

## AndroidEnableMarshalMethods

A bool property, not available in the classic Xamarin.Android
releases.

Enable or disable generation of [marshal
methods](../../internals/JavaJNI_Interop.md). Defaults to `True` for
`Release` builds and to `False` for `Debug` builds.

## AndroidEnableMultiDex

A boolean property that
Expand Down
766 changes: 766 additions & 0 deletions Documentation/guides/internals/JavaJNI_Interop.md

Large diffs are not rendered by default.

9 changes: 9 additions & 0 deletions Xamarin.Android.sln
Expand Up @@ -92,6 +92,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Mono.Android", "src\Mono.An
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Mono.Android.Export", "src\Mono.Android.Export\Mono.Android.Export.csproj", "{B8105878-D423-4159-A3E7-028298281EC6}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Mono.Android.Runtime", "src\Mono.Android.Runtime\Mono.Android.Runtime.csproj", "{43564FB3-0F79-4FF4-A2B0-B1637072FF01}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Android.Build.BaseTasks", "external\xamarin-android-tools\src\Microsoft.Android.Build.BaseTasks\Microsoft.Android.Build.BaseTasks.csproj", "{3DE17662-DCD6-4F49-AF06-D39AACC8649A}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Xamarin.Android.Tools.AndroidSdk", "external\xamarin-android-tools\src\Xamarin.Android.Tools.AndroidSdk\Xamarin.Android.Tools.AndroidSdk.csproj", "{E34BCFA0-CAA4-412C-AA1C-75DB8D67D157}"
Expand Down Expand Up @@ -296,6 +298,12 @@ Global
{B8105878-D423-4159-A3E7-028298281EC6}.Debug|AnyCPU.Build.0 = Debug|Any CPU
{B8105878-D423-4159-A3E7-028298281EC6}.Release|AnyCPU.ActiveCfg = Release|Any CPU
{B8105878-D423-4159-A3E7-028298281EC6}.Release|AnyCPU.Build.0 = Release|Any CPU

{43564FB3-0F79-4FF4-A2B0-B1637072FF01}.Debug|AnyCPU.ActiveCfg = Debug|Any CPU
{43564FB3-0F79-4FF4-A2B0-B1637072FF01}.Debug|AnyCPU.Build.0 = Debug|Any CPU
{43564FB3-0F79-4FF4-A2B0-B1637072FF01}.Release|AnyCPU.ActiveCfg = Release|Any CPU
{43564FB3-0F79-4FF4-A2B0-B1637072FF01}.Release|AnyCPU.Build.0 = Release|Any CPU

{3DE17662-DCD6-4F49-AF06-D39AACC8649A}.Debug|AnyCPU.ActiveCfg = Debug|Any CPU
{3DE17662-DCD6-4F49-AF06-D39AACC8649A}.Debug|AnyCPU.Build.0 = Debug|Any CPU
{3DE17662-DCD6-4F49-AF06-D39AACC8649A}.Release|AnyCPU.ActiveCfg = Release|Any CPU
Expand Down Expand Up @@ -456,6 +464,7 @@ Global
{73DF9E10-E933-4222-B8E1-F4536FFF9FAD} = {864062D3-A415-4A6F-9324-5820237BA058}
{66CF299A-CE95-4131-BCD8-DB66E30C4BF7} = {04E3E11E-B47D-4599-8AFC-50515A95E715}
{B8105878-D423-4159-A3E7-028298281EC6} = {04E3E11E-B47D-4599-8AFC-50515A95E715}
{43564FB3-0F79-4FF4-A2B0-B1637072FF01} = {04E3E11E-B47D-4599-8AFC-50515A95E715}
{3DE17662-DCD6-4F49-AF06-D39AACC8649A} = {04E3E11E-B47D-4599-8AFC-50515A95E715}
{E34BCFA0-CAA4-412C-AA1C-75DB8D67D157} = {04E3E11E-B47D-4599-8AFC-50515A95E715}
{1E5501E8-49C1-4659-838D-CC9720C5208F} = {CAB438D8-B0F5-4AF0-BEBD-9E2ADBD7B483}
Expand Down
5 changes: 4 additions & 1 deletion build-tools/automation/yaml-templates/run-designer-tests.yml
Expand Up @@ -62,7 +62,10 @@ steps:
displayName: 'Copy binlogs'
inputs:
sourceFolder: ${{ parameters.designerSourcePath }}/Xamarin.Designer.Android
contents: '**/*.binlog'
contents: |
**/*.binlog
**/hs*.log
**/hs*.mdmp
targetFolder: $(Build.ArtifactStagingDirectory)/designer-binlogs
overWrite: true
flattenFolders: true
Expand Down
1 change: 1 addition & 0 deletions build-tools/create-packs/Microsoft.Android.Ref.proj
Expand Up @@ -33,6 +33,7 @@ by projects that use the Microsoft.Android framework in .NET 6+.
<ItemGroup>
<_AndroidRefPackAssemblies Include="$(JavaInteropSourceDirectory)\bin\$(Configuration)-net7.0\ref\Java.Interop.dll" />
<_AndroidRefPackAssemblies Include="$(_MonoAndroidNETDefaultOutDir)ref\Mono.Android.dll" />
<_AndroidRefPackAssemblies Include="$(_MonoAndroidNETDefaultOutDir)ref\Mono.Android.Runtime.dll" />
<!-- Always include stable Mono.Android.Export.dll -->
<_AndroidRefPackAssemblies Include="$(_MonoAndroidNETOutputRoot)$(AndroidLatestStableApiLevel)\ref\Mono.Android.Export.dll" />
<FrameworkListFileClass Include="@(_AndroidRefPackAssemblies->'%(Filename)%(Extension)')" Profile="Android" />
Expand Down
1 change: 1 addition & 0 deletions build-tools/create-packs/Microsoft.Android.Runtime.proj
Expand Up @@ -35,6 +35,7 @@ projects that use the Microsoft.Android framework in .NET 6+.
<ItemGroup>
<_AndroidRuntimePackAssemblies Include="$(_MonoAndroidNETDefaultOutDir)Java.Interop.dll" />
<_AndroidRuntimePackAssemblies Include="$(_MonoAndroidNETDefaultOutDir)Mono.Android.dll" />
<_AndroidRuntimePackAssemblies Include="$(_MonoAndroidNETDefaultOutDir)Mono.Android.Runtime.dll" />
<!-- Always include stable Mono.Android.Export.dll -->
<_AndroidRuntimePackAssemblies Include="$(_MonoAndroidNETOutputRoot)$(AndroidLatestStableApiLevel)\Mono.Android.Export.dll" />
<_AndroidRuntimePackAssets Include="$(MicrosoftAndroidSdkOutDir)lib\$(AndroidRID)\libmono-android.debug.so" />
Expand Down
1 change: 0 additions & 1 deletion build-tools/scripts/JavaCallableWrappers.targets
Expand Up @@ -23,7 +23,6 @@
/>
<ItemGroup>
<_JavaSources Include="$(IntermediateOutputPath)jcw\src\**\*.java" />
<_JavaSources Include="$(JavaInteropSourceDirectory)\src\Java.Interop\java\com\xamarin\**\*.java" />
</ItemGroup>
<WriteLinesToFile
File="$(IntermediateOutputPath)jcw/classes.txt"
Expand Down
2 changes: 1 addition & 1 deletion build-tools/scripts/TestApks.targets
Expand Up @@ -103,7 +103,7 @@
WriteOutputAsMessage="True"
/>
<Xamarin.Android.Tools.BootstrapTasks.Adb
Arguments="$(_AdbTarget) shell setprop debug.mono.log timing"
Arguments="$(_AdbTarget) shell setprop debug.mono.log default,assembly,timing=bare"
IgnoreExitCode="True"
ToolExe="$(AdbToolExe)"
ToolPath="$(AdbToolPath)"
Expand Down
@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<linker>
<assembly fullname="Mono.Android.Runtime" preserve="all" />
</linker>
Expand Up @@ -7,17 +7,17 @@
<type fullname="Android.Runtime.InputStreamInvoker" preserve="methods" />
<type fullname="Android.Runtime.JNIEnv">
<method name="Exit" />
<method name="Initialize" />
<method name="PropagateUncaughtException" />
</type>
<type fullname="Android.Runtime.JNIEnvInit">
<method name="Initialize" />
<method name="RegisterJniNatives" />
</type>
<type fullname="Android.Runtime.JNINativeWrapper" />
<type fullname="Android.Runtime.JObjectRefType" />
<type fullname="Android.Runtime.JValue" />
<type fullname="Android.Runtime.JniHandleOwnership" />
<type fullname="Android.Runtime.Logger" />
<type fullname="Android.Runtime.LogLevel" />
<type fullname="Android.Runtime.LogCategories" />
<type fullname="Android.Runtime.NamespaceMappingAttribute" />
<type fullname="Android.Runtime.OutputStreamAdapter" preserve="methods" />
<type fullname="Android.Runtime.OutputStreamInvoker" preserve="methods" />
Expand Down
@@ -0,0 +1,18 @@
using System;

namespace Android.Runtime
{
internal static class AndroidEnvironmentInternal
{
internal static Action<Exception>? UnhandledExceptionHandler;

internal static void UnhandledException (Exception e)
{
if (UnhandledExceptionHandler == null) {
return;
}

UnhandledExceptionHandler (e);
}
}
}
62 changes: 62 additions & 0 deletions src/Mono.Android.Runtime/Mono.Android.Runtime.csproj
@@ -0,0 +1,62 @@
<Project>
<UsingTask AssemblyFile="$(PrepTasksAssembly)" TaskName="Xamarin.Android.BuildTools.PrepTasks.ReplaceFileContents" />
<Import Project="Sdk.props" Sdk="Microsoft.NET.Sdk" />
<Import Project="..\..\Configuration.props" />
<Import Project="..\..\build-tools\scripts\XAVersionInfo.targets" />

<PropertyGroup>
<TargetFrameworks>$(DotNetTargetFramework)</TargetFrameworks>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
<AssemblyOriginatorKeyFile>..\..\product.snk</AssemblyOriginatorKeyFile>
<EnableDefaultCompileItems>false</EnableDefaultCompileItems>
<EnableSingleFileAnalyzer>true</EnableSingleFileAnalyzer>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<ImplicitlyExpandDesignTimeFacades>false</ImplicitlyExpandDesignTimeFacades>
<LangVersion>10</LangVersion>
<NoStdLib>true</NoStdLib>
<Nullable>enable</Nullable>
<ProduceReferenceAssembly>true</ProduceReferenceAssembly>
<SignAssembly>true</SignAssembly>

<!-- Ignore "unused member" warnings from code that originates from Mono.CodeGeneration -->
<NoWarn>$(NoWarn);CS0169;CS0414;CS0649</NoWarn>

<DefineConstants>$(DefineConstants);INSIDE_MONO_ANDROID_RUNTIME;JAVA_INTEROP</DefineConstants>
</PropertyGroup>

<PropertyGroup>
<OutputPath>$(_MonoAndroidNETDefaultOutDir)</OutputPath>
</PropertyGroup>

<Import Project="Sdk.targets" Sdk="Microsoft.NET.Sdk" />

<!-- Only build the .NET 6+ version of 'Mono.Android.Export.dll' for the latest stable Android version. -->
<PropertyGroup Condition=" '$(AndroidApiLevel)' != '$(AndroidLatestStableApiLevel)' ">
<BuildDependsOn></BuildDependsOn>
</PropertyGroup>

<!-- Copy .NET ref/runtime assemblies to bin/$(Configuration)/dotnet/packs folder -->
<PropertyGroup Condition=" '$(AndroidApiLevel)' == '$(AndroidLatestStableApiLevel)' ">
<BuildDependsOn>
$(BuildDependsOn);
_CopyToPackDirs;
</BuildDependsOn>
</PropertyGroup>

<ItemGroup>
<Compile Include="$(IntermediateOutputPath)AssemblyInfo.cs" />
<Compile Include="..\Mono.Android\Android.Runtime\AndroidRuntimeInternal.cs" />
<Compile Include="..\Mono.Android\Android.Runtime\LogCategories.cs" />
<Compile Include="..\Mono.Android\Android.Runtime\LogLevel.cs" />
<Compile Include="..\Mono.Android\Android.Runtime\RuntimeConstants.cs" />
<Compile Include="..\Mono.Android\Android.Runtime\RuntimeNativeMethods.cs" />
<Compile Include="Android.Runtime\AndroidEnvironmentInternal.cs" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\..\external\Java.Interop\src\Java.Interop\Java.Interop.csproj" />
</ItemGroup>

<Import Project="Mono.Android.Runtime.targets" />
</Project>
52 changes: 52 additions & 0 deletions src/Mono.Android.Runtime/Mono.Android.Runtime.targets
@@ -0,0 +1,52 @@
<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<!-- Creates 'AssemblyInfo.cs' with appropriate version information -->
<Target Name="_BuildAssemblyInfo_cs"
DependsOnTargets="GetXAVersionInfo"
BeforeTargets="CoreCompile"
Condition="!Exists ('$(IntermediateOutputPath)AssemblyInfo.cs')"
Inputs="Properties\AssemblyInfo.cs.in"
Outputs="$(IntermediateOutputPath)AssemblyInfo.cs">
<PropertyGroup Condition=" '$(TargetFramework)' == 'monoandroid10' ">
<_PackageVersion>$(ProductVersion)</_PackageVersion>
<_PackageVersionBuild>$(XAVersionCommitCount)</_PackageVersionBuild>
</PropertyGroup>
<PropertyGroup Condition=" '$(TargetFramework)' != 'monoandroid10' ">
<_PackageVersion>$(AndroidPackVersion)</_PackageVersion>
<_PackageVersionBuild>$(PackVersionCommitCount)</_PackageVersionBuild>
</PropertyGroup>
<ReplaceFileContents
SourceFile="Properties\AssemblyInfo.cs.in"
DestinationFile="$(IntermediateOutputPath)AssemblyInfo.cs"
Replacements="@PACKAGE_VERSION@=$(_PackageVersion);@PACKAGE_VERSION_BUILD@=$(_PackageVersionBuild);@PACKAGE_HEAD_REV@=$(XAVersionHash);@PACKAGE_HEAD_BRANCH@=$(XAVersionBranch);@API_LEVEL@=$(AndroidApiLevel);@MIN_API_LEVEL@=$(AndroidMinimumDotNetApiLevel)">
</ReplaceFileContents>
</Target>

<Target Name="_CopyToPackDirs" >
<Copy
SourceFiles="$(OutputPath)ref\Mono.Android.Runtime.dll"
DestinationFolder="$(MicrosoftAndroidRefPackDir)"
SkipUnchangedFiles="true"
/>
<Copy
SourceFiles="$(OutputPath)Mono.Android.Runtime.dll"
DestinationFolder="$(MicrosoftAndroidArmPackDir)lib\$(DotNetTargetFramework)"
SkipUnchangedFiles="true"
/>
<Copy
SourceFiles="$(OutputPath)Mono.Android.Runtime.dll"
DestinationFolder="$(MicrosoftAndroidArm64PackDir)lib\$(DotNetTargetFramework)"
SkipUnchangedFiles="true"
/>
<Copy
SourceFiles="$(OutputPath)Mono.Android.Runtime.dll"
DestinationFolder="$(MicrosoftAndroidx86PackDir)lib\$(DotNetTargetFramework)"
SkipUnchangedFiles="true"
/>
<Copy
SourceFiles="$(OutputPath)Mono.Android.Runtime.dll"
DestinationFolder="$(MicrosoftAndroidx64PackDir)lib\$(DotNetTargetFramework)"
SkipUnchangedFiles="true"
/>
</Target>
</Project>
21 changes: 21 additions & 0 deletions src/Mono.Android.Runtime/Properties/AssemblyInfo.cs.in
@@ -0,0 +1,21 @@
//
// AssemblyInfo.cs.in
//
// Authors:
// Jonathan Pryor (jonp@xamarin.com)
//
// Copyright 2014 Xamarin, Inc.
// Copyright 2016 Microsoft Corporation.

using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;

[assembly: AssemblyInformationalVersion ("@PACKAGE_VERSION@.@PACKAGE_VERSION_BUILD@; git-rev-head:@PACKAGE_HEAD_REV@; git-branch:@PACKAGE_HEAD_BRANCH@")]
[assembly: AssemblyTitle ("Mono.Android.Runtime.dll")]
[assembly: AssemblyProduct ("Xamarin.Android")]
[assembly: AssemblyCompany ("Microsoft Corporation")]
[assembly: TargetPlatform("Android@API_LEVEL@.0")]
[assembly: SupportedOSPlatform("Android@MIN_API_LEVEL@.0")]

[assembly: InternalsVisibleTo("Mono.Android, PublicKey=0024000004800000940000000602000000240000525341310004000011000000438ac2a5acfbf16cbd2b2b47a62762f273df9cb2795ceccdf77d10bf508e69e7a362ea7a45455bbf3ac955e1f2e2814f144e5d817efc4c6502cc012df310783348304e3ae38573c6d658c234025821fda87a0be8a0d504df564e2c93b2b878925f42503e9d54dfef9f9586d9e6f38a305769587b1de01f6c0410328b2c9733db")]
2 changes: 1 addition & 1 deletion src/Mono.Android/Android.App/SyncContext.cs
Expand Up @@ -18,7 +18,7 @@ static bool EnsureLooper ([NotNullWhen (true)]Looper? looper, SendOrPostCallback
{
if (looper == null) {
var message = $"No Android message loop is available. Skipping invocation of `{d.Method.DeclaringType?.FullName}.{d.Method.Name}`!";
if (JNIEnv.IsRunningOnDesktop)
if (JNIEnvInit.IsRunningOnDesktop)
message += " Using `await` when running on the Android Designer is not currently supported. Please use the `View.IsInEditMode` property.";
Logger.Log (LogLevel.Error, "monodroid-synccontext", message);
return false;
Expand Down
22 changes: 5 additions & 17 deletions src/Mono.Android/Android.Runtime/AndroidEnvironment.cs
Expand Up @@ -264,17 +264,14 @@ static void GetDisplayDPI (out float x_dpi, out float y_dpi)
//
static string GetDefaultTimeZone ()
{
IntPtr id = _monodroid_timezone_get_default_id ();
IntPtr id = RuntimeNativeMethods._monodroid_timezone_get_default_id ();
try {
return Marshal.PtrToStringAnsi (id)!;
} finally {
JNIEnv.monodroid_free (id);
RuntimeNativeMethods.monodroid_free (id);
}
}

[DllImport (AndroidRuntime.InternalDllName, CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr _monodroid_timezone_get_default_id ();

// This is invoked by
// mscorlib.dll!System.AndroidPlatform.GetDefaultSyncContext()
// DO NOT REMOVE
Expand All @@ -293,35 +290,26 @@ static string GetDefaultTimeZone ()
// These are invoked by
// System.dll!System.AndroidPlatform.getifaddrs
// DO NOT REMOVE
[DllImport (AndroidRuntime.InternalDllName, CallingConvention = CallingConvention.Cdecl)]
static extern int _monodroid_getifaddrs (out IntPtr ifap);

static int GetInterfaceAddresses (out IntPtr ifap)
{
return _monodroid_getifaddrs (out ifap);
return RuntimeNativeMethods._monodroid_getifaddrs (out ifap);
}

// These are invoked by
// System.dll!System.AndroidPlatform.freeifaddrs
// DO NOT REMOVE
[DllImport (AndroidRuntime.InternalDllName, CallingConvention = CallingConvention.Cdecl)]
static extern void _monodroid_freeifaddrs (IntPtr ifap);

static void FreeInterfaceAddresses (IntPtr ifap)
{
_monodroid_freeifaddrs (ifap);
RuntimeNativeMethods._monodroid_freeifaddrs (ifap);
}

[DllImport (AndroidRuntime.InternalDllName, CallingConvention = CallingConvention.Cdecl)]
static extern void _monodroid_detect_cpu_and_architecture (ref ushort built_for_cpu, ref ushort running_on_cpu, ref byte is64bit);

static void DetectCPUAndArchitecture (out ushort builtForCPU, out ushort runningOnCPU, out bool is64bit)
{
ushort built_for_cpu = 0;
ushort running_on_cpu = 0;
byte _is64bit = 0;

_monodroid_detect_cpu_and_architecture (ref built_for_cpu, ref running_on_cpu, ref _is64bit);
RuntimeNativeMethods._monodroid_detect_cpu_and_architecture (ref built_for_cpu, ref running_on_cpu, ref _is64bit);
builtForCPU = built_for_cpu;
runningOnCPU = running_on_cpu;
is64bit = _is64bit != 0;
Expand Down

0 comments on commit 8bc7a3e

Please sign in to comment.