Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/Mono.Android.Runtime/Mono.Android.Runtime.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -52,11 +52,11 @@
<ItemGroup>
<Compile Include="$(IntermediateOutputPath)AssemblyInfo.cs" />
<Compile Include="..\Mono.Android\Android.Runtime\AndroidRuntimeInternal.cs" />
<Compile Include="..\Mono.Android\Android.Runtime\DotNetRuntimeType.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="..\Mono.Android\Microsoft.Android.Runtime\RuntimeFeature.cs" />
<Compile Include="Android.Runtime\AndroidEnvironmentInternal.cs" />
</ItemGroup>

Expand Down
40 changes: 8 additions & 32 deletions src/Mono.Android/Android.Runtime/AndroidRuntimeInternal.cs
Original file line number Diff line number Diff line change
@@ -1,36 +1,10 @@
#if INSIDE_MONO_ANDROID_RUNTIME
using System;
using System.Reflection;
using Microsoft.Android.Runtime;

namespace Android.Runtime
{
// The existence of InternalRuntimeTypeHolder and DotNetRuntimeTypeConverter classes looks weird, but
// we must handle a weird situation. AndroidRuntimeInternal needs to know in its static constructor
// what is the current runtime type, but it cannot query JNIEnvInit.RuntimeType, since that type lives
// in the Mono.Android assembly, while AndroidRuntimeInternal lives in Mono.Android.Runtime and it cannot
// access JNIEnvInit and Mono.Android.Runtime doesn't reference Mono.Android but Mono.Android **does** reference
// Mono.Android.Runtime and has access to its internals.
//
// Mono.Android.Runtime, also, includes several source files from Mono.Android - **both** assemblies
// include the same source files. In case of the DotNetRuntimeType enum, this declares two distinct types - one
// in Mono.Android and another in Mono.Android.Runtime, and so if JNIEnvInit.Initialize were to try to set the
// `DotNetRuntimeType RuntimeType;` field/property in either of the classes below, we'd get a compilation error
// to the effect of it being unable to cast `Android.Runtime.DotNetRuntimeType` to `Android.Runtime.DotNetRuntimeType`,
// which is usually as clear as mud :)
//
// To solve this and not duplicate code, the InternalRuntimeTypeHolder class is introduced which acts as a proxy since
// the AndroidRuntimeInternal static constructor must know the runtime type and JNIEnvInit.Initialize takes care of it by
// calling `SetRuntimeType` below long before AndroidRuntimeInternal cctor is invoked.
public static class InternalRuntimeTypeHolder
{
internal static DotNetRuntimeType RuntimeType = DotNetRuntimeType.Unknown;

internal static void SetRuntimeType (uint runtimeType)
{
RuntimeType = DotNetRuntimeTypeConverter.Convert (runtimeType);
}
}

public static class AndroidRuntimeInternal
{
internal static readonly Action<Exception> mono_unhandled_exception;
Expand All @@ -41,11 +15,13 @@ public static class AndroidRuntimeInternal

static AndroidRuntimeInternal ()
{
mono_unhandled_exception = InternalRuntimeTypeHolder.RuntimeType switch {
DotNetRuntimeType.MonoVM => MonoUnhandledException,
DotNetRuntimeType.CoreCLR => CoreClrUnhandledException,
_ => throw new NotSupportedException ($"Internal error: runtime type {InternalRuntimeTypeHolder.RuntimeType} not supported")
};
if (RuntimeFeature.IsMonoRuntime) {
mono_unhandled_exception = MonoUnhandledException;
} else if (RuntimeFeature.IsCoreClrRuntime) {
mono_unhandled_exception = CoreClrUnhandledException;
} else {
throw new NotSupportedException ("Internal error: unknown runtime not supported");
}
}

static void CoreClrUnhandledException (Exception ex)
Expand Down
32 changes: 0 additions & 32 deletions src/Mono.Android/Android.Runtime/DotNetRuntimeType.cs

This file was deleted.

31 changes: 15 additions & 16 deletions src/Mono.Android/Android.Runtime/JNIEnv.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.IO;
using System.Reflection;
Expand All @@ -12,7 +13,7 @@

using Java.Interop;
using Java.Interop.Tools.TypeNameMappings;
using System.Diagnostics.CodeAnalysis;
using Microsoft.Android.Runtime;

namespace Android.Runtime {
public static partial class JNIEnv {
Expand Down Expand Up @@ -100,16 +101,12 @@ internal static void PropagateUncaughtException (IntPtr env, IntPtr javaThreadPt
Logger.Log (LogLevel.Info, "MonoDroid", "UNHANDLED EXCEPTION:");
Logger.Log (LogLevel.Info, "MonoDroid", javaException.ToString ());

switch (JNIEnvInit.RuntimeType) {
case DotNetRuntimeType.MonoVM:
MonoDroidUnhandledException (innerException ?? javaException);
break;
case DotNetRuntimeType.CoreCLR:
// TODO: what to do here?
break;

default:
throw new NotSupportedException ($"Internal error: runtime type {JNIEnvInit.RuntimeType} not supported");
if (RuntimeFeature.IsMonoRuntime) {
MonoDroidUnhandledException (innerException ?? javaException);
} else if (RuntimeFeature.IsCoreClrRuntime) {
// TODO: what to do here?
} else {
throw new NotSupportedException ("Internal error: unknown runtime not supported");
}
} catch (Exception e) {
Logger.Log (LogLevel.Error, "monodroid", "Exception thrown while raising AppDomain.UnhandledException event: " + e.ToString ());
Expand Down Expand Up @@ -453,11 +450,13 @@ static unsafe IntPtr monovm_typemap_managed_to_java (Type type, byte* mvidptr)

IntPtr ret;
fixed (byte* mvidptr = mvid_data) {
ret = JNIEnvInit.RuntimeType switch {
DotNetRuntimeType.MonoVM => monovm_typemap_managed_to_java (type, mvidptr),
DotNetRuntimeType.CoreCLR => RuntimeNativeMethods.clr_typemap_managed_to_java (type.FullName, (IntPtr)mvidptr),
_ => throw new NotSupportedException ($"Internal error: runtime type {JNIEnvInit.RuntimeType} not supported")
};
if (RuntimeFeature.IsMonoRuntime) {
ret = monovm_typemap_managed_to_java (type, mvidptr);
} else if (RuntimeFeature.IsCoreClrRuntime) {
ret = RuntimeNativeMethods.clr_typemap_managed_to_java (type.FullName, (IntPtr)mvidptr);
} else {
throw new NotSupportedException ("Internal error: unknown runtime not supported");
}
}

if (ret == IntPtr.Zero) {
Expand Down
23 changes: 11 additions & 12 deletions src/Mono.Android/Android.Runtime/JNIEnvInit.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ internal struct JnienvInitializeArgs {
public bool jniRemappingInUse;
public bool marshalMethodsEnabled;
public IntPtr grefGCUserPeerable;
public uint runtimeType;
public bool managedMarshalMethodsLookupEnabled;
}
#pragma warning restore 0649
Expand All @@ -50,8 +49,6 @@ internal struct JnienvInitializeArgs {

internal static JniRuntime? androidRuntime;

public static DotNetRuntimeType RuntimeType { get; private set; } = DotNetRuntimeType.Unknown;

[UnmanagedCallersOnly]
static unsafe void RegisterJniNatives (IntPtr typeName_ptr, int typeName_len, IntPtr jniClass, IntPtr methods_ptr, int methods_len)
{
Expand Down Expand Up @@ -91,9 +88,10 @@ internal static void InitializeJniRuntime (JniRuntime runtime)
[UnmanagedCallersOnly]
internal static unsafe void Initialize (JnienvInitializeArgs* args)
{
// This looks weird, see comments in RuntimeTypeInternal.cs
RuntimeType = DotNetRuntimeTypeConverter.Convert (args->runtimeType);
InternalRuntimeTypeHolder.SetRuntimeType (args->runtimeType);
// Should not be allowed
if (RuntimeFeature.IsMonoRuntime && RuntimeFeature.IsCoreClrRuntime) {
throw new NotSupportedException ("Internal error: both RuntimeFeature.IsMonoRuntime and RuntimeFeature.IsCoreClrRuntime are enabled");
}

IntPtr total_timing_sequence = IntPtr.Zero;
IntPtr partial_timing_sequence = IntPtr.Zero;
Expand All @@ -114,12 +112,13 @@ internal static unsafe void Initialize (JnienvInitializeArgs* args)
} else {
typeManager = new AndroidTypeManager (args->jniAddNativeMethodRegistrationAttributePresent != 0);
}
valueManager = RuntimeType switch
{
DotNetRuntimeType.MonoVM => new AndroidValueManager(),
DotNetRuntimeType.CoreCLR => ManagedValueManager.GetOrCreateInstance(),
_ => throw new NotSupportedException ($"No value manager for runtime type: {RuntimeType}"),
};
if (RuntimeFeature.IsMonoRuntime) {
valueManager = new AndroidValueManager ();
} else if (RuntimeFeature.IsCoreClrRuntime) {
valueManager = ManagedValueManager.GetOrCreateInstance ();
} else {
throw new NotSupportedException ("Internal error: unknown runtime not supported");
}
androidRuntime = new AndroidRuntime (
args->env,
args->javaVm,
Expand Down
13 changes: 8 additions & 5 deletions src/Mono.Android/Java.Interop/TypeManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
using Java.Interop.Tools.TypeNameMappings;

using Android.Runtime;
using Microsoft.Android.Runtime;

namespace Java.Interop {

Expand Down Expand Up @@ -267,11 +268,13 @@ static Type monovm_typemap_java_to_managed (string java_type_name)
return type;
}

type = JNIEnvInit.RuntimeType switch {
DotNetRuntimeType.MonoVM => monovm_typemap_java_to_managed (class_name),
DotNetRuntimeType.CoreCLR => clr_typemap_java_to_managed (class_name),
_ => throw new NotSupportedException ($"Internal error: runtime type {JNIEnvInit.RuntimeType} not supported")
};
if (RuntimeFeature.IsMonoRuntime) {
type = monovm_typemap_java_to_managed (class_name);
} else if (RuntimeFeature.IsCoreClrRuntime) {
type = clr_typemap_java_to_managed (class_name);
} else {
throw new NotSupportedException ("Internal error: unknown runtime not supported");
}

if (type != null) {
TypeManagerMapDictionaries.JniToManaged.Add (class_name, type);
Expand Down
14 changes: 13 additions & 1 deletion src/Mono.Android/Microsoft.Android.Runtime/RuntimeFeature.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,21 @@ namespace Microsoft.Android.Runtime;

static class RuntimeFeature
{
const bool ManagedTypeMapEnabledByDefault = false;
const bool IsMonoRuntimeEnabledByDefault = true;
const bool IsCoreClrRuntimeEnabledByDefault = false;

const string FeatureSwitchPrefix = "Microsoft.Android.Runtime.RuntimeFeature.";

[FeatureSwitchDefinition ($"{FeatureSwitchPrefix}{nameof (ManagedTypeMap)}")]
internal static bool ManagedTypeMap { get; } =
AppContext.TryGetSwitch ($"{FeatureSwitchPrefix}{nameof (ManagedTypeMap)}", out bool isEnabled) ? isEnabled : false;
AppContext.TryGetSwitch ($"{FeatureSwitchPrefix}{nameof (ManagedTypeMap)}", out bool isEnabled) ? isEnabled : ManagedTypeMapEnabledByDefault;

[FeatureSwitchDefinition ($"{FeatureSwitchPrefix}{nameof (IsMonoRuntime)}")]
internal static bool IsMonoRuntime { get; } =
AppContext.TryGetSwitch ($"{FeatureSwitchPrefix}{nameof (IsMonoRuntime)}", out bool isEnabled) ? isEnabled : IsMonoRuntimeEnabledByDefault;
Copy link
Member

Choose a reason for hiding this comment

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

I wonder if we should enforce that the feature switch is always set explicitly and throw if it isn't. I'm worried that we could introduce a regression and for example we would drop the Microsoft.Android.Runtime.RuntimeFeature.IsMonoRuntime on CoreCLR in the SDK and now both IsMonoRuntime and IsCoreClrRuntime would be true.

Copy link
Member Author

Choose a reason for hiding this comment

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

I'll add something that throws on startup if both are set to true.


[FeatureSwitchDefinition ($"{FeatureSwitchPrefix}{nameof (IsCoreClrRuntime)}")]
internal static bool IsCoreClrRuntime { get; } =
AppContext.TryGetSwitch ($"{FeatureSwitchPrefix}{nameof (IsCoreClrRuntime)}", out bool isEnabled) ? isEnabled : IsCoreClrRuntimeEnabledByDefault;
}
1 change: 0 additions & 1 deletion src/Mono.Android/Mono.Android.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,6 @@
<Compile Include="Android.Runtime\BoundExceptionType.cs" />
<Compile Include="Android.Runtime\CharSequence.cs" />
<Compile Include="Android.Runtime\CPUArchitecture.cs" />
<Compile Include="Android.Runtime\DotNetRuntimeType.cs" />
<Compile Include="Android.Runtime\Extensions.cs" />
<Compile Include="Android.Runtime\GeneratedEnumAttribute.cs" />
<Compile Include="Android.Runtime\IJavaObject.cs" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,18 @@ This file contains the CoreCLR-specific MSBuild logic for .NET for Android.
<AllowReadyToRunWithoutRuntimeIdentifier Condition=" '$(PublishReadyToRun)' == 'true' and '$(RuntimeIdentifiers)' != '' ">true</AllowReadyToRunWithoutRuntimeIdentifier>
</PropertyGroup>

<!-- Default feature switches -->
<ItemGroup>
<RuntimeHostConfigurationOption Include="Microsoft.Android.Runtime.RuntimeFeature.IsMonoRuntime"
Value="false"
Trim="true"
/>
<RuntimeHostConfigurationOption Include="Microsoft.Android.Runtime.RuntimeFeature.IsCoreClrRuntime"
Value="true"
Trim="true"
/>
</ItemGroup>

<Target Name="_CLRUseLocalRuntimePacks" AfterTargets="ResolveFrameworkReferences"
Condition=" '$(_CLRLocalRuntimePath)' != '' And '$(_AndroidRuntime)' == 'CoreCLR' ">
<PropertyGroup>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<!--
***********************************************************************************************
Microsoft.Android.Sdk.MonoVM.targets

This file contains the MonoVM-specific MSBuild logic for .NET for Android.
***********************************************************************************************
-->
<Project>

<!-- Default feature switches -->
<ItemGroup>
<RuntimeHostConfigurationOption Include="Microsoft.Android.Runtime.RuntimeFeature.IsMonoRuntime"
Value="true"
Trim="true"
/>
<RuntimeHostConfigurationOption Include="Microsoft.Android.Runtime.RuntimeFeature.IsCoreClrRuntime"
Value="false"
Trim="true"
/>
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,18 @@ This file contains the NativeAOT-specific MSBuild logic for .NET for Android.
<CompressSymbols>false</CompressSymbols>
</PropertyGroup>

<!-- Default feature switches -->
<ItemGroup>
<RuntimeHostConfigurationOption Include="Microsoft.Android.Runtime.RuntimeFeature.IsMonoRuntime"
Value="false"
Trim="true"
/>
<RuntimeHostConfigurationOption Include="Microsoft.Android.Runtime.RuntimeFeature.IsCoreClrRuntime"
Value="false"
Trim="true"
/>
</ItemGroup>

<!-- Make IlcCompile depend on the trimmer -->
<PropertyGroup>
<IlcCompileDependsOn>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@
<Import Project="Microsoft.Android.Sdk.DefaultProperties.targets" />
<Import Project="$(MSBuildThisFileDirectory)..\tools\Xamarin.Android.Common.Debugging.props"
Condition="Exists('$(MSBuildThisFileDirectory)..\tools\Xamarin.Android.Common.Debugging.props') And '$(DesignTimeBuild)' != 'true' "/>
<Import Project="Microsoft.Android.Sdk.CoreCLR.targets" Condition=" '$(_AndroidRuntime)' == 'CoreCLR' " />
<Import Project="Microsoft.Android.Sdk.NativeAOT.targets" Condition=" '$(_AndroidRuntime)' == 'NativeAOT' " />
<Import Project="Microsoft.Android.Sdk.$(_AndroidRuntime).targets" Condition=" '$(_AndroidRuntime)' != '' " />

</Project>
Loading