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
18 changes: 11 additions & 7 deletions src/Mono.Android/Android.Runtime/JNIEnv.cs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ public static partial class JNIEnv {
internal static bool PropagateExceptions;

internal static bool IsRunningOnDesktop;
internal static bool LogTypemapMissStackTrace;
internal static bool LogAssemblyCategory;

static AndroidRuntime? androidRuntime;
static BoundExceptionType BoundExceptionType;
Expand All @@ -67,7 +67,7 @@ public static partial class JNIEnv {
internal static AndroidValueManager? AndroidValueManager;

[DllImport (AndroidRuntime.InternalDllName, CallingConvention = CallingConvention.Cdecl)]
extern static void monodroid_log (LogLevel level, LogCategories category, string message);
internal extern static void monodroid_log (LogLevel level, LogCategories category, string message);

[DllImport (AndroidRuntime.InternalDllName, CallingConvention = CallingConvention.Cdecl)]
internal extern static IntPtr monodroid_timing_start (string? message);
Expand Down Expand Up @@ -149,7 +149,7 @@ internal static unsafe void Initialize (JnienvInitializeArgs* args)
partial_timing_sequence = monodroid_timing_start (null);
}

LogTypemapMissStackTrace = (args->logCategories & (uint)LogCategories.Assembly) != 0;
LogAssemblyCategory = (args->logCategories & (uint)LogCategories.Assembly) != 0;

gref_gc_threshold = args->grefGcThreshold;

Expand Down Expand Up @@ -246,6 +246,7 @@ static void ManualJavaObjectDispose (Java.Lang.Object obj)
#else // NETCOREAPP
internal static Action<Exception> mono_unhandled_exception = null!;
#endif // NETCOREAPP
internal static MethodInfo? mono_unhandled_exception_method = null;

#if !NETCOREAPP
static Action<AppDomain, UnhandledExceptionEventArgs> AppDomain_DoUnhandledException = null!;
Expand All @@ -254,10 +255,13 @@ static void ManualJavaObjectDispose (Java.Lang.Object obj)
static void Initialize ()
{
if (mono_unhandled_exception == null) {
var mono_UnhandledException = typeof (System.Diagnostics.Debugger)
mono_unhandled_exception_method = typeof (System.Diagnostics.Debugger)
.GetMethod ("Mono_UnhandledException", BindingFlags.NonPublic | BindingFlags.Static);
if (mono_UnhandledException != null)
mono_unhandled_exception = (Action<Exception>) Delegate.CreateDelegate (typeof(Action<Exception>), mono_UnhandledException);
if (mono_unhandled_exception_method != null)
mono_unhandled_exception = (Action<Exception>) Delegate.CreateDelegate (typeof(Action<Exception>), mono_unhandled_exception_method);
}
if (mono_unhandled_exception_method == null && mono_unhandled_exception != null) {
mono_unhandled_exception_method = mono_unhandled_exception.Method;
}

#if !NETCOREAPP
Expand Down Expand Up @@ -737,7 +741,7 @@ internal static void LogTypemapTrace (StackTrace st)
}

if (ret == IntPtr.Zero) {
if (LogTypemapMissStackTrace) {
if (LogAssemblyCategory) {
monodroid_log (LogLevel.Warn, LogCategories.Default, $"typemap: failed to map managed type to Java type: {type.AssemblyQualifiedName} (Module ID: {type.Module.ModuleVersionId}; Type token: {type.MetadataToken})");
LogTypemapTrace (new StackTrace (true));
}
Expand Down
26 changes: 13 additions & 13 deletions src/Mono.Android/Android.Runtime/JNINativeWrapper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,25 +5,16 @@
using System.Threading;

namespace Android.Runtime {
public static class JNINativeWrapper {
public static partial class JNINativeWrapper {

static MethodInfo? mono_unhandled_exception_method;
static MethodInfo? exception_handler_method;
static MethodInfo? wait_for_bridge_processing_method;

static void get_runtime_types ()
{
if (exception_handler_method != null)
return;
#if MONOANDROID1_0
mono_unhandled_exception_method = typeof (System.Diagnostics.Debugger).GetMethod (
"Mono_UnhandledException", BindingFlags.NonPublic | BindingFlags.Static);
if (mono_unhandled_exception_method == null)
AndroidEnvironment.FailFast ("Cannot find System.Diagnostics.Debugger.Mono_UnhandledException");
#endif
#if NETCOREAPP
mono_unhandled_exception_method = JNIEnv.mono_unhandled_exception.Method;
#endif // NETCOREAPP

exception_handler_method = typeof (AndroidEnvironment).GetMethod (
"UnhandledException", BindingFlags.NonPublic | BindingFlags.Static);
if (exception_handler_method == null)
Expand All @@ -45,6 +36,15 @@ public static Delegate CreateDelegate (Delegate dlg)

get_runtime_types ();

var delegateType = dlg.GetType ();
var result = CreateBuiltInDelegate (dlg, delegateType);
if (result != null)
return result;

if (JNIEnv.LogAssemblyCategory) {
JNIEnv.monodroid_log (LogLevel.Debug, LogCategories.Assembly, $"Falling back to System.Reflection.Emit for delegate type '{delegateType}': {dlg.Method}");
}

var ret_type = dlg.Method.ReturnType;
var parameters = dlg.Method.GetParameters ();
var param_types = new Type [parameters.Length];
Expand Down Expand Up @@ -73,10 +73,10 @@ public static Delegate CreateDelegate (Delegate dlg)
ig.Emit (OpCodes.Leave, label);

bool filter = Debugger.IsAttached || !JNIEnv.PropagateExceptions;
if (filter && mono_unhandled_exception_method != null) {
if (filter && JNIEnv.mono_unhandled_exception_method != null) {
ig.BeginExceptFilterBlock ();

ig.Emit (OpCodes.Call, mono_unhandled_exception_method);
ig.Emit (OpCodes.Call, JNIEnv.mono_unhandled_exception_method);
ig.Emit (OpCodes.Ldc_I4_1);
ig.BeginCatchBlock (null!);
} else {
Expand Down
272 changes: 272 additions & 0 deletions src/Mono.Android/Android.Runtime/JNINativeWrapper.g.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,272 @@
using System;
using System.Diagnostics;

namespace Android.Runtime
{
public static partial class JNINativeWrapper
{
static bool _unhandled_exception (Exception e)
{
if (Debugger.IsAttached || !JNIEnv.PropagateExceptions) {
JNIEnv.mono_unhandled_exception (e);
return false;
}
return true;
}

private static Delegate CreateBuiltInDelegate (Delegate dlg, Type delegateType)
{
switch (delegateType.Name) {
case nameof (_JniMarshal_PP_V): {
_JniMarshal_PP_V callback = (_JniMarshal_PP_V) Delegate.CreateDelegate (typeof (_JniMarshal_PP_V), dlg.Target, dlg.Method);
_JniMarshal_PP_V result = (jnienv, klazz) => {
JNIEnv.WaitForBridgeProcessing ();
try {
callback (jnienv, klazz);
} catch (Exception e) when (_unhandled_exception (e)) {
AndroidEnvironment.UnhandledException (e);

}
};
return result;
}
case nameof (_JniMarshal_PPI_V): {
_JniMarshal_PPI_V callback = (_JniMarshal_PPI_V) Delegate.CreateDelegate (typeof (_JniMarshal_PPI_V), dlg.Target, dlg.Method);
_JniMarshal_PPI_V result = (jnienv, klazz, p0) => {
JNIEnv.WaitForBridgeProcessing ();
try {
callback (jnienv, klazz, p0);
} catch (Exception e) when (_unhandled_exception (e)) {
AndroidEnvironment.UnhandledException (e);

}
};
return result;
}
case nameof (_JniMarshal_PPL_L): {
_JniMarshal_PPL_L callback = (_JniMarshal_PPL_L) Delegate.CreateDelegate (typeof (_JniMarshal_PPL_L), dlg.Target, dlg.Method);
_JniMarshal_PPL_L result = (jnienv, klazz, p0) => {
JNIEnv.WaitForBridgeProcessing ();
try {
return callback (jnienv, klazz, p0);
} catch (Exception e) when (_unhandled_exception (e)) {
AndroidEnvironment.UnhandledException (e);
return default;
}
};
return result;
}
case nameof (_JniMarshal_PPL_V): {
_JniMarshal_PPL_V callback = (_JniMarshal_PPL_V) Delegate.CreateDelegate (typeof (_JniMarshal_PPL_V), dlg.Target, dlg.Method);
_JniMarshal_PPL_V result = (jnienv, klazz, p0) => {
JNIEnv.WaitForBridgeProcessing ();
try {
callback (jnienv, klazz, p0);
} catch (Exception e) when (_unhandled_exception (e)) {
AndroidEnvironment.UnhandledException (e);

}
};
return result;
}
case nameof (_JniMarshal_PPL_Z): {
_JniMarshal_PPL_Z callback = (_JniMarshal_PPL_Z) Delegate.CreateDelegate (typeof (_JniMarshal_PPL_Z), dlg.Target, dlg.Method);
_JniMarshal_PPL_Z result = (jnienv, klazz, p0) => {
JNIEnv.WaitForBridgeProcessing ();
try {
return callback (jnienv, klazz, p0);
} catch (Exception e) when (_unhandled_exception (e)) {
AndroidEnvironment.UnhandledException (e);
return default;
}
};
return result;
}
case nameof (_JniMarshal_PPII_V): {
_JniMarshal_PPII_V callback = (_JniMarshal_PPII_V) Delegate.CreateDelegate (typeof (_JniMarshal_PPII_V), dlg.Target, dlg.Method);
_JniMarshal_PPII_V result = (jnienv, klazz, p0, p1) => {
JNIEnv.WaitForBridgeProcessing ();
try {
callback (jnienv, klazz, p0, p1);
} catch (Exception e) when (_unhandled_exception (e)) {
AndroidEnvironment.UnhandledException (e);

}
};
return result;
}
case nameof (_JniMarshal_PPLI_V): {
_JniMarshal_PPLI_V callback = (_JniMarshal_PPLI_V) Delegate.CreateDelegate (typeof (_JniMarshal_PPLI_V), dlg.Target, dlg.Method);
_JniMarshal_PPLI_V result = (jnienv, klazz, p0, p1) => {
JNIEnv.WaitForBridgeProcessing ();
try {
callback (jnienv, klazz, p0, p1);
} catch (Exception e) when (_unhandled_exception (e)) {
AndroidEnvironment.UnhandledException (e);

}
};
return result;
}
case nameof (_JniMarshal_PPLL_V): {
_JniMarshal_PPLL_V callback = (_JniMarshal_PPLL_V) Delegate.CreateDelegate (typeof (_JniMarshal_PPLL_V), dlg.Target, dlg.Method);
_JniMarshal_PPLL_V result = (jnienv, klazz, p0, p1) => {
JNIEnv.WaitForBridgeProcessing ();
try {
callback (jnienv, klazz, p0, p1);
} catch (Exception e) when (_unhandled_exception (e)) {
AndroidEnvironment.UnhandledException (e);

}
};
return result;
}
case nameof (_JniMarshal_PPLL_Z): {
_JniMarshal_PPLL_Z callback = (_JniMarshal_PPLL_Z) Delegate.CreateDelegate (typeof (_JniMarshal_PPLL_Z), dlg.Target, dlg.Method);
_JniMarshal_PPLL_Z result = (jnienv, klazz, p0, p1) => {
JNIEnv.WaitForBridgeProcessing ();
try {
return callback (jnienv, klazz, p0, p1);
} catch (Exception e) when (_unhandled_exception (e)) {
AndroidEnvironment.UnhandledException (e);
return default;
}
};
return result;
}
case nameof (_JniMarshal_PPIIL_V): {
_JniMarshal_PPIIL_V callback = (_JniMarshal_PPIIL_V) Delegate.CreateDelegate (typeof (_JniMarshal_PPIIL_V), dlg.Target, dlg.Method);
_JniMarshal_PPIIL_V result = (jnienv, klazz, p0, p1, p2) => {
JNIEnv.WaitForBridgeProcessing ();
try {
callback (jnienv, klazz, p0, p1, p2);
} catch (Exception e) when (_unhandled_exception (e)) {
AndroidEnvironment.UnhandledException (e);

}
};
return result;
}
case nameof (_JniMarshal_PPILL_V): {
_JniMarshal_PPILL_V callback = (_JniMarshal_PPILL_V) Delegate.CreateDelegate (typeof (_JniMarshal_PPILL_V), dlg.Target, dlg.Method);
_JniMarshal_PPILL_V result = (jnienv, klazz, p0, p1, p2) => {
JNIEnv.WaitForBridgeProcessing ();
try {
callback (jnienv, klazz, p0, p1, p2);
} catch (Exception e) when (_unhandled_exception (e)) {
AndroidEnvironment.UnhandledException (e);

}
};
return result;
}
case nameof (_JniMarshal_PPLIL_Z): {
_JniMarshal_PPLIL_Z callback = (_JniMarshal_PPLIL_Z) Delegate.CreateDelegate (typeof (_JniMarshal_PPLIL_Z), dlg.Target, dlg.Method);
_JniMarshal_PPLIL_Z result = (jnienv, klazz, p0, p1, p2) => {
JNIEnv.WaitForBridgeProcessing ();
try {
return callback (jnienv, klazz, p0, p1, p2);
} catch (Exception e) when (_unhandled_exception (e)) {
AndroidEnvironment.UnhandledException (e);
return default;
}
};
return result;
}
case nameof (_JniMarshal_PPLLL_L): {
_JniMarshal_PPLLL_L callback = (_JniMarshal_PPLLL_L) Delegate.CreateDelegate (typeof (_JniMarshal_PPLLL_L), dlg.Target, dlg.Method);
_JniMarshal_PPLLL_L result = (jnienv, klazz, p0, p1, p2) => {
JNIEnv.WaitForBridgeProcessing ();
try {
return callback (jnienv, klazz, p0, p1, p2);
} catch (Exception e) when (_unhandled_exception (e)) {
AndroidEnvironment.UnhandledException (e);
return default;
}
};
return result;
}
case nameof (_JniMarshal_PPLLL_Z): {
_JniMarshal_PPLLL_Z callback = (_JniMarshal_PPLLL_Z) Delegate.CreateDelegate (typeof (_JniMarshal_PPLLL_Z), dlg.Target, dlg.Method);
_JniMarshal_PPLLL_Z result = (jnienv, klazz, p0, p1, p2) => {
JNIEnv.WaitForBridgeProcessing ();
try {
return callback (jnienv, klazz, p0, p1, p2);
} catch (Exception e) when (_unhandled_exception (e)) {
AndroidEnvironment.UnhandledException (e);
return default;
}
};
return result;
}
case nameof (_JniMarshal_PPIIII_V): {
_JniMarshal_PPIIII_V callback = (_JniMarshal_PPIIII_V) Delegate.CreateDelegate (typeof (_JniMarshal_PPIIII_V), dlg.Target, dlg.Method);
_JniMarshal_PPIIII_V result = (jnienv, klazz, p0, p1, p2, p3) => {
JNIEnv.WaitForBridgeProcessing ();
try {
callback (jnienv, klazz, p0, p1, p2, p3);
} catch (Exception e) when (_unhandled_exception (e)) {
AndroidEnvironment.UnhandledException (e);

}
};
return result;
}
case nameof (_JniMarshal_PPLLLL_V): {
_JniMarshal_PPLLLL_V callback = (_JniMarshal_PPLLLL_V) Delegate.CreateDelegate (typeof (_JniMarshal_PPLLLL_V), dlg.Target, dlg.Method);
_JniMarshal_PPLLLL_V result = (jnienv, klazz, p0, p1, p2, p3) => {
JNIEnv.WaitForBridgeProcessing ();
try {
callback (jnienv, klazz, p0, p1, p2, p3);
} catch (Exception e) when (_unhandled_exception (e)) {
AndroidEnvironment.UnhandledException (e);

}
};
return result;
}
case nameof (_JniMarshal_PPLIIII_V): {
_JniMarshal_PPLIIII_V callback = (_JniMarshal_PPLIIII_V) Delegate.CreateDelegate (typeof (_JniMarshal_PPLIIII_V), dlg.Target, dlg.Method);
_JniMarshal_PPLIIII_V result = (jnienv, klazz, p0, p1, p2, p3, p4) => {
JNIEnv.WaitForBridgeProcessing ();
try {
callback (jnienv, klazz, p0, p1, p2, p3, p4);
} catch (Exception e) when (_unhandled_exception (e)) {
AndroidEnvironment.UnhandledException (e);

}
};
return result;
}
case nameof (_JniMarshal_PPZIIII_V): {
_JniMarshal_PPZIIII_V callback = (_JniMarshal_PPZIIII_V) Delegate.CreateDelegate (typeof (_JniMarshal_PPZIIII_V), dlg.Target, dlg.Method);
_JniMarshal_PPZIIII_V result = (jnienv, klazz, p0, p1, p2, p3, p4) => {
JNIEnv.WaitForBridgeProcessing ();
try {
callback (jnienv, klazz, p0, p1, p2, p3, p4);
} catch (Exception e) when (_unhandled_exception (e)) {
AndroidEnvironment.UnhandledException (e);

}
};
return result;
}
case nameof (_JniMarshal_PPLIIIIIIII_V): {
_JniMarshal_PPLIIIIIIII_V callback = (_JniMarshal_PPLIIIIIIII_V) Delegate.CreateDelegate (typeof (_JniMarshal_PPLIIIIIIII_V), dlg.Target, dlg.Method);
_JniMarshal_PPLIIIIIIII_V result = (jnienv, klazz, p0, p1, p2, p3, p4, p5, p6, p7, p8) => {
JNIEnv.WaitForBridgeProcessing ();
try {
callback (jnienv, klazz, p0, p1, p2, p3, p4, p5, p6, p7, p8);
} catch (Exception e) when (_unhandled_exception (e)) {
AndroidEnvironment.UnhandledException (e);

}
};
return result;
}
default:
return null;
}
}
}
}
Loading