From 5faa35a4effb117ae3643fc5cae303ad766c9d95 Mon Sep 17 00:00:00 2001 From: Jonathan Peppers Date: Tue, 4 Jan 2022 16:25:49 -0600 Subject: [PATCH 1/3] [Mono.Android] avoid System.Reflection.Emit usage for common calls `dotnet new android` calls `JNINativeWrapper.CreateDelegate()` twice, while `dotnet new maui` ends up calling it 58 times during startup. This code path calls System.Reflection.Emit to generate a `System.Delegate` at runtime to be invoked. After some thought, it is possible to "hard code" common delegate types and avoid SRE: 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) { bool filter = Debugger.IsAttached || !JNIEnv.PropagateExceptions; if (filter && JNIEnv.mono_unhandled_exception != null) { JNIEnv.mono_unhandled_exception (e); } AndroidEnvironment.UnhandledException (e); if (filter) throw; } }; return result; } // etc. `dotnet new maui`'s startup can be covered if we hardcoded: _JniMarshal_PP_V _JniMarshal_PPI_V _JniMarshal_PPL_L _JniMarshal_PPL_V _JniMarshal_PPL_Z _JniMarshal_PPII_V _JniMarshal_PPLI_V _JniMarshal_PPLL_V _JniMarshal_PPLL_Z _JniMarshal_PPIIL_V _JniMarshal_PPILL_V _JniMarshal_PPLIL_Z _JniMarshal_PPLLL_L _JniMarshal_PPLLL_Z _JniMarshal_PPIIII_V _JniMarshal_PPLLLL_V _JniMarshal_PPLIIII_V _JniMarshal_PPZIIII_V _JniMarshal_PPLIIIIIIII_V Then System.Reflection.Emit isn't used at all. Other changes: * `TypeManager.GetActivateHandler()` needs to use `_JniMarshal_PPLLLL_V` instead of `Action`, so the fast path can be used. * Added a log message for `debug.mono.log assembly`: Falling back to System.Reflection.Emit for delegate type '{delegateType}': {dlg.Method} * I was also able to remove `mono_unhandled_exception_method` from `JNINativeWrapper` as we already has this value in `JNIEnv`. ~~ Results ~~ Testing `dotnet new maui` with version: msbuild Xamarin.Android.sln -t:InstallMaui -bl -p:MauiVersion=6.0.200-preview.13.2536 A `Release` build on a Pixel 5 device, total startup time: Before: 01-21 11:58:39.030 1867 2226 I ActivityTaskManager: Displayed com.companyname.bar/crc6474063b540de74d1e.MainActivity: +1s83ms 01-21 11:58:41.297 1867 2226 I ActivityTaskManager: Displayed com.companyname.bar/crc6474063b540de74d1e.MainActivity: +1s127ms 01-21 11:58:43.429 1867 2226 I ActivityTaskManager: Displayed com.companyname.bar/crc6474063b540de74d1e.MainActivity: +1s68ms 01-21 11:58:45.702 1867 2226 I ActivityTaskManager: Displayed com.companyname.bar/crc6474063b540de74d1e.MainActivity: +1s113ms 01-21 11:58:47.906 1867 2226 I ActivityTaskManager: Displayed com.companyname.bar/crc6474063b540de74d1e.MainActivity: +1s125ms 01-21 11:58:50.082 1867 2226 I ActivityTaskManager: Displayed com.companyname.bar/crc6474063b540de74d1e.MainActivity: +1s92ms 01-21 11:58:52.297 1867 2226 I ActivityTaskManager: Displayed com.companyname.bar/crc6474063b540de74d1e.MainActivity: +1s133ms 01-21 11:58:54.465 1867 2226 I ActivityTaskManager: Displayed com.companyname.bar/crc6474063b540de74d1e.MainActivity: +1s102ms 01-21 11:58:56.673 1867 2226 I ActivityTaskManager: Displayed com.companyname.bar/crc6474063b540de74d1e.MainActivity: +1s126ms 01-21 11:58:58.848 1867 2226 I ActivityTaskManager: Displayed com.companyname.bar/crc6474063b540de74d1e.MainActivity: +1s94ms Average(ms): 1106.3 Std Err(ms): 6.91865433287267 Std Dev(ms): 21.8787060352704 After: 01-21 12:00:33.312 1867 2226 I ActivityTaskManager: Displayed com.companyname.bar/crc6474063b540de74d1e.MainActivity: +1s61ms 01-21 12:00:35.513 1867 2226 I ActivityTaskManager: Displayed com.companyname.bar/crc6474063b540de74d1e.MainActivity: +1s79ms 01-21 12:00:37.724 1867 2226 I ActivityTaskManager: Displayed com.companyname.bar/crc6474063b540de74d1e.MainActivity: +1s85ms 01-21 12:00:39.928 1867 2226 I ActivityTaskManager: Displayed com.companyname.bar/crc6474063b540de74d1e.MainActivity: +1s83ms 01-21 12:00:42.117 1867 2226 I ActivityTaskManager: Displayed com.companyname.bar/crc6474063b540de74d1e.MainActivity: +1s60ms 01-21 12:00:44.337 1867 2226 I ActivityTaskManager: Displayed com.companyname.bar/crc6474063b540de74d1e.MainActivity: +1s59ms 01-21 12:00:46.612 1867 2226 I ActivityTaskManager: Displayed com.companyname.bar/crc6474063b540de74d1e.MainActivity: +1s106ms 01-21 12:00:48.782 1867 2226 I ActivityTaskManager: Displayed com.companyname.bar/crc6474063b540de74d1e.MainActivity: +1s47ms 01-21 12:00:51.018 1867 2226 I ActivityTaskManager: Displayed com.companyname.bar/crc6474063b540de74d1e.MainActivity: +1s75ms 01-21 12:00:53.200 1867 2226 I ActivityTaskManager: Displayed com.companyname.bar/crc6474063b540de74d1e.MainActivity: +1s53ms Average(ms): 1070.8 Std Err(ms): 5.68584988272544 Std Dev(ms): 17.9802360632137 This might save ~35ms on average? If I time the message for one call, such as: 01-21 12:14:01.132 29819 29819 I monodroid-timing: Runtime.register: registering type `Microsoft.Maui.MauiApplication, Microsoft.Maui, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null` 01-21 12:14:01.150 29819 29819 I monodroid-timing: Runtime.register: end time; elapsed: 0s:17::794845 https://github.com/dotnet/maui/blob/bfba62ed796d3416c4fcaa7cfbea86dc8d5e04c2/src/Compatibility/ControlGallery/src/Android/MainApplication.cs The result is: Before: 01-21 13:21:22.261 9359 9359 I monodroid-timing: Runtime.register: end time; elapsed: 0s:23::868440 01-21 13:21:24.446 9424 9424 I monodroid-timing: Runtime.register: end time; elapsed: 0s:23::875159 01-21 13:21:26.639 9497 9497 I monodroid-timing: Runtime.register: end time; elapsed: 0s:23::829742 01-21 13:21:28.842 9570 9570 I monodroid-timing: Runtime.register: end time; elapsed: 0s:24::165211 01-21 13:21:31.021 9631 9631 I monodroid-timing: Runtime.register: end time; elapsed: 0s:23::976721 01-21 13:21:33.221 9697 9697 I monodroid-timing: Runtime.register: end time; elapsed: 0s:24::237034 01-21 13:21:35.418 9759 9759 I monodroid-timing: Runtime.register: end time; elapsed: 0s:23::857346 01-21 13:21:37.585 9821 9821 I monodroid-timing: Runtime.register: end time; elapsed: 0s:23::872138 01-21 13:21:39.805 9884 9884 I monodroid-timing: Runtime.register: end time; elapsed: 0s:23::840107 01-21 13:21:42.014 9952 9952 I monodroid-timing: Runtime.register: end time; elapsed: 0s:23::723805 Average(ms): 23.9245703 Std Err(ms): 0.0502830551065224 Std Dev(ms): 0.159008981848371 After: 01-21 13:22:28.004 10226 10226 I monodroid-timing: Runtime.register: end time; elapsed: 0s:18::12345 01-21 13:22:30.261 10298 10298 I monodroid-timing: Runtime.register: end time; elapsed: 0s:18::338022 01-21 13:22:32.443 10362 10362 I monodroid-timing: Runtime.register: end time; elapsed: 0s:18::56251 01-21 13:22:34.664 10427 10427 I monodroid-timing: Runtime.register: end time; elapsed: 0s:17::997397 01-21 13:22:36.902 10497 10497 I monodroid-timing: Runtime.register: end time; elapsed: 0s:17::787554 01-21 13:22:39.117 10563 10563 I monodroid-timing: Runtime.register: end time; elapsed: 0s:17::801772 01-21 13:22:41.306 10630 10630 I monodroid-timing: Runtime.register: end time; elapsed: 0s:18::28752 01-21 13:22:43.552 10695 10695 I monodroid-timing: Runtime.register: end time; elapsed: 0s:18::75522 01-21 13:22:45.761 10759 10759 I monodroid-timing: Runtime.register: end time; elapsed: 0s:17::958075 01-21 13:22:47.978 10823 10823 I monodroid-timing: Runtime.register: end time; elapsed: 0s:18::961773 Average(ms): 18.1017463 Std Err(ms): 0.107071213504746 Std Dev(ms): 0.338588906513177 Saving ~5.8ms for this one call. `.apk` size difference for `dotnet new android`: > apkdiff -f before.apk after.apk Size difference in bytes ([*1] apk1 only, [*2] apk2 only): + 3,390 assemblies/assemblies.blob + 54 assemblies/assemblies.x86_64.blob - 4 assemblies/assemblies.arm64_v8a.blob - 15 assemblies/assemblies.x86.blob - 65 assemblies/assemblies.armeabi_v7a.blob Summary: + 3,360 Other entries 0.03% (of 10,526,432) + 0 Dalvik executables 0.00% (of 7,816,392) + 0 Shared libraries 0.00% (of 18,414,404) + 4,096 Package size difference 0.02% (of 21,006,128) --- src/Mono.Android/Android.Runtime/JNIEnv.cs | 18 +- .../Android.Runtime/JNINativeWrapper.cs | 26 +- .../Android.Runtime/JNINativeWrapper.g.cs | 377 ++++++++++++++++++ .../Android.Runtime/JNINativeWrapper.g.tt | 68 ++++ src/Mono.Android/Java.Interop/TypeManager.cs | 7 +- src/Mono.Android/Mono.Android.csproj | 9 + .../BuildReleaseArm64SimpleLegacy.apkdesc | 22 +- 7 files changed, 492 insertions(+), 35 deletions(-) create mode 100644 src/Mono.Android/Android.Runtime/JNINativeWrapper.g.cs create mode 100644 src/Mono.Android/Android.Runtime/JNINativeWrapper.g.tt diff --git a/src/Mono.Android/Android.Runtime/JNIEnv.cs b/src/Mono.Android/Android.Runtime/JNIEnv.cs index f720fab843e..4814585bd7c 100644 --- a/src/Mono.Android/Android.Runtime/JNIEnv.cs +++ b/src/Mono.Android/Android.Runtime/JNIEnv.cs @@ -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; @@ -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); @@ -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; @@ -246,6 +246,7 @@ static void ManualJavaObjectDispose (Java.Lang.Object obj) #else // NETCOREAPP internal static Action mono_unhandled_exception = null!; #endif // NETCOREAPP + internal static MethodInfo? mono_unhandled_exception_method = null; #if !NETCOREAPP static Action AppDomain_DoUnhandledException = null!; @@ -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) Delegate.CreateDelegate (typeof(Action), mono_UnhandledException); + if (mono_unhandled_exception_method != null) + mono_unhandled_exception = (Action) Delegate.CreateDelegate (typeof(Action), mono_unhandled_exception_method); + } + if (mono_unhandled_exception_method == null && mono_unhandled_exception != null) { + mono_unhandled_exception_method = mono_unhandled_exception.Method; } #if !NETCOREAPP @@ -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)); } diff --git a/src/Mono.Android/Android.Runtime/JNINativeWrapper.cs b/src/Mono.Android/Android.Runtime/JNINativeWrapper.cs index 88b1e3b110b..90ed5f28ab9 100644 --- a/src/Mono.Android/Android.Runtime/JNINativeWrapper.cs +++ b/src/Mono.Android/Android.Runtime/JNINativeWrapper.cs @@ -5,9 +5,8 @@ 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; @@ -15,15 +14,7 @@ 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) @@ -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.Warn, LogCategories.Default, $"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]; @@ -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 { diff --git a/src/Mono.Android/Android.Runtime/JNINativeWrapper.g.cs b/src/Mono.Android/Android.Runtime/JNINativeWrapper.g.cs new file mode 100644 index 00000000000..029441832f5 --- /dev/null +++ b/src/Mono.Android/Android.Runtime/JNINativeWrapper.g.cs @@ -0,0 +1,377 @@ +using System; +using System.Diagnostics; + +namespace Android.Runtime +{ + public static partial class JNINativeWrapper + { + 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) { + bool filter = Debugger.IsAttached || !JNIEnv.PropagateExceptions; + if (filter && JNIEnv.mono_unhandled_exception != null) { + JNIEnv.mono_unhandled_exception (e); + } + AndroidEnvironment.UnhandledException (e); + if (filter) + throw; + + } + }; + 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) { + bool filter = Debugger.IsAttached || !JNIEnv.PropagateExceptions; + if (filter && JNIEnv.mono_unhandled_exception != null) { + JNIEnv.mono_unhandled_exception (e); + } + AndroidEnvironment.UnhandledException (e); + if (filter) + throw; + + } + }; + 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) { + bool filter = Debugger.IsAttached || !JNIEnv.PropagateExceptions; + if (filter && JNIEnv.mono_unhandled_exception != null) { + JNIEnv.mono_unhandled_exception (e); + } + AndroidEnvironment.UnhandledException (e); + if (filter) + throw; + 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) { + bool filter = Debugger.IsAttached || !JNIEnv.PropagateExceptions; + if (filter && JNIEnv.mono_unhandled_exception != null) { + JNIEnv.mono_unhandled_exception (e); + } + AndroidEnvironment.UnhandledException (e); + if (filter) + throw; + + } + }; + 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) { + bool filter = Debugger.IsAttached || !JNIEnv.PropagateExceptions; + if (filter && JNIEnv.mono_unhandled_exception != null) { + JNIEnv.mono_unhandled_exception (e); + } + AndroidEnvironment.UnhandledException (e); + if (filter) + throw; + 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) { + bool filter = Debugger.IsAttached || !JNIEnv.PropagateExceptions; + if (filter && JNIEnv.mono_unhandled_exception != null) { + JNIEnv.mono_unhandled_exception (e); + } + AndroidEnvironment.UnhandledException (e); + if (filter) + throw; + + } + }; + 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) { + bool filter = Debugger.IsAttached || !JNIEnv.PropagateExceptions; + if (filter && JNIEnv.mono_unhandled_exception != null) { + JNIEnv.mono_unhandled_exception (e); + } + AndroidEnvironment.UnhandledException (e); + if (filter) + throw; + + } + }; + 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) { + bool filter = Debugger.IsAttached || !JNIEnv.PropagateExceptions; + if (filter && JNIEnv.mono_unhandled_exception != null) { + JNIEnv.mono_unhandled_exception (e); + } + AndroidEnvironment.UnhandledException (e); + if (filter) + throw; + + } + }; + 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) { + bool filter = Debugger.IsAttached || !JNIEnv.PropagateExceptions; + if (filter && JNIEnv.mono_unhandled_exception != null) { + JNIEnv.mono_unhandled_exception (e); + } + AndroidEnvironment.UnhandledException (e); + if (filter) + throw; + 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) { + bool filter = Debugger.IsAttached || !JNIEnv.PropagateExceptions; + if (filter && JNIEnv.mono_unhandled_exception != null) { + JNIEnv.mono_unhandled_exception (e); + } + AndroidEnvironment.UnhandledException (e); + if (filter) + throw; + + } + }; + 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) { + bool filter = Debugger.IsAttached || !JNIEnv.PropagateExceptions; + if (filter && JNIEnv.mono_unhandled_exception != null) { + JNIEnv.mono_unhandled_exception (e); + } + AndroidEnvironment.UnhandledException (e); + if (filter) + throw; + + } + }; + 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) { + bool filter = Debugger.IsAttached || !JNIEnv.PropagateExceptions; + if (filter && JNIEnv.mono_unhandled_exception != null) { + JNIEnv.mono_unhandled_exception (e); + } + AndroidEnvironment.UnhandledException (e); + if (filter) + throw; + 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) { + bool filter = Debugger.IsAttached || !JNIEnv.PropagateExceptions; + if (filter && JNIEnv.mono_unhandled_exception != null) { + JNIEnv.mono_unhandled_exception (e); + } + AndroidEnvironment.UnhandledException (e); + if (filter) + throw; + 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) { + bool filter = Debugger.IsAttached || !JNIEnv.PropagateExceptions; + if (filter && JNIEnv.mono_unhandled_exception != null) { + JNIEnv.mono_unhandled_exception (e); + } + AndroidEnvironment.UnhandledException (e); + if (filter) + throw; + 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) { + bool filter = Debugger.IsAttached || !JNIEnv.PropagateExceptions; + if (filter && JNIEnv.mono_unhandled_exception != null) { + JNIEnv.mono_unhandled_exception (e); + } + AndroidEnvironment.UnhandledException (e); + if (filter) + throw; + + } + }; + 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) { + bool filter = Debugger.IsAttached || !JNIEnv.PropagateExceptions; + if (filter && JNIEnv.mono_unhandled_exception != null) { + JNIEnv.mono_unhandled_exception (e); + } + AndroidEnvironment.UnhandledException (e); + if (filter) + throw; + + } + }; + 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) { + bool filter = Debugger.IsAttached || !JNIEnv.PropagateExceptions; + if (filter && JNIEnv.mono_unhandled_exception != null) { + JNIEnv.mono_unhandled_exception (e); + } + AndroidEnvironment.UnhandledException (e); + if (filter) + throw; + + } + }; + 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) { + bool filter = Debugger.IsAttached || !JNIEnv.PropagateExceptions; + if (filter && JNIEnv.mono_unhandled_exception != null) { + JNIEnv.mono_unhandled_exception (e); + } + AndroidEnvironment.UnhandledException (e); + if (filter) + throw; + + } + }; + 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) { + bool filter = Debugger.IsAttached || !JNIEnv.PropagateExceptions; + if (filter && JNIEnv.mono_unhandled_exception != null) { + JNIEnv.mono_unhandled_exception (e); + } + AndroidEnvironment.UnhandledException (e); + if (filter) + throw; + + } + }; + return result; + } + default: + return null; + } + } + } +} diff --git a/src/Mono.Android/Android.Runtime/JNINativeWrapper.g.tt b/src/Mono.Android/Android.Runtime/JNINativeWrapper.g.tt new file mode 100644 index 00000000000..d8cc765c7c1 --- /dev/null +++ b/src/Mono.Android/Android.Runtime/JNINativeWrapper.g.tt @@ -0,0 +1,68 @@ +<#@ template debug="false" hostspecific="false" language="C#" #> +<#@ assembly name="System.Core" #> +<#@ import namespace="System.Collections.Generic" #> +<#@ output extension=".cs" #> +<# +var delegateTypes = new [] { + new { Type = "_JniMarshal_PP_V", Signature = "(jnienv, klazz)", Return = false }, + new { Type = "_JniMarshal_PPI_V", Signature = "(jnienv, klazz, p0)", Return = false }, + new { Type = "_JniMarshal_PPL_L", Signature = "(jnienv, klazz, p0)", Return = true }, + new { Type = "_JniMarshal_PPL_V", Signature = "(jnienv, klazz, p0)", Return = false }, + new { Type = "_JniMarshal_PPL_Z", Signature = "(jnienv, klazz, p0)", Return = true }, + new { Type = "_JniMarshal_PPII_V", Signature = "(jnienv, klazz, p0, p1)", Return = false }, + new { Type = "_JniMarshal_PPLI_V", Signature = "(jnienv, klazz, p0, p1)", Return = false }, + new { Type = "_JniMarshal_PPLL_V", Signature = "(jnienv, klazz, p0, p1)", Return = false }, + new { Type = "_JniMarshal_PPLL_Z", Signature = "(jnienv, klazz, p0, p1)", Return = true }, + new { Type = "_JniMarshal_PPIIL_V", Signature = "(jnienv, klazz, p0, p1, p2)", Return = false }, + new { Type = "_JniMarshal_PPILL_V", Signature = "(jnienv, klazz, p0, p1, p2)", Return = false }, + new { Type = "_JniMarshal_PPLIL_Z", Signature = "(jnienv, klazz, p0, p1, p2)", Return = true }, + new { Type = "_JniMarshal_PPLLL_L", Signature = "(jnienv, klazz, p0, p1, p2)", Return = true }, + new { Type = "_JniMarshal_PPLLL_Z", Signature = "(jnienv, klazz, p0, p1, p2)", Return = true }, + new { Type = "_JniMarshal_PPIIII_V", Signature = "(jnienv, klazz, p0, p1, p2, p3)", Return = false }, + new { Type = "_JniMarshal_PPLLLL_V", Signature = "(jnienv, klazz, p0, p1, p2, p3)", Return = false }, + new { Type = "_JniMarshal_PPLIIII_V", Signature = "(jnienv, klazz, p0, p1, p2, p3, p4)", Return = false }, + new { Type = "_JniMarshal_PPZIIII_V", Signature = "(jnienv, klazz, p0, p1, p2, p3, p4)", Return = false }, + new { Type = "_JniMarshal_PPLIIIIIIII_V", Signature = "(jnienv, klazz, p0, p1, p2, p3, p4, p5, p6, p7, p8)", Return = false }, +}; +#> +using System; +using System.Diagnostics; + +namespace Android.Runtime +{ + public static partial class JNINativeWrapper + { + private static Delegate CreateBuiltInDelegate (Delegate dlg, Type delegateType) + { + switch (delegateType.Name) { +<# +foreach (var info in delegateTypes) { +#> + case nameof (<#= info.Type #>): { + <#= info.Type #> callback = (<#= info.Type #>) Delegate.CreateDelegate (typeof (<#= info.Type #>), dlg.Target, dlg.Method); + <#= info.Type #> result = <#= info.Signature #> => { + JNIEnv.WaitForBridgeProcessing (); + try { + <#= info.Return ? "return " : "" #>callback <#= info.Signature #>; + } catch (Exception e) { + bool filter = Debugger.IsAttached || !JNIEnv.PropagateExceptions; + if (filter && JNIEnv.mono_unhandled_exception != null) { + JNIEnv.mono_unhandled_exception (e); + } + AndroidEnvironment.UnhandledException (e); + if (filter) + throw; + <#= info.Return ? "return default;" : "" #> + } + }; + return result; + } +<# +} +#> + default: + return null; + } + } + } +} diff --git a/src/Mono.Android/Java.Interop/TypeManager.cs b/src/Mono.Android/Java.Interop/TypeManager.cs index 5476bd15f29..9dbaed1c368 100644 --- a/src/Mono.Android/Java.Interop/TypeManager.cs +++ b/src/Mono.Android/Java.Interop/TypeManager.cs @@ -97,12 +97,11 @@ public int Compare (string x, string y) return mappings [i].Substring (c+1); } - static Action? cb_activate; + static _JniMarshal_PPLLLL_V? cb_activate; internal static Delegate GetActivateHandler () { if (cb_activate == null) - cb_activate = (Action) JNINativeWrapper.CreateDelegate ( - (Action) n_Activate); + cb_activate = (_JniMarshal_PPLLLL_V) JNINativeWrapper.CreateDelegate ((_JniMarshal_PPLLLL_V) n_Activate); return cb_activate; } @@ -220,7 +219,7 @@ static Exception CreateJavaLocationException () if (!JNIEnv.IsRunningOnDesktop) { // Miss message is logged in the native runtime - if (JNIEnv.LogTypemapMissStackTrace) + if (JNIEnv.LogAssemblyCategory) JNIEnv.LogTypemapTrace (new System.Diagnostics.StackTrace (true)); return null; } diff --git a/src/Mono.Android/Mono.Android.csproj b/src/Mono.Android/Mono.Android.csproj index 67be0aac176..41419fc4984 100644 --- a/src/Mono.Android/Mono.Android.csproj +++ b/src/Mono.Android/Mono.Android.csproj @@ -125,6 +125,10 @@ + + TextTemplatingFileGenerator + JNINativeWrapper.g.cs + @@ -241,6 +245,11 @@ + + True + True + JNINativeWrapper.g.tt + diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64SimpleLegacy.apkdesc b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64SimpleLegacy.apkdesc index ad0f9acde7f..21cfa18f851 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64SimpleLegacy.apkdesc +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64SimpleLegacy.apkdesc @@ -5,25 +5,25 @@ "Size": 2604 }, "assemblies/Java.Interop.dll": { - "Size": 67759 + "Size": 67924 }, "assemblies/Mono.Android.dll": { - "Size": 251399 + "Size": 255765 }, "assemblies/mscorlib.dll": { - "Size": 769324 + "Size": 769156 }, "assemblies/System.Core.dll": { - "Size": 28187 + "Size": 28199 }, "assemblies/System.dll": { - "Size": 9171 + "Size": 9180 }, "assemblies/UnnamedProject.dll": { - "Size": 2866 + "Size": 2880 }, "classes.dex": { - "Size": 345208 + "Size": 347796 }, "lib/arm64-v8a/libmono-btls-shared.so": { "Size": 1613872 @@ -32,16 +32,16 @@ "Size": 707024 }, "lib/arm64-v8a/libmonodroid.so": { - "Size": 286736 + "Size": 294736 }, "lib/arm64-v8a/libmonosgen-2.0.so": { - "Size": 4037584 + "Size": 4030000 }, "lib/arm64-v8a/libxa-internal-api.so": { "Size": 65624 }, "lib/arm64-v8a/libxamarin-app.so": { - "Size": 20032 + "Size": 20592 }, "META-INF/ANDROIDD.RSA": { "Size": 1213 @@ -74,5 +74,5 @@ "Size": 1724 } }, - "PackageSize": 3983060 + "PackageSize": 3991252 } \ No newline at end of file From a76034baaeb16faa7dee8cac07dbafabcfa4ed1c Mon Sep 17 00:00:00 2001 From: Jonathan Peppers Date: Wed, 26 Jan 2022 16:30:31 -0600 Subject: [PATCH 2/3] Update src/Mono.Android/Android.Runtime/JNINativeWrapper.cs Co-authored-by: Jonathan Pryor --- src/Mono.Android/Android.Runtime/JNINativeWrapper.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Mono.Android/Android.Runtime/JNINativeWrapper.cs b/src/Mono.Android/Android.Runtime/JNINativeWrapper.cs index 90ed5f28ab9..1d09ccf9772 100644 --- a/src/Mono.Android/Android.Runtime/JNINativeWrapper.cs +++ b/src/Mono.Android/Android.Runtime/JNINativeWrapper.cs @@ -42,7 +42,7 @@ public static Delegate CreateDelegate (Delegate dlg) return result; if (JNIEnv.LogAssemblyCategory) { - JNIEnv.monodroid_log (LogLevel.Warn, LogCategories.Default, $"Falling back to System.Reflection.Emit for delegate type '{delegateType}': {dlg.Method}"); + 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; From decce29992422333778f01c7044c9f38648e0251 Mon Sep 17 00:00:00 2001 From: Jonathan Peppers Date: Fri, 28 Jan 2022 12:41:00 -0600 Subject: [PATCH 3/3] Fix Debugger "break" with exception filter --- .../Android.Runtime/JNINativeWrapper.g.cs | 579 +++++++----------- .../Android.Runtime/JNINativeWrapper.g.tt | 17 +- 2 files changed, 247 insertions(+), 349 deletions(-) diff --git a/src/Mono.Android/Android.Runtime/JNINativeWrapper.g.cs b/src/Mono.Android/Android.Runtime/JNINativeWrapper.g.cs index 029441832f5..31dc9e1e5b8 100644 --- a/src/Mono.Android/Android.Runtime/JNINativeWrapper.g.cs +++ b/src/Mono.Android/Android.Runtime/JNINativeWrapper.g.cs @@ -5,370 +5,265 @@ 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) { - bool filter = Debugger.IsAttached || !JNIEnv.PropagateExceptions; - if (filter && JNIEnv.mono_unhandled_exception != null) { - JNIEnv.mono_unhandled_exception (e); - } - AndroidEnvironment.UnhandledException (e); - if (filter) - throw; - - } - }; - return result; - } + _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) { - bool filter = Debugger.IsAttached || !JNIEnv.PropagateExceptions; - if (filter && JNIEnv.mono_unhandled_exception != null) { - JNIEnv.mono_unhandled_exception (e); - } - AndroidEnvironment.UnhandledException (e); - if (filter) - throw; - - } - }; - return result; - } + _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) { - bool filter = Debugger.IsAttached || !JNIEnv.PropagateExceptions; - if (filter && JNIEnv.mono_unhandled_exception != null) { - JNIEnv.mono_unhandled_exception (e); - } - AndroidEnvironment.UnhandledException (e); - if (filter) - throw; - return default; - } - }; - return result; - } + _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) { - bool filter = Debugger.IsAttached || !JNIEnv.PropagateExceptions; - if (filter && JNIEnv.mono_unhandled_exception != null) { - JNIEnv.mono_unhandled_exception (e); - } - AndroidEnvironment.UnhandledException (e); - if (filter) - throw; - - } - }; - return result; - } + _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) { - bool filter = Debugger.IsAttached || !JNIEnv.PropagateExceptions; - if (filter && JNIEnv.mono_unhandled_exception != null) { - JNIEnv.mono_unhandled_exception (e); - } - AndroidEnvironment.UnhandledException (e); - if (filter) - throw; - return default; - } - }; - return result; - } + _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) { - bool filter = Debugger.IsAttached || !JNIEnv.PropagateExceptions; - if (filter && JNIEnv.mono_unhandled_exception != null) { - JNIEnv.mono_unhandled_exception (e); - } - AndroidEnvironment.UnhandledException (e); - if (filter) - throw; - - } - }; - return result; - } + _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) { - bool filter = Debugger.IsAttached || !JNIEnv.PropagateExceptions; - if (filter && JNIEnv.mono_unhandled_exception != null) { - JNIEnv.mono_unhandled_exception (e); - } - AndroidEnvironment.UnhandledException (e); - if (filter) - throw; - - } - }; - return result; - } + _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) { - bool filter = Debugger.IsAttached || !JNIEnv.PropagateExceptions; - if (filter && JNIEnv.mono_unhandled_exception != null) { - JNIEnv.mono_unhandled_exception (e); - } - AndroidEnvironment.UnhandledException (e); - if (filter) - throw; - - } - }; - return result; - } + _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) { - bool filter = Debugger.IsAttached || !JNIEnv.PropagateExceptions; - if (filter && JNIEnv.mono_unhandled_exception != null) { - JNIEnv.mono_unhandled_exception (e); - } - AndroidEnvironment.UnhandledException (e); - if (filter) - throw; - return default; - } - }; - return result; - } + _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) { - bool filter = Debugger.IsAttached || !JNIEnv.PropagateExceptions; - if (filter && JNIEnv.mono_unhandled_exception != null) { - JNIEnv.mono_unhandled_exception (e); - } - AndroidEnvironment.UnhandledException (e); - if (filter) - throw; - - } - }; - return result; - } + _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) { - bool filter = Debugger.IsAttached || !JNIEnv.PropagateExceptions; - if (filter && JNIEnv.mono_unhandled_exception != null) { - JNIEnv.mono_unhandled_exception (e); - } - AndroidEnvironment.UnhandledException (e); - if (filter) - throw; - - } - }; - return result; - } + _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) { - bool filter = Debugger.IsAttached || !JNIEnv.PropagateExceptions; - if (filter && JNIEnv.mono_unhandled_exception != null) { - JNIEnv.mono_unhandled_exception (e); - } - AndroidEnvironment.UnhandledException (e); - if (filter) - throw; - return default; - } - }; - return result; - } + _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) { - bool filter = Debugger.IsAttached || !JNIEnv.PropagateExceptions; - if (filter && JNIEnv.mono_unhandled_exception != null) { - JNIEnv.mono_unhandled_exception (e); - } - AndroidEnvironment.UnhandledException (e); - if (filter) - throw; - return default; - } - }; - return result; - } + _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) { - bool filter = Debugger.IsAttached || !JNIEnv.PropagateExceptions; - if (filter && JNIEnv.mono_unhandled_exception != null) { - JNIEnv.mono_unhandled_exception (e); - } - AndroidEnvironment.UnhandledException (e); - if (filter) - throw; - return default; - } - }; - return result; - } + _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) { - bool filter = Debugger.IsAttached || !JNIEnv.PropagateExceptions; - if (filter && JNIEnv.mono_unhandled_exception != null) { - JNIEnv.mono_unhandled_exception (e); - } - AndroidEnvironment.UnhandledException (e); - if (filter) - throw; - - } - }; - return result; - } + _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) { - bool filter = Debugger.IsAttached || !JNIEnv.PropagateExceptions; - if (filter && JNIEnv.mono_unhandled_exception != null) { - JNIEnv.mono_unhandled_exception (e); - } - AndroidEnvironment.UnhandledException (e); - if (filter) - throw; - - } - }; - return result; - } + _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) { - bool filter = Debugger.IsAttached || !JNIEnv.PropagateExceptions; - if (filter && JNIEnv.mono_unhandled_exception != null) { - JNIEnv.mono_unhandled_exception (e); - } - AndroidEnvironment.UnhandledException (e); - if (filter) - throw; - - } - }; - return result; - } + _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) { - bool filter = Debugger.IsAttached || !JNIEnv.PropagateExceptions; - if (filter && JNIEnv.mono_unhandled_exception != null) { - JNIEnv.mono_unhandled_exception (e); - } - AndroidEnvironment.UnhandledException (e); - if (filter) - throw; - - } - }; - return result; - } + _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) { - bool filter = Debugger.IsAttached || !JNIEnv.PropagateExceptions; - if (filter && JNIEnv.mono_unhandled_exception != null) { - JNIEnv.mono_unhandled_exception (e); - } - AndroidEnvironment.UnhandledException (e); - if (filter) - throw; - - } - }; - return result; - } + _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; } diff --git a/src/Mono.Android/Android.Runtime/JNINativeWrapper.g.tt b/src/Mono.Android/Android.Runtime/JNINativeWrapper.g.tt index d8cc765c7c1..d757c2fad5a 100644 --- a/src/Mono.Android/Android.Runtime/JNINativeWrapper.g.tt +++ b/src/Mono.Android/Android.Runtime/JNINativeWrapper.g.tt @@ -32,6 +32,15 @@ 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) { @@ -44,14 +53,8 @@ foreach (var info in delegateTypes) { JNIEnv.WaitForBridgeProcessing (); try { <#= info.Return ? "return " : "" #>callback <#= info.Signature #>; - } catch (Exception e) { - bool filter = Debugger.IsAttached || !JNIEnv.PropagateExceptions; - if (filter && JNIEnv.mono_unhandled_exception != null) { - JNIEnv.mono_unhandled_exception (e); - } + } catch (Exception e) when (_unhandled_exception (e)) { AndroidEnvironment.UnhandledException (e); - if (filter) - throw; <#= info.Return ? "return default;" : "" #> } };