diff --git a/.external b/.external index 4860877f91c..01e4987437b 100644 --- a/.external +++ b/.external @@ -1,2 +1,2 @@ -xamarin/monodroid:main@2e93b630e47701dae56f426fe5934846d571832b +xamarin/monodroid:main@dade1f497271f3ae5ceb1fe8c6c672b399a369ec mono/mono:2020-02@c66141a8c7ba2566c578c2dd012b2b723e006213 diff --git a/.gitmodules b/.gitmodules index 3fda7ea93db..03f994fd0a8 100644 --- a/.gitmodules +++ b/.gitmodules @@ -35,6 +35,10 @@ url = https://github.com/Guardsquare/proguard.git branch = master ignore = dirty +[submodule "external/robin-map"] + path = external/robin-map + url = https://github.com/Tessil/robin-map.git + branch = master [submodule "external/sqlite"] path = external/sqlite url = https://github.com/xamarin/sqlite.git diff --git a/Configuration.props b/Configuration.props index 1ac20529783..5e87a5827f3 100644 --- a/Configuration.props +++ b/Configuration.props @@ -75,8 +75,11 @@ $(AndroidToolchainDirectory)\dotnet\ $(DotNetPreviewPath)dotnet + 6.0.100 $(DotNetPreviewVersionBand)-preview.1.21109.8 + + 6.0.0-preview.2.21108.2 6.0.0 $(ILLinkVersionBand)-alpha.1.21109.1 $(AndroidToolchainDirectory)\wix\ diff --git a/ThirdPartyNotices.txt b/ThirdPartyNotices.txt index 31a8d5b57b0..d84d5f7a3e8 100644 --- a/ThirdPartyNotices.txt +++ b/ThirdPartyNotices.txt @@ -15,6 +15,7 @@ The attached notices are provided for information only. 2. bazelbuild/bazel (https://github.com/bazelbuild/bazel/) 3. force-net/crc32.net (https://github.com/force-net/Crc32.NET) 4. nunit/nunitlite (https://github.com/nunit/nunitlite/) +5. tessil/robin-map (https://github.com/Tessil/robin-map) %% android/platform/tools/base NOTICES AND INFORMATION BEGIN HERE ================================================================= @@ -487,3 +488,31 @@ THE SOFTWARE. ===================================================== END OF nunit/nunitlite NOTICES AND INFORMATION +%% tessil/robin-map NOTICES AND INFORMATION BEGIN HERE +====================================================== +MIT License + +Copyright (c) 2017 Thibaut Goetghebuer-Planchon + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +====================================================== +END OF tessil/robin-map NOTICES AND INFORMATION + diff --git a/build-tools/create-packs/Directory.Build.targets b/build-tools/create-packs/Directory.Build.targets index 173ccd7ed0a..43efa9ab75a 100644 --- a/build-tools/create-packs/Directory.Build.targets +++ b/build-tools/create-packs/Directory.Build.targets @@ -77,10 +77,10 @@ - - - - + + + + diff --git a/build-tools/create-packs/Microsoft.Android.Runtime.proj b/build-tools/create-packs/Microsoft.Android.Runtime.proj index 2e89e21a009..cdf18885614 100644 --- a/build-tools/create-packs/Microsoft.Android.Runtime.proj +++ b/build-tools/create-packs/Microsoft.Android.Runtime.proj @@ -11,7 +11,7 @@ projects that use the Microsoft.Android framework in .NET 5. android-arm64 - arm64-v8a + arm64-v8a-net6 Microsoft.Android.Runtime.$(AndroidRID) Microsoft.Android runtime components. Please do not reference directly. <_AndroidRuntimePackAssemblyPath>runtimes\$(AndroidRID)\lib\net6.0 @@ -39,7 +39,6 @@ projects that use the Microsoft.Android framework in .NET 5. <_AndroidRuntimePackAssemblies Include="$(_MonoAndroidNETOutputDir)Mono.Android.Export.dll" /> <_AndroidRuntimePackAssets Include="$(XAInstallPrefix)xbuild\Xamarin\Android\lib\$(AndroidABI)\libmono-android.debug.so" /> <_AndroidRuntimePackAssets Include="$(XAInstallPrefix)xbuild\Xamarin\Android\lib\$(AndroidABI)\libmono-android.release.so" /> - <_AndroidRuntimePackAssets Include="$(XAInstallPrefix)xbuild\Xamarin\Android\lib\$(AndroidABI)\libxa-internal-api.so" /> <_AndroidRuntimePackAssets Include="$(XAInstallPrefix)xbuild\Xamarin\Android\lib\$(AndroidABI)\libxamarin-debug-app-helper.so" /> diff --git a/build-tools/create-pkg/create-pkg.targets b/build-tools/create-pkg/create-pkg.targets index e9d24dc0b0a..bdd498a5616 100644 --- a/build-tools/create-pkg/create-pkg.targets +++ b/build-tools/create-pkg/create-pkg.targets @@ -27,6 +27,10 @@ $(XAFrameworkDir)\lib\xamarin.android\xbuild-frameworks\MonoAndroid + + + + Microsoft/Framework/MonoAndroid/$([System.IO.Path]::GetDirectoryName(%(RelativePath))) + + Xamarin/Android/$([System.IO.Path]::GetDirectoryName(%(RelativePath))) diff --git a/build-tools/installers/create-installers.targets b/build-tools/installers/create-installers.targets index ea061103c1a..51f3f728e0f 100644 --- a/build-tools/installers/create-installers.targets +++ b/build-tools/installers/create-installers.targets @@ -227,10 +227,14 @@ <_MSBuildFiles Include="$(MSBuildSrcDir)\startup-xf.aotprofile" /> <_MSBuildFiles Include="$(MSBuildSrcDir)\r8.jar" /> <_MSBuildFiles Include="$(MSBuildSrcDir)\bundletool.jar" ExcludeFromAndroidNETSdk="true" /> - <_MSBuildFiles Include="$(MSBuildSrcDir)\java_runtime.jar" /> - <_MSBuildFiles Include="$(MSBuildSrcDir)\java_runtime_fastdev.jar" /> - <_MSBuildFiles Include="$(MSBuildSrcDir)\java_runtime.dex" /> - <_MSBuildFiles Include="$(MSBuildSrcDir)\java_runtime_fastdev.dex" /> + <_MSBuildFiles Include="$(MSBuildSrcDir)\java_runtime.jar" ExcludeFromAndroidNETSdk="true" /> + <_MSBuildFiles Include="$(MSBuildSrcDir)\java_runtime_fastdev.jar" ExcludeFromAndroidNETSdk="true" /> + <_MSBuildFiles Include="$(MSBuildSrcDir)\java_runtime.dex" ExcludeFromAndroidNETSdk="true" /> + <_MSBuildFiles Include="$(MSBuildSrcDir)\java_runtime_fastdev.dex" ExcludeFromAndroidNETSdk="true" /> + <_MSBuildFiles Include="$(MSBuildSrcDir)\java_runtime_net6.jar" ExcludeFromLegacy="true" /> + <_MSBuildFiles Include="$(MSBuildSrcDir)\java_runtime_fastdev_net6.jar" ExcludeFromLegacy="true" /> + <_MSBuildFiles Include="$(MSBuildSrcDir)\java_runtime_net6.dex" ExcludeFromLegacy="true" /> + <_MSBuildFiles Include="$(MSBuildSrcDir)\java_runtime_fastdev_net6.dex" ExcludeFromLegacy="true" /> <_MSBuildFiles Include="$(MSBuildSrcDir)\manifestmerger.jar" /> <_MSBuildFiles Include="$(MSBuildSrcDir)\protobuf-net.dll" /> <_MSBuildFiles Include="$(MSBuildSrcDir)\SgmlReaderDll.dll" /> diff --git a/build-tools/scripts/Ndk.projitems.in b/build-tools/scripts/Ndk.projitems.in index 14a9400db15..8f1971136d4 100644 --- a/build-tools/scripts/Ndk.projitems.in +++ b/build-tools/scripts/Ndk.projitems.in @@ -3,9 +3,13 @@ @NDK_RELEASE@ @NDK_ARMEABI_V7_API@ + @NDK_ARMEABI_V7_API_NET6@ @NDK_ARM64_V8A_API@ + @NDK_ARM64_V8A_API_NET6@ @NDK_X86_API@ + @NDK_X86_API_NET6@ @NDK_X86_64_API@ + @NDK_X86_64_API_NET6@ @@ -13,24 +17,28 @@ Include="armeabi-v7a" Condition=" $(AndroidSupportedTargetJitAbisForConditionalChecks.Contains (':armeabi-v7a:')) "> $(AndroidNdkApiLevel_ArmV7a) + $(AndroidNdkApiLevel_ArmV7a_NET6) $(AndroidNdkApiLevel_ArmV8a) + $(AndroidNdkApiLevel_ArmV8a_NET6) $(AndroidNdkApiLevel_X86) + $(AndroidNdkApiLevel_X86_NET6) $(AndroidNdkApiLevel_X86_64) + $(AndroidNdkApiLevel_X86_64_NET6) diff --git a/build-tools/scripts/xa_build_configuration.cmake.in b/build-tools/scripts/xa_build_configuration.cmake.in new file mode 100644 index 00000000000..ad6da1b812a --- /dev/null +++ b/build-tools/scripts/xa_build_configuration.cmake.in @@ -0,0 +1,4 @@ +set(NETCORE_APP_RUNTIME_DIR_ARM "@NETCORE_APP_RUNTIME_ANDROID_ARM@") +set(NETCORE_APP_RUNTIME_DIR_ARM64 "@NETCORE_APP_RUNTIME_ANDROID_ARM64@") +set(NETCORE_APP_RUNTIME_DIR_X86 "@NETCORE_APP_RUNTIME_ANDROID_X86@") +set(NETCORE_APP_RUNTIME_DIR_X86_64 "@NETCORE_APP_RUNTIME_ANDROID_X86_64@") diff --git a/build-tools/xaprepare/xaprepare/Application/GeneratedMonodroidCmakeFiles.cs b/build-tools/xaprepare/xaprepare/Application/GeneratedMonodroidCmakeFiles.cs index 94d3af6553e..fa1b0647f6b 100644 --- a/build-tools/xaprepare/xaprepare/Application/GeneratedMonodroidCmakeFiles.cs +++ b/build-tools/xaprepare/xaprepare/Application/GeneratedMonodroidCmakeFiles.cs @@ -40,16 +40,20 @@ public override void Generate (Context context) static readonly Dictionary ApiLevelVariableNames = new Dictionary (StringComparer.Ordinal) { { AbiNames.TargetJit.AndroidArmV7a, "NDK_LEGACY_API_ARMV7A" }, + { BuildAndroidPlatforms.AndroidArmV7a_NET6, "NDK_NET6_API_ARMV7A" }, { AbiNames.TargetJit.AndroidArmV8a, "NDK_LEGACY_API_ARMV8A" }, + { BuildAndroidPlatforms.AndroidArmV8a_NET6, "NDK_NET6_API_ARMV8A" }, { AbiNames.TargetJit.AndroidX86, "NDK_LEGACY_API_X86" }, + { BuildAndroidPlatforms.AndroidX86_NET6, "NDK_NET6_API_X86" }, { AbiNames.TargetJit.AndroidX86_64, "NDK_LEGACY_API_X86_64" }, + { BuildAndroidPlatforms.AndroidX86_64_NET6, "NDK_NET6_API_X86_64" }, }; static readonly Dictionary JitAbis = new Dictionary (StringComparer.Ordinal) { - { AbiNames.TargetJit.AndroidArmV7a, String.Empty }, - { AbiNames.TargetJit.AndroidArmV8a, String.Empty }, - { AbiNames.TargetJit.AndroidX86, String.Empty }, - { AbiNames.TargetJit.AndroidX86_64, String.Empty }, + { AbiNames.TargetJit.AndroidArmV7a, BuildAndroidPlatforms.AndroidArmV7a_NET6 }, + { AbiNames.TargetJit.AndroidArmV8a, BuildAndroidPlatforms.AndroidArmV8a_NET6 }, + { AbiNames.TargetJit.AndroidX86, BuildAndroidPlatforms.AndroidX86_NET6 }, + { AbiNames.TargetJit.AndroidX86_64, BuildAndroidPlatforms.AndroidX86_64_NET6 }, }; static readonly Dictionary HostAbis = new Dictionary (StringComparer.Ordinal) { @@ -107,9 +111,13 @@ void GenerateShellConfig (Context context, StreamWriter sw) sw.WriteLine (); WriteApiLevelVariable (AbiNames.TargetJit.AndroidArmV7a); + WriteApiLevelVariable (BuildAndroidPlatforms.AndroidArmV7a_NET6); WriteApiLevelVariable (AbiNames.TargetJit.AndroidArmV8a); + WriteApiLevelVariable (BuildAndroidPlatforms.AndroidArmV8a_NET6); WriteApiLevelVariable (AbiNames.TargetJit.AndroidX86); + WriteApiLevelVariable (BuildAndroidPlatforms.AndroidX86_NET6); WriteApiLevelVariable (AbiNames.TargetJit.AndroidX86_64); + WriteApiLevelVariable (BuildAndroidPlatforms.AndroidX86_64_NET6); sw.WriteLine (); string indent = "\t"; @@ -240,8 +248,8 @@ void WriteShellRuntimeCommand (StreamWriter sw, Dictionary abis, foreach (var kvp in abis) { string abi = kvp.Key; - string apiLevelVarName = kvp.Key; - string outputDirName = abi; + string apiLevelVarName = command.IsNet6 ? kvp.Value : kvp.Key; + string outputDirName = command.IsNet6 ? $"{abi}-net6" : abi; string isMxe = "no"; string mxeBitness = String.Empty; bool forMxe = false; @@ -353,7 +361,6 @@ void GenerateMonodroidTargets (Context context, StreamWriter sw) { "@NATIVE_API_LEVEL@", "" }, { "@ABI@", "%(AndroidSupportedTargetJitAbi.Identity)" }, { "@OUTPUT_DIRECTORY@", "" }, - }; var hostRuntimeReplacements = new Dictionary (StringComparer.Ordinal) { @@ -419,12 +426,13 @@ string EnsureRequired (string name, string v) void WriteMSBuildConfigureAndroidRuntimeCommands (StreamWriter sw, string indent, CmakeBuilds.RuntimeCommand command, Dictionary replacements) { const string LegacyOutputDirectory = "$(OutputPath)%(AndroidSupportedTargetJitAbi.Identity)"; + const string Net6OutputDirectory = LegacyOutputDirectory + "-net6"; WriteMSBuildConfigureRuntimeCommands ( sw, indent, $"$(IntermediateOutputPath)%(AndroidSupportedTargetJitAbi.Identity)-{command.Suffix}", - LegacyOutputDirectory, + command.IsNet6 ? Net6OutputDirectory : LegacyOutputDirectory, "@(AndroidSupportedTargetJitAbi)", CmakeBuilds.ConfigureAndroidRuntimeCommandsCommonFlags, command, diff --git a/build-tools/xaprepare/xaprepare/ConfigAndData/BuildAndroidPlatforms.cs b/build-tools/xaprepare/xaprepare/ConfigAndData/BuildAndroidPlatforms.cs index cb1c4b41a56..4567610119a 100644 --- a/build-tools/xaprepare/xaprepare/ConfigAndData/BuildAndroidPlatforms.cs +++ b/build-tools/xaprepare/xaprepare/ConfigAndData/BuildAndroidPlatforms.cs @@ -42,11 +42,17 @@ class BuildAndroidPlatforms new AndroidPlatform (apiName: "S", apiLevel: 31, platformID: "S", include: "v11.0.99", framework: "v11.0.99", stable: false), }; + // These are here until we can drop "legacy" targets and use only .NET6+ + public const string AndroidArmV7a_NET6 = AbiNames.TargetJit.AndroidArmV7a + "_NET6"; + public const string AndroidArmV8a_NET6 = AbiNames.TargetJit.AndroidArmV8a + "_NET6"; + public const string AndroidX86_NET6 = AbiNames.TargetJit.AndroidX86 + "_NET6"; + public const string AndroidX86_64_NET6 = AbiNames.TargetJit.AndroidX86_64 + "_NET6"; + public static readonly Dictionary NdkMinimumAPI = new Dictionary { - { AbiNames.TargetJit.AndroidArmV7a, 16 }, - { AbiNames.TargetJit.AndroidArmV8a, 21 }, - { AbiNames.TargetJit.AndroidX86, 16 }, - { AbiNames.TargetJit.AndroidX86_64, 21 }, + { AbiNames.TargetJit.AndroidArmV7a, 16 }, { AndroidArmV7a_NET6, 21 }, + { AbiNames.TargetJit.AndroidArmV8a, 21 }, { AndroidArmV8a_NET6, 21 }, + { AbiNames.TargetJit.AndroidX86, 16 }, { AndroidX86_NET6, 21 }, + { AbiNames.TargetJit.AndroidX86_64, 21 }, { AndroidX86_64_NET6, 21 }, }; } } diff --git a/build-tools/xaprepare/xaprepare/ConfigAndData/CmakeBuilds.cs b/build-tools/xaprepare/xaprepare/ConfigAndData/CmakeBuilds.cs index 4b5a247e460..d3b03f10470 100644 --- a/build-tools/xaprepare/xaprepare/ConfigAndData/CmakeBuilds.cs +++ b/build-tools/xaprepare/xaprepare/ConfigAndData/CmakeBuilds.cs @@ -20,6 +20,7 @@ public sealed class RuntimeCommand public string Suffix = String.Empty; public string MSBuildApiLevel = String.Empty; public List? ExtraOptions = null; + public bool IsNet6 = false; public bool IsHost = false; }; @@ -83,6 +84,7 @@ public sealed class RuntimeCommand public static readonly List AsanExtraOptions = new List { "-DENABLE_CLANG_ASAN=ON", + "-DANDROID_STL=\"c++_static\"", }; public static readonly List UbsanExtraOptions = new List { @@ -91,6 +93,19 @@ public sealed class RuntimeCommand "-DANDROID_CPP_FEATURES=\"rtti exceptions\"", }; + const string enableNet6 = "-DENABLE_NET6=ON"; + public static readonly List Net6ExtraOptions = new List { + enableNet6, + }; + + public static readonly List Net6AsanExtraOptions = new List (AsanExtraOptions) { + enableNet6, + }; + + public static readonly List Net6UbsanExtraOptions = new List (UbsanExtraOptions) { + enableNet6, + }; + public static readonly List AndroidRuntimeCommands = new List { // Debug builds new RuntimeCommand { @@ -116,6 +131,33 @@ public sealed class RuntimeCommand ExtraOptions = UbsanExtraOptions, }, + new RuntimeCommand { + Suffix = "net6-Debug", + Configuration = "Release", + BuildType = "Debug", + MSBuildApiLevel = msbuildApiLevelNet6, + ExtraOptions = Net6ExtraOptions, + IsNet6 = true, + }, + + new RuntimeCommand { + Suffix = "net6-asan-Debug", + Configuration = "Release", + BuildType = "Debug", + MSBuildApiLevel = msbuildApiLevelNet6, + ExtraOptions = Net6AsanExtraOptions, + IsNet6 = true, + }, + + new RuntimeCommand { + Suffix = "net6-ubsan-Debug", + Configuration = "Release", + BuildType = "Debug", + MSBuildApiLevel = msbuildApiLevelNet6, + ExtraOptions = Net6UbsanExtraOptions, + IsNet6 = true, + }, + // Release builds new RuntimeCommand { @@ -140,6 +182,33 @@ public sealed class RuntimeCommand MSBuildApiLevel = msbuildApiLevelLegacy, ExtraOptions = UbsanExtraOptions, }, + + new RuntimeCommand { + Suffix = "net6-Release", + Configuration = "Debug", + BuildType = "Release", + MSBuildApiLevel = msbuildApiLevelNet6, + ExtraOptions = Net6ExtraOptions, + IsNet6 = true, + }, + + new RuntimeCommand { + Suffix = "net6-asan-Release", + Configuration = "Debug", + BuildType = "Release", + MSBuildApiLevel = msbuildApiLevelNet6, + ExtraOptions = Net6AsanExtraOptions, + IsNet6 = true, + }, + + new RuntimeCommand { + Suffix = "net6-ubsan-Release", + Configuration = "Debug", + BuildType = "Release", + MSBuildApiLevel = msbuildApiLevelNet6, + ExtraOptions = Net6UbsanExtraOptions, + IsNet6 = true, + }, }; public static readonly List HostRuntimeCommands = new List { diff --git a/build-tools/xaprepare/xaprepare/ConfigAndData/Configurables.cs b/build-tools/xaprepare/xaprepare/ConfigAndData/Configurables.cs index 90eee6e1251..94811ca21dc 100644 --- a/build-tools/xaprepare/xaprepare/ConfigAndData/Configurables.cs +++ b/build-tools/xaprepare/xaprepare/ConfigAndData/Configurables.cs @@ -367,6 +367,12 @@ public static partial class Paths public static string MonoArchiveLocalPath => Path.Combine (ctx.Properties.GetRequiredValue (KnownProperties.AndroidToolchainCacheDirectory), MonoArchiveFileName); public static string MonoArchiveWindowsLocalPath => Path.Combine (ctx.Properties.GetRequiredValue (KnownProperties.AndroidToolchainCacheDirectory), MonoArchiveWindowsFileName); + // .NET 6 + public static string NetcoreAppRuntimeAndroidARM => GetCachedPath (ref netcoreAppRuntimeAndroidARM, () => GetNetcoreAppRuntimePath (ctx, "arm")); + public static string NetcoreAppRuntimeAndroidARM64 => GetCachedPath (ref netcoreAppRuntimeAndroidARM64, () => GetNetcoreAppRuntimePath (ctx, "arm64")); + public static string NetcoreAppRuntimeAndroidX86 => GetCachedPath (ref netcoreAppRuntimeAndroidX86, () => GetNetcoreAppRuntimePath (ctx, "x86")); + public static string NetcoreAppRuntimeAndroidX86_64 => GetCachedPath (ref netcoreAppRuntimeAndroidX86_64, () => GetNetcoreAppRuntimePath (ctx, "x64")); + // CMake public static string CmakeMSBuildPropsName = "cmake-config.props"; public static string CmakeShellScriptsPropsName = "cmake-config.sh"; @@ -392,6 +398,17 @@ public static partial class Paths return Directory.Exists (path) ? path : Path.Combine (MonoSdksTpnExternalPath, "llvm"); }); + static string GetNetcoreAppRuntimePath (Context ctx, string androidTarget) + { + return Path.Combine ( + XAPackagesDir, + $"microsoft.netcore.app.runtime.android-{androidTarget}", + ctx.Properties.GetRequiredValue (KnownProperties.DotNetRuntimePacksVersion), + "runtimes", + $"android-{androidTarget}" + ); + } + static string DetermineNugetPackagesDir (Context ctx) { return Path.GetFullPath ( @@ -470,6 +487,10 @@ static string GetCachedPath (ref string? variable, Func creator) static string? configurationPropsGeneratedPath; static string? windowsBinutilsInstallDir; static string? hostBinutilsInstallDir; + static string? netcoreAppRuntimeAndroidARM; + static string? netcoreAppRuntimeAndroidARM64; + static string? netcoreAppRuntimeAndroidX86; + static string? netcoreAppRuntimeAndroidX86_64; static string? monodroidSourceDir; } } diff --git a/build-tools/xaprepare/xaprepare/Steps/Step_GenerateFiles.cs b/build-tools/xaprepare/xaprepare/Steps/Step_GenerateFiles.cs index f36482a88be..97a9a524c5a 100644 --- a/build-tools/xaprepare/xaprepare/Steps/Step_GenerateFiles.cs +++ b/build-tools/xaprepare/xaprepare/Steps/Step_GenerateFiles.cs @@ -48,12 +48,14 @@ protected override async Task Execute (Context context) return new List { Get_MonoGitHash_props (context), Get_Configuration_Generated_Props (context), + Get_Cmake_XA_Build_Configuration (context), new GeneratedMonodroidCmakeFiles (Configurables.Paths.BuildBinDir), }; } else { return new List { Get_Configuration_OperatingSystem_props (context), Get_Configuration_Generated_Props (context), + Get_Cmake_XA_Build_Configuration (context), new GeneratedMonodroidCmakeFiles (Configurables.Paths.BuildBinDir), Get_Ndk_projitems (context), Get_XABuildConfig_cs (context), @@ -81,12 +83,30 @@ protected override async Task Execute (Context context) partial void AddUnixPostBuildSteps (Context context, List steps); partial void AddOSSpecificSteps (Context context, List steps); + GeneratedFile Get_Cmake_XA_Build_Configuration (Context context) + { + const string OutputFileName = "xa_build_configuration.cmake"; + + var replacements = new Dictionary (StringComparer.Ordinal) { + { "@NETCORE_APP_RUNTIME_ANDROID_ARM@", Utilities.EscapePathSeparators (Configurables.Paths.NetcoreAppRuntimeAndroidARM) }, + { "@NETCORE_APP_RUNTIME_ANDROID_ARM64@", Utilities.EscapePathSeparators (Configurables.Paths.NetcoreAppRuntimeAndroidARM64) }, + { "@NETCORE_APP_RUNTIME_ANDROID_X86@", Utilities.EscapePathSeparators (Configurables.Paths.NetcoreAppRuntimeAndroidX86) }, + { "@NETCORE_APP_RUNTIME_ANDROID_X86_64@", Utilities.EscapePathSeparators (Configurables.Paths.NetcoreAppRuntimeAndroidX86_64) }, + }; + + return new GeneratedPlaceholdersFile ( + replacements, + Path.Combine (Configurables.Paths.BuildToolsScriptsDir, $"{OutputFileName}.in"), + Path.Combine (Configurables.Paths.BuildBinDir, OutputFileName) + ); + } + GeneratedFile Get_Configuration_Generated_Props (Context context) { const string OutputFileName = "Configuration.Generated.props"; var replacements = new Dictionary (StringComparer.Ordinal) { - { "@XA_PACKAGES_DIR@", Configurables.Paths.XAPackagesDir }, + { "@XA_PACKAGES_DIR@", Configurables.Paths.XAPackagesDir }, }; return new GeneratedPlaceholdersFile ( @@ -162,9 +182,13 @@ GeneratedFile Get_Ndk_projitems (Context context) var replacements = new Dictionary (StringComparer.Ordinal) { { "@NDK_RELEASE@", BuildAndroidPlatforms.AndroidNdkVersion }, { "@NDK_ARMEABI_V7_API@", BuildAndroidPlatforms.NdkMinimumAPI [AbiNames.TargetJit.AndroidArmV7a].ToString () }, + { "@NDK_ARMEABI_V7_API_NET6@", BuildAndroidPlatforms.NdkMinimumAPI [BuildAndroidPlatforms.AndroidArmV7a_NET6].ToString () }, { "@NDK_ARM64_V8A_API@", BuildAndroidPlatforms.NdkMinimumAPI [AbiNames.TargetJit.AndroidArmV8a].ToString () }, + { "@NDK_ARM64_V8A_API_NET6@", BuildAndroidPlatforms.NdkMinimumAPI [BuildAndroidPlatforms.AndroidArmV8a_NET6].ToString () }, { "@NDK_X86_API@", BuildAndroidPlatforms.NdkMinimumAPI [AbiNames.TargetJit.AndroidX86].ToString () }, + { "@NDK_X86_API_NET6@", BuildAndroidPlatforms.NdkMinimumAPI [BuildAndroidPlatforms.AndroidX86_NET6].ToString () }, { "@NDK_X86_64_API@", BuildAndroidPlatforms.NdkMinimumAPI [AbiNames.TargetJit.AndroidX86_64].ToString () }, + { "@NDK_X86_64_API_NET6@", BuildAndroidPlatforms.NdkMinimumAPI [BuildAndroidPlatforms.AndroidX86_64_NET6].ToString () }, }; return new GeneratedPlaceholdersFile ( diff --git a/build-tools/xaprepare/xaprepare/ThirdPartyNotices/bionic.cs b/build-tools/xaprepare/xaprepare/ThirdPartyNotices/bionic.cs new file mode 100644 index 00000000000..fcc87a3ae7b --- /dev/null +++ b/build-tools/xaprepare/xaprepare/ThirdPartyNotices/bionic.cs @@ -0,0 +1,31 @@ +using System; + +namespace Xamarin.Android.Prepare +{ + [TPN] + class google_bionic_TPN : ThirdPartyNotice + { + static readonly Uri url = new Uri ("https://android.googlesource.com/platform/bionic/"); + + public override string LicenseFile => String.Empty; + public override string Name => "google/bionic"; + public override Uri SourceUrl => url; + public override string LicenseText => @" +Copyright (C) 2006 The Android Open Source Project + +Licensed under the Apache License, Version 2.0 (the ""License""); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an ""AS IS"" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +"; + + public override bool Include (bool includeExternalDeps, bool includeBuildDeps) => includeExternalDeps; + } +} diff --git a/build-tools/xaprepare/xaprepare/ThirdPartyNotices/robin-map.cs b/build-tools/xaprepare/xaprepare/ThirdPartyNotices/robin-map.cs new file mode 100644 index 00000000000..560f8d62cdb --- /dev/null +++ b/build-tools/xaprepare/xaprepare/ThirdPartyNotices/robin-map.cs @@ -0,0 +1,19 @@ +using System; +using System.IO; + +namespace Xamarin.Android.Prepare +{ + [TPN] + class tessil_robin_map_TPN : ThirdPartyNotice + { + static readonly Uri url = new Uri ("https://github.com/Tessil/robin-map"); + static readonly string licenseFile = Path.Combine (Configurables.Paths.ExternalDir, "robin-map", "LICENSE"); + + public override string LicenseFile => licenseFile; + public override string Name => "tessil/robin-map"; + public override Uri SourceUrl => url; + public override string LicenseText => String.Empty; + + public override bool Include (bool includeExternalDeps, bool includeBuildDeps) => includeBuildDeps; + } +} diff --git a/build-tools/xaprepare/xaprepare/xaprepare.csproj b/build-tools/xaprepare/xaprepare/xaprepare.csproj index 1e95fdd4157..0c13e86bbc6 100644 --- a/build-tools/xaprepare/xaprepare/xaprepare.csproj +++ b/build-tools/xaprepare/xaprepare/xaprepare.csproj @@ -60,4 +60,10 @@ + + + + + + diff --git a/external/robin-map b/external/robin-map new file mode 160000 index 00000000000..a603419b9a0 --- /dev/null +++ b/external/robin-map @@ -0,0 +1 @@ +Subproject commit a603419b9a0687c9148e02c8bd5e3db180bb9ac0 diff --git a/src-ThirdParty/bionic/bionic_futex.hh b/src-ThirdParty/bionic/bionic_futex.hh new file mode 100644 index 00000000000..094ec5028ff --- /dev/null +++ b/src-ThirdParty/bionic/bionic_futex.hh @@ -0,0 +1,84 @@ +/* + * Ported to Xamarin.Android from: https://android.googlesource.com/platform/bionic/+/refs/tags/android-11.0.0_r31/libc/private/bionic_futex.h + */ + +/* + * Copyright (C) 2008 The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#ifndef _BIONIC_FUTEX_H +#define _BIONIC_FUTEX_H + +#include +#include +#include +#include +#include +#include +#include + +struct timespec; + +static inline __always_inline long __futex(volatile void* ftx, int op, int value, + const timespec* timeout, int bitset) { + // Our generated syscall assembler sets errno, but our callers (pthread functions) don't want to. + int saved_errno = errno; + long result = syscall(__NR_futex, ftx, op, value, timeout, NULL, bitset); + if (__predict_false(result == -1)) { + result = -errno; + errno = saved_errno; + } + return result; +} + +static inline long __futex_wake(volatile void* ftx, int count) { + return __futex(ftx, FUTEX_WAKE, count, nullptr, 0); +} + +static inline long __futex_wake_ex(volatile void* ftx, bool shared, int count) { + return __futex(ftx, shared ? FUTEX_WAKE : FUTEX_WAKE_PRIVATE, count, nullptr, 0); +} + +static inline long __futex_wait(volatile void* ftx, int value, const timespec* timeout) { + return __futex(ftx, FUTEX_WAIT, value, timeout, 0); +} + +static inline long __futex_wait_ex(volatile void* ftx, bool shared, int value) { + return __futex(ftx, (shared ? FUTEX_WAIT_BITSET : FUTEX_WAIT_BITSET_PRIVATE), value, nullptr, + static_cast(FUTEX_BITSET_MATCH_ANY)); +} + +__LIBC_HIDDEN__ long __futex_wait_ex(volatile void* ftx, bool shared, int value, + bool use_realtime_clock, const timespec* abs_timeout); + +static inline long __futex_pi_unlock(volatile void* ftx, bool shared) { + return __futex(ftx, shared ? FUTEX_UNLOCK_PI : FUTEX_UNLOCK_PI_PRIVATE, 0, nullptr, 0); +} + +__LIBC_HIDDEN__ long __futex_pi_lock_ex(volatile void* ftx, bool shared, bool use_realtime_clock, + const timespec* abs_timeout); + +#endif /* _BIONIC_FUTEX_H */ diff --git a/src-ThirdParty/bionic/cxa_guard.cc b/src-ThirdParty/bionic/cxa_guard.cc new file mode 100644 index 00000000000..099d8f476eb --- /dev/null +++ b/src-ThirdParty/bionic/cxa_guard.cc @@ -0,0 +1,130 @@ +// +// Ported to Xamarin.Android from: https://android.googlesource.com/platform/bionic/+/refs/tags/android-11.0.0_r31/libc/bionic/__cxa_guard.cpp +// + +/* + * Copyright (C) 2006 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include + +#include "bionic_futex.hh" + +// This file contains C++ ABI support functions for one time +// constructors as defined in the "Run-time ABI for the ARM Architecture" +// section 4.4.2 +// +// ARM C++ ABI and Itanium/x86 C++ ABI has different definition for +// one time construction: +// +// ARM C++ ABI defines the LSB of guard variable should be tested +// by compiler-generated code before calling __cxa_guard_acquire et al. +// +// The Itanium/x86 C++ ABI defines the low-order _byte_ should be +// tested instead. +// +// Meanwhile, guard variable are 32bit aligned for ARM, and 64bit +// aligned for x86. +// +// Reference documentation: +// +// section 3.2.3 of ARM IHI 0041C (for ARM) +// section 3.3.2 of the Itanium C++ ABI specification v1.83 (for x86). +// +// There is no C++ ABI available for other ARCH. But the gcc source +// shows all other ARCH follow the definition of Itanium/x86 C++ ABI. + +#if defined(__arm__) +// The ARM C++ ABI mandates that guard variables are 32-bit aligned, 32-bit +// values. The LSB is tested by the compiler-generated code before calling +// __cxa_guard_acquire. +union _guard_t { + atomic_int state; + int32_t aligner; +}; + +#else +// The Itanium/x86 C++ ABI (used by all other architectures) mandates that +// guard variables are 64-bit aligned, 64-bit values. The LSB is tested by +// the compiler-generated code before calling __cxa_guard_acquire. +union _guard_t { + atomic_int state; + int64_t aligner; +}; + +#endif + +// Set construction state values according to reference documentation. +// 0 is the initialization value. +// Arm requires ((*gv & 1) == 1) after __cxa_guard_release, ((*gv & 3) == 0) after __cxa_guard_abort. +// X86 requires first byte not modified by __cxa_guard_acquire, first byte is non-zero after +// __cxa_guard_release. + +#define CONSTRUCTION_NOT_YET_STARTED 0 +#define CONSTRUCTION_COMPLETE 1 +#define CONSTRUCTION_UNDERWAY_WITHOUT_WAITER 0x100 +#define CONSTRUCTION_UNDERWAY_WITH_WAITER 0x200 + +extern "C" int __cxa_guard_acquire(_guard_t* gv) { + int old_value = atomic_load_explicit(&gv->state, memory_order_acquire); + // In the common CONSTRUCTION_COMPLETE case we have to ensure that all the stores performed by + // the construction function are observable on this CPU after we exit. A similar constraint may + // apply in the CONSTRUCTION_NOT_YET_STARTED case with a prior abort. + + while (true) { + if (old_value == CONSTRUCTION_COMPLETE) { + return 0; + } else if (old_value == CONSTRUCTION_NOT_YET_STARTED) { + if (!atomic_compare_exchange_weak_explicit(&gv->state, &old_value, + CONSTRUCTION_UNDERWAY_WITHOUT_WAITER, + memory_order_acquire /* or relaxed in C++17 */, + memory_order_acquire)) { + continue; + } + return 1; + } else if (old_value == CONSTRUCTION_UNDERWAY_WITHOUT_WAITER) { + if (!atomic_compare_exchange_weak_explicit(&gv->state, &old_value, + CONSTRUCTION_UNDERWAY_WITH_WAITER, + memory_order_acquire /* or relaxed in C++17 */, + memory_order_acquire)) { + continue; + } + } + + __futex_wait_ex(&gv->state, false, CONSTRUCTION_UNDERWAY_WITH_WAITER); + old_value = atomic_load_explicit(&gv->state, memory_order_acquire); + } +} + +extern "C" void __cxa_guard_release(_guard_t* gv) { + // Release fence is used to make all stores performed by the construction function + // visible in other threads. + int old_value = atomic_exchange_explicit(&gv->state, CONSTRUCTION_COMPLETE, memory_order_release); + if (old_value == CONSTRUCTION_UNDERWAY_WITH_WAITER) { + __futex_wake_ex(&gv->state, false, INT_MAX); + } +} + +extern "C" void __cxa_guard_abort(_guard_t* gv) { + // Release fence is used to make all stores performed by the construction function + // visible in other threads. + int old_value = atomic_exchange_explicit(&gv->state, CONSTRUCTION_NOT_YET_STARTED, memory_order_release); + if (old_value == CONSTRUCTION_UNDERWAY_WITH_WAITER) { + __futex_wake_ex(&gv->state, false, INT_MAX); + } +} diff --git a/src/Xamarin.Android.Build.Tasks/Microsoft.NET.Workload.Android/WorkloadManifest.in.json b/src/Xamarin.Android.Build.Tasks/Microsoft.NET.Workload.Android/WorkloadManifest.in.json index e856c4e1dc1..e74c9547d6e 100644 --- a/src/Xamarin.Android.Build.Tasks/Microsoft.NET.Workload.Android/WorkloadManifest.in.json +++ b/src/Xamarin.Android.Build.Tasks/Microsoft.NET.Workload.Android/WorkloadManifest.in.json @@ -17,7 +17,8 @@ "version": "@SDK_PACK_VERSION@", "alias-to": { "osx-x64": "Microsoft.Android.Sdk.osx-x64", - "win-x64": "Microsoft.Android.Sdk.win-x64" + "win-x64": "Microsoft.Android.Sdk.win-x64", + "linux-x64": "Microsoft.Android.Sdk.linux-x64" } }, "Microsoft.Android.Sdk.BundleTool": { diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Common/Builder.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Common/Builder.cs index e5bdd637424..06258e10dab 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Common/Builder.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Common/Builder.cs @@ -17,6 +17,8 @@ public class Builder : IDisposable const string SigSegvError = "Got a SIGSEGV while executing native code"; const string ConsoleLoggerError = "[ERROR] FATAL UNHANDLED EXCEPTION: System.ArgumentException: is negative"; + string Arm32AbiDir => UseDotNet ? "armeabi-v7a-net6" : "armeabi-v7a"; + /// /// If true, use `dotnet build` and IShortFormProject throughout the tests /// @@ -80,7 +82,7 @@ public string BuildOutputDirectory { get { var outdir = Environment.GetEnvironmentVariable ("XA_BUILD_OUTPUT_PATH"); string configuration = Environment.GetEnvironmentVariable ("CONFIGURATION") ?? XABuildPaths.Configuration; - var libmonodroidPath = Path.Combine ("lib", "xamarin.android", "xbuild", "Xamarin", "Android", "lib", "armeabi-v7a", "libmono-android.release.so"); + var libmonodroidPath = Path.Combine ("lib", "xamarin.android", "xbuild", "Xamarin", "Android", "lib", Arm32AbiDir, "libmono-android.release.so"); if (String.IsNullOrEmpty(outdir)) outdir = Path.GetFullPath (Path.Combine (Root, "..", "..", "..", "..", "..", "..", "..", "out")); if (!Directory.Exists (Path.Combine (outdir, "lib")) || !File.Exists (Path.Combine (outdir, libmonodroidPath))) @@ -105,7 +107,7 @@ public string BuildOutputDirectory { public string AndroidMSBuildDirectory { get { var msbuildDir = Path.Combine (BuildOutputDirectory, "lib", "xamarin.android", "xbuild", "Xamarin", "Android"); - if (Directory.Exists (msbuildDir) && File.Exists (Path.Combine (msbuildDir, "lib", "armeabi-v7a", "libmono-android.release.so"))) + if (Directory.Exists (msbuildDir) && File.Exists (Path.Combine (msbuildDir, "lib", Arm32AbiDir, "libmono-android.release.so"))) return msbuildDir; return TestEnvironment.MonoAndroidToolsDirectory; diff --git a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets index 491562ff420..53bfeee4bb3 100644 --- a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets +++ b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets @@ -1261,8 +1261,11 @@ because xbuild doesn't support framework reference assemblies. - <_RuntimeJar>$(MSBuildThisFileDirectory)\java_runtime.jar - <_RuntimeDex>$(MSBuildThisFileDirectory)\java_runtime.dex + <_RuntimeJar Condition=" '$(UsingAndroidNETSdk)' != 'True' ">$(MSBuildThisFileDirectory)\java_runtime.jar + <_RuntimeDex Condition=" '$(UsingAndroidNETSdk)' != 'True' ">$(MSBuildThisFileDirectory)\java_runtime.dex + + <_RuntimeJar Condition=" '$(UsingAndroidNETSdk)' == 'True' ">$(MSBuildThisFileDirectory)\java_runtime_net6.jar + <_RuntimeDex Condition=" '$(UsingAndroidNETSdk)' == 'True' ">$(MSBuildThisFileDirectory)\java_runtime_net6.dex diff --git a/src/java-runtime/java-runtime.targets b/src/java-runtime/java-runtime.targets index 99cb0d31c05..0f17932c4d7 100644 --- a/src/java-runtime/java-runtime.targets +++ b/src/java-runtime/java-runtime.targets @@ -7,14 +7,29 @@ $(OutputPath)java_runtime.dex $(IntermediateOutputPath)release $(IntermediateOutputPath)release.txt - ..\..\src-ThirdParty\bazel\java\mono\android\debug\MultiDexLoader.java;java\mono\android\debug\BuildConfig.java + ..\..\src-ThirdParty\bazel\java\mono\android\debug\MultiDexLoader.java;java\mono\android\debug\BuildConfig.java;java\mono\android\debug-net6\BuildConfig.java;java\mono\android\release-net6\BuildConfig.java <_RuntimeOutput Include="$(OutputPath)java_runtime_fastdev.jar"> $(OutputPath)java_runtime_fastdev.jar $(OutputPath)java_runtime_fastdev.dex $(IntermediateOutputPath)fastdev $(IntermediateOutputPath)fastdev.txt - ..\..\src-ThirdParty\bazel\java\mono\android\release\MultiDexLoader.java;java\mono\android\release\BuildConfig.java + ..\..\src-ThirdParty\bazel\java\mono\android\release\MultiDexLoader.java;java\mono\android\release\BuildConfig.java;java\mono\android\release-net6\BuildConfig.java;java\mono\android\debug-net6\BuildConfig.java + + + <_RuntimeOutput Include="$(OutputPath)java_runtime_net6.jar"> + $(OutputPath)java_runtime_net6.jar + $(OutputPath)java_runtime_net6.dex + $(IntermediateOutputPath)release-net6 + $(IntermediateOutputPath)release-net6.txt + ..\..\src-ThirdParty\bazel\java\mono\android\debug\MultiDexLoader.java;java\mono\android\debug-net6\BuildConfig.java;java\mono\android\debug\BuildConfig.java;java\mono\android\release\BuildConfig.java + + <_RuntimeOutput Include="$(OutputPath)java_runtime_fastdev_net6.jar"> + $(OutputPath)java_runtime_fastdev_net6.jar + $(OutputPath)java_runtime_fastdev_net6.dex + $(IntermediateOutputPath)fastdev-net6 + $(IntermediateOutputPath)fastdev-net6.txt + ..\..\src-ThirdParty\bazel\java\mono\android\release\MultiDexLoader.java;java\mono\android\release-net6\BuildConfig.java;java\mono\android\release\BuildConfig.java;java\mono\android\debug\BuildConfig.java diff --git a/src/java-runtime/java/mono/android/MonoPackageManager.java b/src/java-runtime/java/mono/android/MonoPackageManager.java index 96048d65c12..52451489f33 100644 --- a/src/java-runtime/java/mono/android/MonoPackageManager.java +++ b/src/java-runtime/java/mono/android/MonoPackageManager.java @@ -79,13 +79,9 @@ public static void LoadApplication (Context context, ApplicationInfo runtimePack } System.loadLibrary("xamarin-app"); - // .net5+ APKs don't contain `libmono-native.so` but we can't just perform a file existence check - // because we might be running with embedded DSOs enabled in which case the check would fail and we - // would have to catch the exception anyway in this case. - try { + if (!BuildConfig.DotNetRuntime) { + // .net5+ APKs don't contain `libmono-native.so` System.loadLibrary("mono-native"); - } catch (java.lang.UnsatisfiedLinkError ex) { - Log.i ("monodroid", "Failed to preload libmono-native.so (may not exist), ignoring", ex); } System.loadLibrary("monodroid"); diff --git a/src/java-runtime/java/mono/android/debug-net6/BuildConfig.java b/src/java-runtime/java/mono/android/debug-net6/BuildConfig.java new file mode 100644 index 00000000000..e05ba068714 --- /dev/null +++ b/src/java-runtime/java/mono/android/debug-net6/BuildConfig.java @@ -0,0 +1,6 @@ +package mono.android; + +public class BuildConfig { + public static boolean Debug = true; + public static boolean DotNetRuntime = true; +} diff --git a/src/java-runtime/java/mono/android/debug/BuildConfig.java b/src/java-runtime/java/mono/android/debug/BuildConfig.java index 198c2d10df9..575b166ca60 100644 --- a/src/java-runtime/java/mono/android/debug/BuildConfig.java +++ b/src/java-runtime/java/mono/android/debug/BuildConfig.java @@ -2,4 +2,5 @@ public class BuildConfig { public static boolean Debug = true; + public static boolean DotNetRuntime = false; } diff --git a/src/java-runtime/java/mono/android/release-net6/BuildConfig.java b/src/java-runtime/java/mono/android/release-net6/BuildConfig.java new file mode 100644 index 00000000000..498a947ff8c --- /dev/null +++ b/src/java-runtime/java/mono/android/release-net6/BuildConfig.java @@ -0,0 +1,6 @@ +package mono.android; + +public class BuildConfig { + public static boolean Debug = false; + public static boolean DotNetRuntime = true; +} diff --git a/src/java-runtime/java/mono/android/release/BuildConfig.java b/src/java-runtime/java/mono/android/release/BuildConfig.java index e709a143496..4070a147bb1 100644 --- a/src/java-runtime/java/mono/android/release/BuildConfig.java +++ b/src/java-runtime/java/mono/android/release/BuildConfig.java @@ -2,4 +2,5 @@ public class BuildConfig { public static boolean Debug = false; + public static boolean DotNetRuntime = false; } diff --git a/src/monodroid/CMakeLists.txt b/src/monodroid/CMakeLists.txt index 8b9c6f2bd60..b3d75cd85a1 100644 --- a/src/monodroid/CMakeLists.txt +++ b/src/monodroid/CMakeLists.txt @@ -22,6 +22,7 @@ set(CMAKE_C_EXTENSIONS OFF) option(ENABLE_CLANG_ASAN "Enable the clang AddressSanitizer support" OFF) option(ENABLE_CLANG_UBSAN "Enable the clang UndefinedBehaviorSanitizer support" OFF) +option(ENABLE_NET6 "Enable compilation for .NET6" OFF) option(ENABLE_TIMING "Build with timing support" OFF) option(STRIP_DEBUG "Strip debugging information when linking" ON) option(DISABLE_DEBUG "Disable the built-in debugging code" OFF) @@ -32,6 +33,14 @@ else() set(DEBUG_BUILD False) endif() +if(ANDROID) + if(ANDROID_STL STREQUAL none) + set(USES_LIBSTDCPP False) + else() + set(USES_LIBSTDCPP True) + endif() +endif() + # Environment checks if(NOT DEFINED MONO_PATH) @@ -106,11 +115,13 @@ endif() set(EXTERNAL_DIR "../../external") set(JAVA_INTEROP_SRC_PATH "${EXTERNAL_DIR}/Java.Interop/src/java-interop") set(SOURCES_DIR ${CMAKE_SOURCE_DIR}/jni) +set(BIONIC_SOURCES_DIR "../../src-ThirdParty/bionic") set(LZ4_SRC_DIR "${EXTERNAL_DIR}/lz4/lib") set(LZ4_INCLUDE_DIR ${LZ4_SRC_DIR}) set(XA_BIN_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../../bin/${XA_BUILD_CONFIGURATION}") set(XA_BUILD_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../../bin/Build${XA_BUILD_CONFIGURATION}") set(XA_LIB_TOP_DIR "${XA_BIN_DIR}/lib/xamarin.android/xbuild/Xamarin/Android/lib") +set(ROBIN_MAP_DIR "${EXTERNAL_DIR}/robin-map") if(NOT ANDROID) if(WIN32 OR MINGW) @@ -130,12 +141,29 @@ if(NOT ANDROID) endif() endif() +include("${XA_BUILD_DIR}/xa_build_configuration.cmake") + +if(ENABLE_NET6) + if(ANDROID_ABI MATCHES "^arm64-v8a") + set(NET6_RUNTIME_DIR "${NETCORE_APP_RUNTIME_DIR_ARM64}") + elseif(ANDROID_ABI MATCHES "^armeabi-v7a") + set(NET6_RUNTIME_DIR "${NETCORE_APP_RUNTIME_DIR_ARM}") + elseif(ANDROID_ABI MATCHES "^x86_64") + set(NET6_RUNTIME_DIR "${NETCORE_APP_RUNTIME_DIR_X86_64}") + elseif(ANDROID_ABI MATCHES "^x86") + set(NET6_RUNTIME_DIR "${NETCORE_APP_RUNTIME_DIR_X86}") + else() + message(FATAL "${ANDROID_ABI} is not supported for .NET6 builds") + endif() +endif() + set(LZ4_SOURCES "${LZ4_SRC_DIR}/lz4.c" ) # Include directories include_directories(${CMAKE_CURRENT_BINARY_DIR}/include/ ${CMAKE_SOURCE_DIR}/include) +include_directories(${ROBIN_MAP_DIR}/include) if(NOT ANDROID) string(REPLACE " " ";" JDK_INCLUDE_LIST ${JDK_INCLUDE}) @@ -176,7 +204,12 @@ if (WIN32) include_directories(BEFORE "jni/win32") endif() -include_directories("${XA_BIN_DIR}/include/mono-2.0") +if(ENABLE_NET6) + include_directories("${NET6_RUNTIME_DIR}/native/include/mono-2.0") +else() + include_directories("${XA_BIN_DIR}/include/mono-2.0") +endif() + include_directories("jni") include_directories("${XA_BIN_DIR}/include") include_directories("${XA_BIN_DIR}/include/${ANDROID_ABI}/eglib") @@ -196,11 +229,17 @@ xa_macos_prepare_arm64() # Compiler defines -add_compile_definitions(DHAVE_CONFIG_H) +add_compile_definitions(TSL_NO_EXCEPTIONS) +add_compile_definitions(HAVE_CONFIG_H) add_compile_definitions(_REENTRANT) add_compile_definitions(JI_DLL_EXPORT) add_compile_definitions(MONO_DLL_EXPORT) +if(ENABLE_NET6) + add_compile_definitions(NET6) + add_compile_definitions(JI_NO_VISIBILITY) +endif() + if(DEBUG_BUILD AND NOT DISABLE_DEBUG) add_compile_definitions(DEBUG) endif() @@ -341,8 +380,13 @@ endif() # Library directories if(ANDROID) - set(XA_LIBRARY_OUTPUT_DIRECTORY "${XA_LIB_TOP_DIR}/${ANDROID_ABI}") - link_directories("${XA_LIBRARY_OUTPUT_DIRECTORY}") + if(ENABLE_NET6) + set(XA_LIBRARY_OUTPUT_DIRECTORY "${XA_LIB_TOP_DIR}/${ANDROID_ABI}-net6") + link_directories("${NET6_RUNTIME_DIR}/native") + else() + set(XA_LIBRARY_OUTPUT_DIRECTORY "${XA_LIB_TOP_DIR}/${ANDROID_ABI}") + link_directories("${XA_LIBRARY_OUTPUT_DIRECTORY}") + endif() endif() if(WIN32 OR MINGW) @@ -399,7 +443,6 @@ set(XAMARIN_MONODROID_SOURCES ${SOURCES_DIR}/globals.cc ${SOURCES_DIR}/logger.cc ${SOURCES_DIR}/monodroid-glue.cc - ${SOURCES_DIR}/xa-internal-api.cc ${SOURCES_DIR}/osbridge.cc ${SOURCES_DIR}/shared-constants.cc ${SOURCES_DIR}/timezones.cc @@ -414,9 +457,18 @@ if(ANDROID) list(APPEND XAMARIN_MONODROID_SOURCES ${LZ4_SOURCES} ) + + if(NOT USES_LIBSTDCPP) + list(APPEND XAMARIN_MONODROID_SOURCES + ${BIONIC_SOURCES_DIR}/cxa_guard.cc + ${SOURCES_DIR}/cxx-abi/string.cc + ${SOURCES_DIR}/cxx-abi/terminate.cc + ) + endif() else() list(APPEND XAMARIN_MONODROID_SOURCES ${SOURCES_DIR}/designer-assemblies.cc + ${SOURCES_DIR}/monodroid-glue-designer.cc ${JAVA_INTEROP_SRC_PATH}/java-interop-gc-bridge-mono.cc ${JAVA_INTEROP_SRC_PATH}/java-interop-jvm.cc ) @@ -429,11 +481,23 @@ if(UNIX) ) endif() -set(XAMARIN_INTERNAL_API_SOURCES - ${SOURCES_DIR}/jni.c - ${SOURCES_DIR}/internal-pinvoke-api.cc - ${JAVA_INTEROP_SRC_PATH}/java-interop-util.cc - ) +if(ANDROID AND ENABLE_NET6) + list(APPEND XAMARIN_MONODROID_SOURCES + ${SOURCES_DIR}/pinvoke-override-api.cc + ${SOURCES_DIR}/java_interop_api.c + ${JAVA_INTEROP_SRC_PATH}/java-interop-util.cc + ) +else() + list(APPEND XAMARIN_MONODROID_SOURCES + ${SOURCES_DIR}/xa-internal-api.cc + ) + + set(XAMARIN_INTERNAL_API_SOURCES + ${SOURCES_DIR}/java_interop_api.c + ${SOURCES_DIR}/internal-pinvoke-api.cc + ${JAVA_INTEROP_SRC_PATH}/java-interop-util.cc + ) +endif() set(XAMARIN_APP_STUB_SOURCES ${SOURCES_DIR}/application_dso_stub.cc @@ -451,21 +515,23 @@ set(XAMARIN_DEBUG_APP_HELPER_SOURCES # Build configure_file(jni/host-config.h.in ${CMAKE_CURRENT_BINARY_DIR}/include/host-config.h) -add_library( - ${XAMARIN_INTERNAL_API_LIB} - SHARED - ${XAMARIN_INTERNAL_API_SOURCES} - ) +if(NOT (ANDROID AND ENABLE_NET6)) + add_library( + ${XAMARIN_INTERNAL_API_LIB} + SHARED + ${XAMARIN_INTERNAL_API_SOURCES} + ) -target_compile_options( - ${XAMARIN_INTERNAL_API_LIB} - PRIVATE -fvisibility=default - ) + target_compile_options( + ${XAMARIN_INTERNAL_API_LIB} + PRIVATE -fvisibility=default + ) -target_link_options( - ${XAMARIN_INTERNAL_API_LIB} - PRIVATE -fvisibility=default - ) + target_link_options( + ${XAMARIN_INTERNAL_API_LIB} + PRIVATE -fvisibility=default + ) +endif() add_library( ${XAMARIN_APP_STUB_LIB} diff --git a/src/monodroid/jni/cpu-arch.hh b/src/monodroid/jni/cpu-arch.hh index 5d66b8a959a..9be5d356e5c 100644 --- a/src/monodroid/jni/cpu-arch.hh +++ b/src/monodroid/jni/cpu-arch.hh @@ -10,5 +10,8 @@ #define CPU_KIND_X86 ((unsigned short)4) #define CPU_KIND_X86_64 ((unsigned short)5) -MONO_API void _monodroid_detect_cpu_and_architecture (unsigned short *built_for_cpu, unsigned short *running_on_cpu, unsigned char *is64bit); -#endif +#if !defined(NET6) +MONO_API +#endif // def NET6 +void _monodroid_detect_cpu_and_architecture (unsigned short *built_for_cpu, unsigned short *running_on_cpu, unsigned char *is64bit); +#endif // ndef NET6 diff --git a/src/monodroid/jni/cxx-abi/string.cc b/src/monodroid/jni/cxx-abi/string.cc new file mode 100644 index 00000000000..53b5731defc --- /dev/null +++ b/src/monodroid/jni/cxx-abi/string.cc @@ -0,0 +1,13 @@ +// +// Defining the macro will make the the explicit instantations below truely hidden +// +#define _LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS + +#include + +_LIBCPP_BEGIN_NAMESPACE_STD + +template class __attribute__ ((__visibility__("hidden"))) __basic_string_common; +template class __attribute__ ((__visibility__("hidden"))) basic_string; + +_LIBCPP_END_NAMESPACE_STD diff --git a/src/monodroid/jni/cxx-abi/terminate.cc b/src/monodroid/jni/cxx-abi/terminate.cc new file mode 100644 index 00000000000..624274a30d8 --- /dev/null +++ b/src/monodroid/jni/cxx-abi/terminate.cc @@ -0,0 +1,17 @@ +// +// Simple implementation of std::terminate() for Xamarin.Android +// +// Does NOT support terminate handlers, since we don't use them. +// +#include +#include +#include + +namespace std { + [[noreturn]] void + terminate () noexcept + { + __android_log_write (ANDROID_LOG_FATAL, "monodroid", "std::terminate() called. Aborting."); + abort (); + } +} diff --git a/src/monodroid/jni/embedded-assemblies.cc b/src/monodroid/jni/embedded-assemblies.cc index 845272eda90..c526ad5b18f 100644 --- a/src/monodroid/jni/embedded-assemblies.cc +++ b/src/monodroid/jni/embedded-assemblies.cc @@ -133,8 +133,20 @@ EmbeddedAssemblies::get_assembly_data (const MonoBundledAssembly *e, char*& asse } MonoAssembly* +#if defined (NET6) && defined (NET6_ALC_WORKS) +EmbeddedAssemblies::open_from_bundles (MonoAssemblyName* aname, MonoAssemblyLoadContextGCHandle alc_gchandle, MonoError *error) +#else // !(def NET6 && def NET6_ALC_WORKS) EmbeddedAssemblies::open_from_bundles (MonoAssemblyName* aname, bool ref_only) +#endif // def NET6 && def NET6_ALC_WORKS { +#if defined (NET6) + // NET6 doesn't support reference-only loads, define the variable here to minimize ifdefs in the code below +#if defined (NET6_ALC_WORKS) + constexpr bool ref_only = false; +#else // def NET6_ALC_WORKS + ref_only = false; +#endif // ndef NET6_ALC_WORKS +#endif // def NET6 const char *culture = mono_assembly_name_get_culture (aname); const char *asmname = mono_assembly_name_get_name (aname); @@ -176,19 +188,51 @@ EmbeddedAssemblies::open_from_bundles (MonoAssemblyName* aname, bool ref_only) get_assembly_data (e, assembly_data, assembly_data_size); - if ((image = mono_image_open_from_data_with_name (assembly_data, assembly_data_size, 0, nullptr, ref_only, name.get ())) != nullptr && - (a = mono_assembly_load_from_full (image, name.get (), &status, ref_only)) != nullptr) { - mono_config_for_assembly (image); - break; +#if defined (NET6) && defined (NET6_ALC_WORKS) + image = mono_image_open_from_data_alc ( + alc_gchandle, + assembly_data, + assembly_data_size, + 0 /* need_copy */, + nullptr /* status */, + name.get () + ); +#else // (def NET6 && def NET6_ALC_WORKS) + image = mono_image_open_from_data_with_name (assembly_data, assembly_data_size, 0, nullptr, ref_only, name.get ()); +#endif // !(def NET6 && def NET6_ALC_WORKS) + if (image == nullptr) { + continue; + } + + a = mono_assembly_load_from_full (image, name.get (), &status, ref_only); + if (a == nullptr) { + continue; } + + mono_config_for_assembly (image); + break; } - if (a && utils.should_log (LOG_ASSEMBLY)) { + if (a != nullptr && utils.should_log (LOG_ASSEMBLY)) { log_info_nocheck (LOG_ASSEMBLY, "open_from_bundles: loaded assembly: %p\n", a); } + +#if defined (NET6) && defined (NET6_ALC_WORKS) + if (error != nullptr) { + error->error_code = a == nullptr ? MONO_ERROR_NONE : MONO_ERROR_FILE_NOT_FOUND; + } +#endif // def NET6 && def NET6_ALC_WORKS return a; } +#if defined (NET6) && defined (NET6_ALC_WORKS) +MonoAssembly* +EmbeddedAssemblies::open_from_bundles (MonoAssemblyLoadContextGCHandle alc_gchandle, MonoAssemblyName *aname, [[maybe_unused]] char **assemblies_path, [[maybe_unused]] void *user_data, MonoError *error) +{ + log_warn (LOG_DEFAULT, __PRETTY_FUNCTION__); + return embeddedAssemblies.open_from_bundles (aname, alc_gchandle, error); +} +#else // def NET6 && def NET6_ALC_WORKS MonoAssembly* EmbeddedAssemblies::open_from_bundles_full (MonoAssemblyName *aname, UNUSED_ARG char **assemblies_path, UNUSED_ARG void *user_data) { @@ -200,12 +244,23 @@ EmbeddedAssemblies::open_from_bundles_refonly (MonoAssemblyName *aname, UNUSED_A { return embeddedAssemblies.open_from_bundles (aname, true); } +#endif // !(def NET6 && def NET6_ALC_WORKS) void EmbeddedAssemblies::install_preload_hooks () { +#if defined (NET6) && defined (NET6_ALC_WORKS) + mono_install_assembly_preload_hook_v3 ( + open_from_bundles, + nullptr /* user_data */, + 0 /* append */ + ); +#else // def NET6 && def NET6_ALC_WORKS mono_install_assembly_preload_hook (open_from_bundles_full, nullptr); +#if !defined (NET6) // Reference-only loads don't exist in NET6 mono_install_assembly_refonly_preload_hook (open_from_bundles_refonly, nullptr); +#endif // !def NET6 +#endif // !(def NET6 && def NET6_ALC_WORKS) } template diff --git a/src/monodroid/jni/embedded-assemblies.hh b/src/monodroid/jni/embedded-assemblies.hh index 0eaaf8c9767..2ce875dbe1f 100644 --- a/src/monodroid/jni/embedded-assemblies.hh +++ b/src/monodroid/jni/embedded-assemblies.hh @@ -6,6 +6,10 @@ #include #include +#if defined (NET6) +#include +#endif + #include "strings.hh" #include "xamarin-app.hh" @@ -72,7 +76,11 @@ namespace xamarin::android::internal { MonoReflectionType* typemap_java_to_managed (const char *java_type_name); size_t register_from (const char *apk_file, monodroid_should_register should_register); void gather_bundled_assemblies_from_apk (const char* apk, monodroid_should_register should_register); +#if defined (NET6) && defined (NET6_ALC_WORKS) + MonoAssembly* open_from_bundles (MonoAssemblyName* aname, MonoAssemblyLoadContextGCHandle alc_gchandle, MonoError *error); +#else // def NET6 && def NET6_ALC_WORKS MonoAssembly* open_from_bundles (MonoAssemblyName* aname, bool ref_only); +#endif // !(def NET6 && def NET6_ALC_WORKS) #if defined (DEBUG) || !defined (ANDROID) template bool typemap_read_header (int dir_fd, const char *file_type, const char *dir_path, const char *file_path, uint32_t expected_magic, H &header, size_t &file_size, int &fd); @@ -86,9 +94,12 @@ namespace xamarin::android::internal { bool register_debug_symbols_for_assembly (const char *entry_name, MonoBundledAssembly *assembly, const mono_byte *debug_contents, int debug_size); static md_mmap_info md_mmap_apk_file (int fd, uint32_t offset, uint32_t size, const char* filename, const char* apk); - +#if defined (NET6) && defined (NET6_ALC_WORKS) + static MonoAssembly* open_from_bundles (MonoAssemblyLoadContextGCHandle alc_gchandle, MonoAssemblyName *aname, char **assemblies_path, void *user_data, MonoError *error); +#else // def NET6 && def NET6_ALC_WORKS static MonoAssembly* open_from_bundles_full (MonoAssemblyName *aname, char **assemblies_path, void *user_data); static MonoAssembly* open_from_bundles_refonly (MonoAssemblyName *aname, char **assemblies_path, void *user_data); +#endif // !(def NET6 && def NET6_ALC_WORKS) static void get_assembly_data (const MonoBundledAssembly *e, char*& assembly_data, uint32_t& assembly_data_size); void zip_load_entries (int fd, const char *apk_name, monodroid_should_register should_register); @@ -132,5 +143,8 @@ namespace xamarin::android::internal { }; } +#if !defined (NET6) MONO_API int monodroid_embedded_assemblies_set_assemblies_prefix (const char *prefix); +#endif // ndef NET6 + #endif /* INC_MONODROID_EMBEDDED_ASSEMBLIES_H */ diff --git a/src/monodroid/jni/jni.c b/src/monodroid/jni/java_interop_api.c similarity index 98% rename from src/monodroid/jni/jni.c rename to src/monodroid/jni/java_interop_api.c index 111f401226f..c4602190919 100644 --- a/src/monodroid/jni/jni.c +++ b/src/monodroid/jni/java_interop_api.c @@ -1,35 +1,10 @@ /* * Generated file; DO NOT EDIT! * - * To make changes, edit Java.Interop/tools/jnienv-gen and rerun + * To make changes, edit Java.Interop/build-tools/jnienv-gen and rerun */ -#include - -typedef jmethodID jstaticmethodID; -typedef jfieldID jstaticfieldID; -typedef jobject jglobal; - -/* VS 2010 and later have stdint.h */ -#if defined(_MSC_VER) - - #define JI_API_EXPORT __declspec(dllexport) - #define JI_API_IMPORT __declspec(dllimport) - -#else /* defined(_MSC_VER */ - - #define JI_API_EXPORT __attribute__ ((visibility ("default"))) - #define JI_API_IMPORT - -#endif /* !defined(_MSC_VER) */ - -#if defined(JI_DLL_EXPORT) - #define JI_API JI_API_EXPORT -#elif defined(JI_DLL_IMPORT) - #define JI_API JI_API_IMPORT -#else /* !defined(JI_DLL_IMPORT) && !defined(JI_API_IMPORT) */ - #define JI_API -#endif /* JI_DLL_EXPORT... */ +#include "java_interop_api.h" JI_API jint java_interop_jnienv_get_version (JNIEnv *env) diff --git a/src/monodroid/jni/java_interop_api.h b/src/monodroid/jni/java_interop_api.h new file mode 100644 index 00000000000..012c34a2948 --- /dev/null +++ b/src/monodroid/jni/java_interop_api.h @@ -0,0 +1,230 @@ +/* + * Generated file; DO NOT EDIT! + * + * To make changes, edit Java.Interop/build-tools/jnienv-gen and rerun + */ + +#if !defined (__JAVA_INTEROP_NATIVE_H) +#define __JAVA_INTEROP_NATIVE_H + +#include + +typedef jmethodID jstaticmethodID; +typedef jfieldID jstaticfieldID; +typedef jobject jglobal; + +#if !defined(JI_NO_VISIBILITY) + /* VS 2010 and later have stdint.h */ + #if defined(_MSC_VER) + + #define JI_API_EXPORT __declspec(dllexport) + #define JI_API_IMPORT __declspec(dllimport) + + #else /* defined(_MSC_VER */ + + #define JI_API_EXPORT __attribute__ ((visibility ("default"))) + #define JI_API_IMPORT + + #endif /* !defined(_MSC_VER) */ + + #if defined(JI_DLL_EXPORT) + #define JI_API JI_API_EXPORT + #elif defined(JI_DLL_IMPORT) + #define JI_API JI_API_IMPORT + #else /* !defined(JI_DLL_IMPORT) && !defined(JI_API_IMPORT) */ + #define JI_API + #endif /* JI_DLL_EXPORT... */ +#else // JI_NO_VISIBILITY + #define JI_API +#endif // JI_NO_VISIBILITY + +JI_API jint java_interop_jnienv_get_version (JNIEnv *env); +JI_API jclass java_interop_jnienv_define_class (JNIEnv *env, jthrowable *_thrown, const char* name, jobject loader, const jbyte* buffer, jsize bufferLength); +JI_API jclass java_interop_jnienv_find_class (JNIEnv *env, jthrowable *_thrown, const char* classname); +JI_API jobject java_interop_jnienv_to_reflected_method (JNIEnv *env, jthrowable *_thrown, jclass type, jmethodID method, jboolean isStatic); +JI_API jclass java_interop_jnienv_get_superclass (JNIEnv *env, jclass type); +JI_API jboolean java_interop_jnienv_is_assignable_from (JNIEnv *env, jclass class1, jclass class2); +JI_API jobject java_interop_jnienv_to_reflected_field (JNIEnv *env, jthrowable *_thrown, jclass type, jfieldID field, jboolean isStatic); +JI_API jint java_interop_jnienv_throw (JNIEnv *env, jthrowable toThrow); +JI_API jint java_interop_jnienv_throw_new (JNIEnv *env, jclass type, const char* message); +JI_API jthrowable java_interop_jnienv_exception_occurred (JNIEnv *env); +JI_API void java_interop_jnienv_exception_describe (JNIEnv *env); +JI_API void java_interop_jnienv_exception_clear (JNIEnv *env); +JI_API void java_interop_jnienv_fatal_error (JNIEnv *env, const char* message); +JI_API jint java_interop_jnienv_push_local_frame (JNIEnv *env, jint capacity); +JI_API jobject java_interop_jnienv_pop_local_frame (JNIEnv *env, jobject result); +JI_API jglobal java_interop_jnienv_new_global_ref (JNIEnv *env, jobject instance); +JI_API void java_interop_jnienv_delete_global_ref (JNIEnv *env, jobject instance); +JI_API void java_interop_jnienv_delete_local_ref (JNIEnv *env, jobject instance); +JI_API jboolean java_interop_jnienv_is_same_object (JNIEnv *env, jobject object1, jobject object2); +JI_API jobject java_interop_jnienv_new_local_ref (JNIEnv *env, jobject instance); +JI_API jint java_interop_jnienv_ensure_local_capacity (JNIEnv *env, jint capacity); +JI_API jobject java_interop_jnienv_alloc_object (JNIEnv *env, jthrowable *_thrown, jclass type); +JI_API jobject java_interop_jnienv_new_object (JNIEnv *env, jthrowable *_thrown, jclass type, jmethodID method); +JI_API jobject java_interop_jnienv_new_object_a (JNIEnv *env, jthrowable *_thrown, jclass type, jmethodID method, jvalue* args); +JI_API jclass java_interop_jnienv_get_object_class (JNIEnv *env, jobject instance); +JI_API jboolean java_interop_jnienv_is_instance_of (JNIEnv *env, jobject instance, jclass type); +JI_API jmethodID java_interop_jnienv_get_method_id (JNIEnv *env, jthrowable *_thrown, jclass type, const char* name, const char* signature); +JI_API jobject java_interop_jnienv_call_object_method (JNIEnv *env, jthrowable *_thrown, jobject instance, jmethodID method); +JI_API jobject java_interop_jnienv_call_object_method_a (JNIEnv *env, jthrowable *_thrown, jobject instance, jmethodID method, jvalue* args); +JI_API jboolean java_interop_jnienv_call_boolean_method (JNIEnv *env, jthrowable *_thrown, jobject instance, jmethodID method); +JI_API jboolean java_interop_jnienv_call_boolean_method_a (JNIEnv *env, jthrowable *_thrown, jobject instance, jmethodID method, jvalue* args); +JI_API jbyte java_interop_jnienv_call_byte_method (JNIEnv *env, jthrowable *_thrown, jobject instance, jmethodID method); +JI_API jbyte java_interop_jnienv_call_byte_method_a (JNIEnv *env, jthrowable *_thrown, jobject instance, jmethodID method, jvalue* args); +JI_API jchar java_interop_jnienv_call_char_method (JNIEnv *env, jthrowable *_thrown, jobject instance, jmethodID method); +JI_API jchar java_interop_jnienv_call_char_method_a (JNIEnv *env, jthrowable *_thrown, jobject instance, jmethodID method, jvalue* args); +JI_API jshort java_interop_jnienv_call_short_method (JNIEnv *env, jthrowable *_thrown, jobject instance, jmethodID method); +JI_API jshort java_interop_jnienv_call_short_method_a (JNIEnv *env, jthrowable *_thrown, jobject instance, jmethodID method, jvalue* args); +JI_API jint java_interop_jnienv_call_int_method (JNIEnv *env, jthrowable *_thrown, jobject instance, jmethodID method); +JI_API jint java_interop_jnienv_call_int_method_a (JNIEnv *env, jthrowable *_thrown, jobject instance, jmethodID method, jvalue* args); +JI_API jlong java_interop_jnienv_call_long_method (JNIEnv *env, jthrowable *_thrown, jobject instance, jmethodID method); +JI_API jlong java_interop_jnienv_call_long_method_a (JNIEnv *env, jthrowable *_thrown, jobject instance, jmethodID method, jvalue* args); +JI_API jfloat java_interop_jnienv_call_float_method (JNIEnv *env, jthrowable *_thrown, jobject instance, jmethodID method); +JI_API jfloat java_interop_jnienv_call_float_method_a (JNIEnv *env, jthrowable *_thrown, jobject instance, jmethodID method, jvalue* args); +JI_API jdouble java_interop_jnienv_call_double_method (JNIEnv *env, jthrowable *_thrown, jobject instance, jmethodID method); +JI_API jdouble java_interop_jnienv_call_double_method_a (JNIEnv *env, jthrowable *_thrown, jobject instance, jmethodID method, jvalue* args); +JI_API void java_interop_jnienv_call_void_method (JNIEnv *env, jthrowable *_thrown, jobject instance, jmethodID method); +JI_API void java_interop_jnienv_call_void_method_a (JNIEnv *env, jthrowable *_thrown, jobject instance, jmethodID method, jvalue* args); +JI_API jobject java_interop_jnienv_call_nonvirtual_object_method (JNIEnv *env, jthrowable *_thrown, jobject instance, jclass type, jmethodID method); +JI_API jobject java_interop_jnienv_call_nonvirtual_object_method_a (JNIEnv *env, jthrowable *_thrown, jobject instance, jclass type, jmethodID method, jvalue* args); +JI_API jboolean java_interop_jnienv_call_nonvirtual_boolean_method (JNIEnv *env, jthrowable *_thrown, jobject instance, jclass type, jmethodID method); +JI_API jboolean java_interop_jnienv_call_nonvirtual_boolean_method_a (JNIEnv *env, jthrowable *_thrown, jobject instance, jclass type, jmethodID method, jvalue* args); +JI_API jbyte java_interop_jnienv_call_nonvirtual_byte_method (JNIEnv *env, jthrowable *_thrown, jobject instance, jclass type, jmethodID method); +JI_API jbyte java_interop_jnienv_call_nonvirtual_byte_method_a (JNIEnv *env, jthrowable *_thrown, jobject instance, jclass type, jmethodID method, jvalue* args); +JI_API jchar java_interop_jnienv_call_nonvirtual_char_method (JNIEnv *env, jthrowable *_thrown, jobject instance, jclass type, jmethodID method); +JI_API jchar java_interop_jnienv_call_nonvirtual_char_method_a (JNIEnv *env, jthrowable *_thrown, jobject instance, jclass type, jmethodID method, jvalue* args); +JI_API jshort java_interop_jnienv_call_nonvirtual_short_method (JNIEnv *env, jthrowable *_thrown, jobject instance, jclass type, jmethodID method); +JI_API jshort java_interop_jnienv_call_nonvirtual_short_method_a (JNIEnv *env, jthrowable *_thrown, jobject instance, jclass type, jmethodID method, jvalue* args); +JI_API jint java_interop_jnienv_call_nonvirtual_int_method (JNIEnv *env, jthrowable *_thrown, jobject instance, jclass type, jmethodID method); +JI_API jint java_interop_jnienv_call_nonvirtual_int_method_a (JNIEnv *env, jthrowable *_thrown, jobject instance, jclass type, jmethodID method, jvalue* args); +JI_API jlong java_interop_jnienv_call_nonvirtual_long_method (JNIEnv *env, jthrowable *_thrown, jobject instance, jclass type, jmethodID method); +JI_API jlong java_interop_jnienv_call_nonvirtual_long_method_a (JNIEnv *env, jthrowable *_thrown, jobject instance, jclass type, jmethodID method, jvalue* args); +JI_API jfloat java_interop_jnienv_call_nonvirtual_float_method (JNIEnv *env, jthrowable *_thrown, jobject instance, jclass type, jmethodID method); +JI_API jfloat java_interop_jnienv_call_nonvirtual_float_method_a (JNIEnv *env, jthrowable *_thrown, jobject instance, jclass type, jmethodID method, jvalue* args); +JI_API jdouble java_interop_jnienv_call_nonvirtual_double_method (JNIEnv *env, jthrowable *_thrown, jobject instance, jclass type, jmethodID method); +JI_API jdouble java_interop_jnienv_call_nonvirtual_double_method_a (JNIEnv *env, jthrowable *_thrown, jobject instance, jclass type, jmethodID method, jvalue* args); +JI_API void java_interop_jnienv_call_nonvirtual_void_method (JNIEnv *env, jthrowable *_thrown, jobject instance, jclass type, jmethodID method); +JI_API void java_interop_jnienv_call_nonvirtual_void_method_a (JNIEnv *env, jthrowable *_thrown, jobject instance, jclass type, jmethodID method, jvalue* args); +JI_API jfieldID java_interop_jnienv_get_field_id (JNIEnv *env, jthrowable *_thrown, jclass type, const char* name, const char* signature); +JI_API jobject java_interop_jnienv_get_object_field (JNIEnv *env, jobject instance, jfieldID field); +JI_API jboolean java_interop_jnienv_get_boolean_field (JNIEnv *env, jobject instance, jfieldID field); +JI_API jbyte java_interop_jnienv_get_byte_field (JNIEnv *env, jobject instance, jfieldID field); +JI_API jchar java_interop_jnienv_get_char_field (JNIEnv *env, jobject instance, jfieldID field); +JI_API jshort java_interop_jnienv_get_short_field (JNIEnv *env, jobject instance, jfieldID field); +JI_API jint java_interop_jnienv_get_int_field (JNIEnv *env, jobject instance, jfieldID field); +JI_API jlong java_interop_jnienv_get_long_field (JNIEnv *env, jobject instance, jfieldID field); +JI_API jfloat java_interop_jnienv_get_float_field (JNIEnv *env, jobject instance, jfieldID field); +JI_API jdouble java_interop_jnienv_get_double_field (JNIEnv *env, jobject instance, jfieldID field); +JI_API void java_interop_jnienv_set_object_field (JNIEnv *env, jobject instance, jfieldID field, jobject value); +JI_API void java_interop_jnienv_set_boolean_field (JNIEnv *env, jobject instance, jfieldID field, jboolean value); +JI_API void java_interop_jnienv_set_byte_field (JNIEnv *env, jobject instance, jfieldID field, jbyte value); +JI_API void java_interop_jnienv_set_char_field (JNIEnv *env, jobject instance, jfieldID field, jchar value); +JI_API void java_interop_jnienv_set_short_field (JNIEnv *env, jobject instance, jfieldID field, jshort value); +JI_API void java_interop_jnienv_set_int_field (JNIEnv *env, jobject instance, jfieldID field, jint value); +JI_API void java_interop_jnienv_set_long_field (JNIEnv *env, jobject instance, jfieldID field, jlong value); +JI_API void java_interop_jnienv_set_float_field (JNIEnv *env, jobject instance, jfieldID field, jfloat value); +JI_API void java_interop_jnienv_set_double_field (JNIEnv *env, jobject instance, jfieldID field, jdouble value); +JI_API jstaticmethodID java_interop_jnienv_get_static_method_id (JNIEnv *env, jthrowable *_thrown, jclass type, const char* name, const char* signature); +JI_API jobject java_interop_jnienv_call_static_object_method (JNIEnv *env, jthrowable *_thrown, jclass type, jstaticmethodID method); +JI_API jobject java_interop_jnienv_call_static_object_method_a (JNIEnv *env, jthrowable *_thrown, jclass type, jstaticmethodID method, jvalue* args); +JI_API jboolean java_interop_jnienv_call_static_boolean_method (JNIEnv *env, jthrowable *_thrown, jclass type, jstaticmethodID method); +JI_API jboolean java_interop_jnienv_call_static_boolean_method_a (JNIEnv *env, jthrowable *_thrown, jclass type, jstaticmethodID method, jvalue* args); +JI_API jbyte java_interop_jnienv_call_static_byte_method (JNIEnv *env, jthrowable *_thrown, jclass type, jstaticmethodID method); +JI_API jbyte java_interop_jnienv_call_static_byte_method_a (JNIEnv *env, jthrowable *_thrown, jclass type, jstaticmethodID method, jvalue* args); +JI_API jchar java_interop_jnienv_call_static_char_method (JNIEnv *env, jthrowable *_thrown, jclass type, jstaticmethodID method); +JI_API jchar java_interop_jnienv_call_static_char_method_a (JNIEnv *env, jthrowable *_thrown, jclass type, jstaticmethodID method, jvalue* args); +JI_API jshort java_interop_jnienv_call_static_short_method (JNIEnv *env, jthrowable *_thrown, jclass type, jstaticmethodID method); +JI_API jshort java_interop_jnienv_call_static_short_method_a (JNIEnv *env, jthrowable *_thrown, jclass type, jstaticmethodID method, jvalue* args); +JI_API jint java_interop_jnienv_call_static_int_method (JNIEnv *env, jthrowable *_thrown, jclass type, jstaticmethodID method); +JI_API jint java_interop_jnienv_call_static_int_method_a (JNIEnv *env, jthrowable *_thrown, jclass type, jstaticmethodID method, jvalue* args); +JI_API jlong java_interop_jnienv_call_static_long_method (JNIEnv *env, jthrowable *_thrown, jclass type, jstaticmethodID method); +JI_API jlong java_interop_jnienv_call_static_long_method_a (JNIEnv *env, jthrowable *_thrown, jclass type, jstaticmethodID method, jvalue* args); +JI_API jfloat java_interop_jnienv_call_static_float_method (JNIEnv *env, jthrowable *_thrown, jclass type, jstaticmethodID method); +JI_API jfloat java_interop_jnienv_call_static_float_method_a (JNIEnv *env, jthrowable *_thrown, jclass type, jstaticmethodID method, jvalue* args); +JI_API jdouble java_interop_jnienv_call_static_double_method (JNIEnv *env, jthrowable *_thrown, jclass type, jstaticmethodID method); +JI_API jdouble java_interop_jnienv_call_static_double_method_a (JNIEnv *env, jthrowable *_thrown, jclass type, jstaticmethodID method, jvalue* args); +JI_API void java_interop_jnienv_call_static_void_method (JNIEnv *env, jthrowable *_thrown, jclass type, jstaticmethodID method); +JI_API void java_interop_jnienv_call_static_void_method_a (JNIEnv *env, jthrowable *_thrown, jclass type, jstaticmethodID method, jvalue* args); +JI_API jstaticfieldID java_interop_jnienv_get_static_field_id (JNIEnv *env, jthrowable *_thrown, jclass type, const char* name, const char* signature); +JI_API jobject java_interop_jnienv_get_static_object_field (JNIEnv *env, jclass type, jstaticfieldID field); +JI_API jboolean java_interop_jnienv_get_static_boolean_field (JNIEnv *env, jclass type, jstaticfieldID field); +JI_API jbyte java_interop_jnienv_get_static_byte_field (JNIEnv *env, jclass type, jstaticfieldID field); +JI_API jchar java_interop_jnienv_get_static_char_field (JNIEnv *env, jclass type, jstaticfieldID field); +JI_API jshort java_interop_jnienv_get_static_short_field (JNIEnv *env, jclass type, jstaticfieldID field); +JI_API jint java_interop_jnienv_get_static_int_field (JNIEnv *env, jclass type, jstaticfieldID field); +JI_API jlong java_interop_jnienv_get_static_long_field (JNIEnv *env, jclass type, jstaticfieldID field); +JI_API jfloat java_interop_jnienv_get_static_float_field (JNIEnv *env, jclass type, jstaticfieldID field); +JI_API jdouble java_interop_jnienv_get_static_double_field (JNIEnv *env, jclass type, jstaticfieldID field); +JI_API void java_interop_jnienv_set_static_object_field (JNIEnv *env, jclass type, jstaticfieldID field, jobject value); +JI_API void java_interop_jnienv_set_static_boolean_field (JNIEnv *env, jclass type, jstaticfieldID field, jboolean value); +JI_API void java_interop_jnienv_set_static_byte_field (JNIEnv *env, jclass type, jstaticfieldID field, jbyte value); +JI_API void java_interop_jnienv_set_static_char_field (JNIEnv *env, jclass type, jstaticfieldID field, jchar value); +JI_API void java_interop_jnienv_set_static_short_field (JNIEnv *env, jclass type, jstaticfieldID field, jshort value); +JI_API void java_interop_jnienv_set_static_int_field (JNIEnv *env, jclass type, jstaticfieldID field, jint value); +JI_API void java_interop_jnienv_set_static_long_field (JNIEnv *env, jclass type, jstaticfieldID field, jlong value); +JI_API void java_interop_jnienv_set_static_float_field (JNIEnv *env, jclass type, jstaticfieldID field, jfloat value); +JI_API void java_interop_jnienv_set_static_double_field (JNIEnv *env, jclass type, jstaticfieldID field, jdouble value); +JI_API jstring java_interop_jnienv_new_string (JNIEnv *env, jthrowable *_thrown, jchar* unicodeChars, jsize length); +JI_API jsize java_interop_jnienv_get_string_length (JNIEnv *env, jstring stringInstance); +JI_API const jchar* java_interop_jnienv_get_string_chars (JNIEnv *env, jstring stringInstance, jboolean* isCopy); +JI_API void java_interop_jnienv_release_string_chars (JNIEnv *env, jstring stringInstance, jchar* chars); +JI_API jsize java_interop_jnienv_get_array_length (JNIEnv *env, jarray array); +JI_API jobjectArray java_interop_jnienv_new_object_array (JNIEnv *env, jthrowable *_thrown, jsize length, jclass elementClass, jobject initialElement); +JI_API jobject java_interop_jnienv_get_object_array_element (JNIEnv *env, jthrowable *_thrown, jobjectArray array, jsize index); +JI_API void java_interop_jnienv_set_object_array_element (JNIEnv *env, jthrowable *_thrown, jobjectArray array, jsize index, jobject value); +JI_API jbooleanArray java_interop_jnienv_new_boolean_array (JNIEnv *env, jsize length); +JI_API jbyteArray java_interop_jnienv_new_byte_array (JNIEnv *env, jsize length); +JI_API jcharArray java_interop_jnienv_new_char_array (JNIEnv *env, jsize length); +JI_API jshortArray java_interop_jnienv_new_short_array (JNIEnv *env, jsize length); +JI_API jintArray java_interop_jnienv_new_int_array (JNIEnv *env, jsize length); +JI_API jlongArray java_interop_jnienv_new_long_array (JNIEnv *env, jsize length); +JI_API jfloatArray java_interop_jnienv_new_float_array (JNIEnv *env, jsize length); +JI_API jdoubleArray java_interop_jnienv_new_double_array (JNIEnv *env, jsize length); +JI_API jboolean* java_interop_jnienv_get_boolean_array_elements (JNIEnv *env, jbooleanArray array, jboolean* isCopy); +JI_API jbyte* java_interop_jnienv_get_byte_array_elements (JNIEnv *env, jbyteArray array, jboolean* isCopy); +JI_API jchar* java_interop_jnienv_get_char_array_elements (JNIEnv *env, jcharArray array, jboolean* isCopy); +JI_API jshort* java_interop_jnienv_get_short_array_elements (JNIEnv *env, jshortArray array, jboolean* isCopy); +JI_API jint* java_interop_jnienv_get_int_array_elements (JNIEnv *env, jintArray array, jboolean* isCopy); +JI_API jlong* java_interop_jnienv_get_long_array_elements (JNIEnv *env, jlongArray array, jboolean* isCopy); +JI_API jfloat* java_interop_jnienv_get_float_array_elements (JNIEnv *env, jfloatArray array, jboolean* isCopy); +JI_API jdouble* java_interop_jnienv_get_double_array_elements (JNIEnv *env, jdoubleArray array, jboolean* isCopy); +JI_API void java_interop_jnienv_release_boolean_array_elements (JNIEnv *env, jbooleanArray array, jboolean* elements, jint mode); +JI_API void java_interop_jnienv_release_byte_array_elements (JNIEnv *env, jbyteArray array, jbyte* elements, jint mode); +JI_API void java_interop_jnienv_release_char_array_elements (JNIEnv *env, jcharArray array, jchar* elements, jint mode); +JI_API void java_interop_jnienv_release_short_array_elements (JNIEnv *env, jshortArray array, jshort* elements, jint mode); +JI_API void java_interop_jnienv_release_int_array_elements (JNIEnv *env, jintArray array, jint* elements, jint mode); +JI_API void java_interop_jnienv_release_long_array_elements (JNIEnv *env, jlongArray array, jlong* elements, jint mode); +JI_API void java_interop_jnienv_release_float_array_elements (JNIEnv *env, jfloatArray array, jfloat* elements, jint mode); +JI_API void java_interop_jnienv_release_double_array_elements (JNIEnv *env, jdoubleArray array, jdouble* elements, jint mode); +JI_API void java_interop_jnienv_get_boolean_array_region (JNIEnv *env, jthrowable *_thrown, jbooleanArray array, jsize start, jsize length, jboolean* buffer); +JI_API void java_interop_jnienv_get_byte_array_region (JNIEnv *env, jthrowable *_thrown, jbyteArray array, jsize start, jsize length, jbyte* buffer); +JI_API void java_interop_jnienv_get_char_array_region (JNIEnv *env, jthrowable *_thrown, jcharArray array, jsize start, jsize length, jchar* buffer); +JI_API void java_interop_jnienv_get_short_array_region (JNIEnv *env, jthrowable *_thrown, jshortArray array, jsize start, jsize length, jshort* buffer); +JI_API void java_interop_jnienv_get_int_array_region (JNIEnv *env, jthrowable *_thrown, jintArray array, jsize start, jsize length, jint* buffer); +JI_API void java_interop_jnienv_get_long_array_region (JNIEnv *env, jthrowable *_thrown, jlongArray array, jsize start, jsize length, jlong* buffer); +JI_API void java_interop_jnienv_get_float_array_region (JNIEnv *env, jthrowable *_thrown, jlongArray array, jsize start, jsize length, jfloat* buffer); +JI_API void java_interop_jnienv_get_double_array_region (JNIEnv *env, jthrowable *_thrown, jdoubleArray array, jsize start, jsize length, jdouble* buffer); +JI_API void java_interop_jnienv_set_boolean_array_region (JNIEnv *env, jthrowable *_thrown, jbooleanArray array, jsize start, jsize length, jboolean* buffer); +JI_API void java_interop_jnienv_set_byte_array_region (JNIEnv *env, jthrowable *_thrown, jbyteArray array, jsize start, jsize length, jbyte* buffer); +JI_API void java_interop_jnienv_set_char_array_region (JNIEnv *env, jthrowable *_thrown, jcharArray array, jsize start, jsize length, const jchar* buffer); +JI_API void java_interop_jnienv_set_short_array_region (JNIEnv *env, jthrowable *_thrown, jshortArray array, jsize start, jsize length, jshort* buffer); +JI_API void java_interop_jnienv_set_int_array_region (JNIEnv *env, jthrowable *_thrown, jintArray array, jsize start, jsize length, jint* buffer); +JI_API void java_interop_jnienv_set_long_array_region (JNIEnv *env, jthrowable *_thrown, jlongArray array, jsize start, jsize length, jlong* buffer); +JI_API void java_interop_jnienv_set_float_array_region (JNIEnv *env, jthrowable *_thrown, jfloatArray array, jsize start, jsize length, jfloat* buffer); +JI_API void java_interop_jnienv_set_double_array_region (JNIEnv *env, jthrowable *_thrown, jdoubleArray array, jsize start, jsize length, jdouble* buffer); +JI_API jint java_interop_jnienv_register_natives (JNIEnv *env, jthrowable *_thrown, jclass type, const JNINativeMethod* methods, jint numMethods); +JI_API jint java_interop_jnienv_unregister_natives (JNIEnv *env, jclass type); +JI_API jint java_interop_jnienv_monitor_enter (JNIEnv *env, jobject instance); +JI_API jint java_interop_jnienv_monitor_exit (JNIEnv *env, jobject instance); +JI_API jint java_interop_jnienv_get_java_vm (JNIEnv *env, JavaVM** vm); +JI_API void* java_interop_jnienv_get_primitive_array_critical (JNIEnv *env, jarray array, jboolean* isCopy); +JI_API void java_interop_jnienv_release_primitive_array_critical (JNIEnv *env, jarray array, void* carray, jint mode); +JI_API jweak java_interop_jnienv_new_weak_global_ref (JNIEnv *env, jobject instance); +JI_API void java_interop_jnienv_delete_weak_global_ref (JNIEnv *env, jobject instance); +JI_API jboolean java_interop_jnienv_exception_check (JNIEnv *env); +JI_API jobject java_interop_jnienv_new_direct_byte_buffer (JNIEnv *env, jthrowable *_thrown, void* address, jlong capacity); +JI_API void* java_interop_jnienv_get_direct_buffer_address (JNIEnv *env, jobject buffer); +JI_API jlong java_interop_jnienv_get_direct_buffer_capacity (JNIEnv *env, jobject buffer); +JI_API jobjectRefType java_interop_jnienv_get_object_ref_type (JNIEnv *env, jobject instance); + +#endif // __JAVA_INTEROP_NATIVE_H diff --git a/src/monodroid/jni/mono_android_Runtime.h b/src/monodroid/jni/mono_android_Runtime.h index 40f51c63825..0e5aa37d095 100644 --- a/src/monodroid/jni/mono_android_Runtime.h +++ b/src/monodroid/jni/mono_android_Runtime.h @@ -39,6 +39,7 @@ JNIEXPORT void JNICALL Java_mono_android_Runtime_register JNIEXPORT void JNICALL Java_mono_android_Runtime_notifyTimeZoneChanged (JNIEnv *, jclass); +#if !defined (ANDROID) /* * Class: mono_android_Runtime * Method: createNewContext @@ -70,6 +71,7 @@ JNIEXPORT void JNICALL Java_mono_android_Runtime_switchToContext */ JNIEXPORT void JNICALL Java_mono_android_Runtime_destroyContexts (JNIEnv *, jclass, jintArray); +#endif // ndef ANDROID /* * Class: mono_android_Runtime diff --git a/src/monodroid/jni/monodroid-glue-designer.cc b/src/monodroid/jni/monodroid-glue-designer.cc new file mode 100644 index 00000000000..422e45e3c12 --- /dev/null +++ b/src/monodroid/jni/monodroid-glue-designer.cc @@ -0,0 +1,147 @@ +// +// Android designer support code, not used on devices +// +#include "globals.hh" +#include "mono_android_Runtime.h" +#include "monodroid-glue-internal.hh" + +using namespace xamarin::android::internal; + +// DO NOT USE ON NORMAL X.A +// This function only works with the custom TypeManager embedded with the designer process. +force_inline static void +reinitialize_android_runtime_type_manager (JNIEnv *env) +{ + jclass typeManager = env->FindClass ("mono/android/TypeManager"); + env->UnregisterNatives (typeManager); + + jmethodID resetRegistration = env->GetStaticMethodID (typeManager, "resetRegistration", "()V"); + env->CallStaticVoidMethod (typeManager, resetRegistration); + + env->DeleteLocalRef (typeManager); +} + +inline void +MonodroidRuntime::shutdown_android_runtime (MonoDomain *domain) +{ + MonoClass *runtime = get_android_runtime_class (domain); + MonoMethod *method = mono_class_get_method_from_name (runtime, "Exit", 0); + + utils.monodroid_runtime_invoke (domain, method, nullptr, nullptr, nullptr); +} + +inline jint +MonodroidRuntime::Java_mono_android_Runtime_createNewContextWithData (JNIEnv *env, jclass klass, jobjectArray runtimeApksJava, jobjectArray assembliesJava, + jobjectArray assembliesBytes, jobjectArray assembliesPaths, jobject loader, jboolean force_preload_assemblies) +{ + log_info (LOG_DEFAULT, "CREATING NEW CONTEXT"); + reinitialize_android_runtime_type_manager (env); + MonoDomain *root_domain = mono_get_root_domain (); + mono_jit_thread_attach (root_domain); + + jstring_array_wrapper runtimeApks (env, runtimeApksJava); + jstring_array_wrapper assemblies (env, assembliesJava); + jstring_array_wrapper assembliePaths (env, assembliesPaths); + MonoDomain *domain = create_and_initialize_domain (env, klass, runtimeApks, assemblies, assembliesBytes, assembliePaths, loader, /*is_root_domain:*/ false, force_preload_assemblies); + mono_domain_set (domain, FALSE); + int domain_id = mono_domain_get_id (domain); + current_context_id = domain_id; + log_info (LOG_DEFAULT, "Created new context with id %d\n", domain_id); + return domain_id; +} + +inline void +MonodroidRuntime::Java_mono_android_Runtime_switchToContext (JNIEnv *env, jint contextID) +{ + log_info (LOG_DEFAULT, "SWITCHING CONTEXT"); + MonoDomain *domain = mono_domain_get_by_id ((int)contextID); + if (current_context_id != (int)contextID) { + mono_domain_set (domain, TRUE); + // Reinitialize TypeManager so that its JNI handle goes into the right domain + reinitialize_android_runtime_type_manager (env); + } + current_context_id = (int)contextID; +} + +inline void +MonodroidRuntime::Java_mono_android_Runtime_destroyContexts (JNIEnv *env, jintArray array) +{ + MonoDomain *root_domain = mono_get_root_domain (); + mono_jit_thread_attach (root_domain); + current_context_id = -1; + + jint *contextIDs = env->GetIntArrayElements (array, nullptr); + jsize count = env->GetArrayLength (array); + + log_info (LOG_DEFAULT, "Cleaning %d domains", count); + + for (jsize i = 0; i < count; i++) { + int domain_id = contextIDs[i]; + MonoDomain *domain = mono_domain_get_by_id (domain_id); + + if (domain == nullptr) + continue; + log_info (LOG_DEFAULT, "Shutting down domain `%d'", contextIDs[i]); + shutdown_android_runtime (domain); + osBridge.remove_monodroid_domain (domain); + designerAssemblies.clear_for_domain (domain); + } + osBridge.on_destroy_contexts (); + for (jsize i = 0; i < count; i++) { + int domain_id = contextIDs[i]; + MonoDomain *domain = mono_domain_get_by_id (domain_id); + + if (domain == nullptr) + continue; + log_info (LOG_DEFAULT, "Unloading domain `%d'", contextIDs[i]); + mono_domain_unload (domain); + } + env->ReleaseIntArrayElements (array, contextIDs, JNI_ABORT); + + reinitialize_android_runtime_type_manager (env); + + log_info (LOG_DEFAULT, "All domain cleaned up"); +} + +JNIEXPORT jint +JNICALL Java_mono_android_Runtime_createNewContextWithData (JNIEnv *env, jclass klass, jobjectArray runtimeApksJava, jobjectArray assembliesJava, jobjectArray assembliesBytes, jobjectArray assembliesPaths, jobject loader, jboolean force_preload_assemblies) +{ + return monodroidRuntime.Java_mono_android_Runtime_createNewContextWithData ( + env, + klass, + runtimeApksJava, + assembliesJava, + assembliesBytes, + assembliesPaths, + loader, + force_preload_assemblies + ); +} + +/* !DO NOT REMOVE! Used by older versions of the Android Designer (pre-16.4) */ +JNIEXPORT jint +JNICALL Java_mono_android_Runtime_createNewContext (JNIEnv *env, jclass klass, jobjectArray runtimeApksJava, jobjectArray assembliesJava, jobject loader) +{ + return monodroidRuntime.Java_mono_android_Runtime_createNewContextWithData ( + env, + klass, + runtimeApksJava, + assembliesJava, + nullptr, // assembliesBytes + nullptr, // assembliesPaths + loader, + false // force_preload_assemblies + ); +} + +JNIEXPORT void +JNICALL Java_mono_android_Runtime_switchToContext (JNIEnv *env, [[maybe_unused]] jclass klass, jint contextID) +{ + monodroidRuntime.Java_mono_android_Runtime_switchToContext (env, contextID); +} + +JNIEXPORT void +JNICALL Java_mono_android_Runtime_destroyContexts (JNIEnv *env, [[maybe_unused]] jclass klass, jintArray array) +{ + monodroidRuntime.Java_mono_android_Runtime_destroyContexts (env, array); +} diff --git a/src/monodroid/jni/monodroid-glue-internal.hh b/src/monodroid/jni/monodroid-glue-internal.hh index 1dc9dfee2b7..9369f5a29b4 100644 --- a/src/monodroid/jni/monodroid-glue-internal.hh +++ b/src/monodroid/jni/monodroid-glue-internal.hh @@ -2,6 +2,7 @@ #ifndef __MONODROID_GLUE_INTERNAL_H #define __MONODROID_GLUE_INTERNAL_H +#include #include #include "android-system.hh" #include "osbridge.hh" @@ -10,10 +11,65 @@ #include #include +#if defined (NET6) +// NDEBUG causes robin_map.h not to include which, in turn, prevents indirect inclusion of . +// conflicts with our std::mutex definition in cppcompat.hh +#if !defined (NDEBUG) +#define NDEBUG +#define NDEBUG_UNDEFINE +#endif + +// hush some compiler warnings +#if defined (__clang__) +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunused-parameter" +#endif // __clang__ + +#include + +#if defined (__clang__) +#pragma clang diagnostic pop +#endif // __clang__ + +#if defined (NDEBUG_UNDEFINE) +#undef NDEBUG +#undef NDEBUG_UNDEFINE +#endif + +#include +#include + +// This should be defined in the public Mono headers +typedef void * (*PInvokeOverrideFn) (const char *libraryName, const char *entrypointName); +#endif + namespace xamarin::android::internal { class MonodroidRuntime { +#if defined (NET6) + using pinvoke_api_map = tsl::robin_map< + std::string, + void*, + std::hash, + std::equal_to, + std::allocator>, + true + >; + + using pinvoke_api_map_ptr = pinvoke_api_map*; + using pinvoke_library_map = tsl::robin_map< + std::string, + pinvoke_api_map_ptr, + std::hash, + std::equal_to, + std::allocator>, + true + >; + + static constexpr pinvoke_library_map::size_type LIBRARY_MAP_INITIAL_BUCKET_COUNT = 1; +#endif // def NET6 + #if defined (DEBUG) && !defined (WINDOWS) struct RuntimeOptions { bool debug = false; @@ -61,6 +117,7 @@ namespace xamarin::android::internal #else true; #endif + #define MAKE_API_DSO_NAME(_ext_) "libxa-internal-api." # _ext_ #if defined (WINDOWS) static constexpr char API_DSO_NAME[] = MAKE_API_DSO_NAME (dll); @@ -70,6 +127,12 @@ namespace xamarin::android::internal static constexpr char API_DSO_NAME[] = MAKE_API_DSO_NAME (so); #endif // defined(WINDOWS) public: + static constexpr bool is_net6 = +#if NET6 + true; +#else // def NET6 + false; +#endif // ndef NET6 static constexpr int XA_LOG_COUNTERS = MONO_COUNTER_JIT | MONO_COUNTER_METADATA | MONO_COUNTER_GC | MONO_COUNTER_GENERICS | MONO_COUNTER_INTERP; public: @@ -77,10 +140,13 @@ namespace xamarin::android::internal void Java_mono_android_Runtime_initInternal (JNIEnv *env, jclass klass, jstring lang, jobjectArray runtimeApksJava, jstring runtimeNativeLibDir, jobjectArray appDirs, jobject loader, jobjectArray assembliesJava, jint apiLevel, jboolean isEmulator); +#if !defined (ANDROID) jint Java_mono_android_Runtime_createNewContextWithData (JNIEnv *env, jclass klass, jobjectArray runtimeApksJava, jobjectArray assembliesJava, jobjectArray assembliesBytes, jobjectArray assembliesPaths, jobject loader, jboolean force_preload_assemblies); void Java_mono_android_Runtime_switchToContext (JNIEnv *env, jint contextID); void Java_mono_android_Runtime_destroyContexts (JNIEnv *env, jintArray array); + void shutdown_android_runtime (MonoDomain *domain); +#endif jint Java_JNI_OnLoad (JavaVM *vm, void *reserved); int get_android_api_level () const @@ -139,10 +205,18 @@ namespace xamarin::android::internal #if defined (WINDOWS) || defined (APPLE_OS_X) static const char* get_my_location (bool remove_file_name = true); #endif // defined(WINDOWS) || defined(APPLE_OS_X) +#if defined (NET6) + static void* load_library_entry (std::string const& library_name, std::string const& entrypoint_name, pinvoke_api_map_ptr api_map); + static void* fetch_or_create_pinvoke_map_entry (std::string const& library_name, std::string const& entrypoint_name, pinvoke_api_map_ptr api_map, bool need_lock); + static void* monodroid_pinvoke_override (const char *library_name, const char *entrypoint_name); + static void* monodroid_dlopen (const char *name, int flags, char **err); +#endif // def NET6 static void* monodroid_dlopen (const char *name, int flags, char **err, void *user_data); static void* monodroid_dlsym (void *handle, const char *name, char **err, void *user_data); static void* monodroid_dlopen_log_and_return (void *handle, char **err, const char *full_name, bool free_memory, bool need_api_init = false); +#if !defined (NET6) static void init_internal_api_dso (void *handle); +#endif // ndef NET6 int LocalRefsAreIndirect (JNIEnv *env, jclass runtimeClass, int version); void create_xdg_directory (jstring_wrapper& home, size_t home_len, const char *relativePath, size_t relative_path_len, const char *environmentVariableName); void create_xdg_directories_and_environment (jstring_wrapper &homeDir); @@ -168,7 +242,6 @@ namespace xamarin::android::internal } MonoClass* get_android_runtime_class (MonoDomain *domain); - void shutdown_android_runtime (MonoDomain *domain); MonoDomain* create_domain (JNIEnv *env, jstring_array_wrapper &runtimeApks, bool is_root_domain); MonoDomain* create_and_initialize_domain (JNIEnv* env, jclass runtimeClass, jstring_array_wrapper &runtimeApks, jstring_array_wrapper &assemblies, jobjectArray assembliesBytes, jstring_array_wrapper &assembliesPaths, @@ -227,8 +300,14 @@ namespace xamarin::android::internal */ int current_context_id = -1; +#if defined (NET6) + static std::mutex pinvoke_map_write_lock; + static pinvoke_api_map xa_pinvoke_map; + static pinvoke_library_map other_pinvoke_map; +#else // def NET6 static std::mutex api_init_lock; static void *api_dso_handle; +#endif // !def NET6 }; } #endif diff --git a/src/monodroid/jni/monodroid-glue.cc b/src/monodroid/jni/monodroid-glue.cc index f7dc3ec1c51..634fd108ad6 100644 --- a/src/monodroid/jni/monodroid-glue.cc +++ b/src/monodroid/jni/monodroid-glue.cc @@ -1,7 +1,6 @@ #include #include #include -#include #include #include @@ -99,11 +98,17 @@ using namespace xamarin::android::internal; // implementation details as it would prevent mkbundle from working #include "mkbundle-api.h" +#if !defined (NET6) #include "config.include" +#endif // ndef NET6 #include "machine.config.include" +#if defined (NET6) +std::mutex MonodroidRuntime::pinvoke_map_write_lock; +#else // def NET6 std::mutex MonodroidRuntime::api_init_lock; void *MonodroidRuntime::api_dso_handle = nullptr; +#endif // ndef NET6 #ifdef WINDOWS static const char* get_xamarin_android_msbuild_path (void); @@ -395,9 +400,7 @@ MonodroidRuntime::gather_bundled_assemblies (jstring_array_wrapper &runtimeApks, size_t cur_num_assemblies = embeddedAssemblies.register_from (apk_file.get_cstr ()); - if (strstr (apk_file.get_cstr (), "/Mono.Android.DebugRuntime") == nullptr && - strstr (apk_file.get_cstr (), "/Mono.Android.Platform.ApiLevel_") == nullptr) - *out_user_assemblies_count += (cur_num_assemblies - prev_num_assemblies); + *out_user_assemblies_count += (cur_num_assemblies - prev_num_assemblies); prev_num_assemblies = cur_num_assemblies; } } @@ -1013,7 +1016,7 @@ MonodroidRuntime::init_android_runtime (MonoDomain *domain, JNIEnv *env, jclass } } -inline MonoClass* +MonoClass* MonodroidRuntime::get_android_runtime_class (MonoDomain *domain) { MonoAssembly *assm = utils.monodroid_load_assembly (domain, "Mono.Android"); @@ -1023,15 +1026,6 @@ MonodroidRuntime::get_android_runtime_class (MonoDomain *domain) return runtime; } -inline void -MonodroidRuntime::shutdown_android_runtime (MonoDomain *domain) -{ - MonoClass *runtime = get_android_runtime_class (domain); - MonoMethod *method = mono_class_get_method_from_name (runtime, "Exit", 0); - - utils.monodroid_runtime_invoke (domain, method, nullptr, nullptr, nullptr); -} - inline void MonodroidRuntime::propagate_uncaught_exception (MonoDomain *domain, JNIEnv *env, jobject javaThread, jthrowable javaException) { @@ -1066,6 +1060,7 @@ MonodroidRuntime::convert_dl_flags (int flags) return lflags; } +#if !defined (NET6) force_inline void MonodroidRuntime::init_internal_api_dso (void *handle) { @@ -1113,9 +1108,10 @@ MonodroidRuntime::init_internal_api_dso (void *handle) exit (FATAL_EXIT_MONO_MISSING_SYMBOLS); } } +#endif // ndef NET6 force_inline void* -MonodroidRuntime::monodroid_dlopen_log_and_return (void *handle, char **err, const char *full_name, bool free_memory, bool need_api_init) +MonodroidRuntime::monodroid_dlopen_log_and_return (void *handle, char **err, const char *full_name, bool free_memory, [[maybe_unused]] bool need_api_init) { if (handle == nullptr && err != nullptr) { *err = utils.monodroid_strdup_printf ("Could not load library: Library '%s' not found.", full_name); @@ -1125,14 +1121,77 @@ MonodroidRuntime::monodroid_dlopen_log_and_return (void *handle, char **err, con delete[] full_name; } +#if !defined (NET6) if (!need_api_init) return handle; - init_internal_api_dso (handle); +#endif // ndef NET6 return handle; } +#if defined (NET6) && defined (ANDROID) +force_inline void* +MonodroidRuntime::monodroid_dlopen (const char *name, int flags, char **err) +{ + unsigned int dl_flags = monodroidRuntime.convert_dl_flags (flags); + void *h = androidSystem.load_dso_from_any_directories (name, dl_flags); + if (h != nullptr) { + return monodroid_dlopen_log_and_return (h, err, name, false /* name_needs_free */); + } + + if (!utils.ends_with (name, ".dll.so")) { + return monodroid_dlopen_log_and_return (h, err, name, false /* name_needs_free */); + } + + char *basename_part = const_cast (strrchr (name, '/')); + if (basename_part != nullptr) { + basename_part++; + } else { + basename_part = (char*)name; + } + + constexpr char LIBAOT_PREFIX[] = "libaot-"; + constexpr size_t LIBAOT_PREFIX_SIZE = sizeof(LIBAOT_PREFIX); + + size_t base_len = strlen (basename_part); + size_t len = base_len + LIBAOT_PREFIX_SIZE; // includes the trailing \0 + static_local_string basename (len); + + basename.append (LIBAOT_PREFIX).append (basename_part); + + h = androidSystem.load_dso_from_any_directories (basename.get (), dl_flags); + + if (h != nullptr && XA_UNLIKELY (utils.should_log (LOG_ASSEMBLY))) { + log_info_nocheck (LOG_ASSEMBLY, "Loaded AOT image '%s'", basename.get ()); + } + + return h; +} + +void* +MonodroidRuntime::monodroid_dlopen (const char *name, int flags, char **err, [[maybe_unused]] void *user_data) +{ + log_warn (LOG_DEFAULT, "MonodroidRuntime::monodroid_dlopen (\"%s\", 0x%x, %p, %p)", name, flags, err, user_data); + if (name == nullptr) { + log_warn (LOG_ASSEMBLY, "monodroid_dlopen got a null name. This is not supported in NET6+"); + return nullptr; + } + + constexpr char DSO_EXTENSION[] = ".so"; + constexpr size_t DSO_EXTENSION_SIZE = sizeof(DSO_EXTENSION); + + if (utils.ends_with (name, DSO_EXTENSION)) { + return monodroid_dlopen (name, flags, err); + } + + size_t len = ADD_WITH_OVERFLOW_CHECK (size_t, strlen (name), DSO_EXTENSION_SIZE); // includes the trailing \0 + static_local_string full_name (len); + + full_name.append (name).append (DSO_EXTENSION); + return monodroid_dlopen (full_name.get (), flags, err); +} +#else // def NET6 && def ANDROID void* MonodroidRuntime::monodroid_dlopen (const char *name, int flags, char **err, [[maybe_unused]] void *user_data) { @@ -1252,6 +1311,7 @@ MonodroidRuntime::monodroid_dlopen (const char *name, int flags, char **err, [[m return h; } +#endif // !(def NET6 && def ANDROID) void* MonodroidRuntime::monodroid_dlsym (void *handle, const char *name, char **err, [[maybe_unused]] void *user_data) @@ -1635,6 +1695,20 @@ MonodroidRuntime::Java_mono_android_Runtime_initInternal (JNIEnv *env, jclass kl total_time.mark_start (); } +#if defined (NET6) + { + PInvokeOverrideFn pinvoke_override_cb = monodroid_pinvoke_override; + char ptr_str[20]; + snprintf (ptr_str, sizeof(ptr_str), "%p", pinvoke_override_cb); + + const char* property_keys[] { "PINVOKE_OVERRIDE" }; + const char* property_values[] { ptr_str }; + + log_warn (LOG_DEFAULT, "Initializing .NET6 Mono VM (override callback at %p, passed as %s", pinvoke_override_cb, ptr_str); + monovm_initialize (1, property_keys, property_values); + } +#endif // def NET6 + jstring_array_wrapper applicationDirs (env, appDirs); android_api_level = apiLevel; @@ -1710,8 +1784,9 @@ MonodroidRuntime::Java_mono_android_Runtime_initInternal (JNIEnv *env, jclass kl #endif // defined(WINDOWS) || defined(APPLE_OS_X) if (dso_handle == nullptr) dso_handle = androidSystem.load_dso_from_any_directories (API_DSO_NAME, JAVA_INTEROP_LIB_LOAD_GLOBALLY); +#if !defined (NET6) init_internal_api_dso (dso_handle); - +#endif // ndef NET6 mono_dl_fallback_register (monodroid_dlopen, monodroid_dlsym, nullptr, nullptr); set_profile_options (); @@ -1722,7 +1797,9 @@ MonodroidRuntime::Java_mono_android_Runtime_initInternal (JNIEnv *env, jclass kl debug.start_debugging_and_profiling (); #endif +#if !defined (NET6) mono_config_parse_memory (reinterpret_cast (monodroid_config)); +#endif // ndef NET6 mono_register_machine_config (reinterpret_cast (monodroid_machine_config)); log_info (LOG_DEFAULT, "Probing for Mono AOT mode\n"); @@ -1928,97 +2005,6 @@ JNICALL Java_mono_android_Runtime_register (JNIEnv *env, [[maybe_unused]] jclass monodroidRuntime.Java_mono_android_Runtime_register (env, managedType, nativeClass, methods); } -// DO NOT USE ON NORMAL X.A -// This function only works with the custom TypeManager embedded with the designer process. -static void -reinitialize_android_runtime_type_manager (JNIEnv *env) -{ - jclass typeManager = env->FindClass ("mono/android/TypeManager"); - env->UnregisterNatives (typeManager); - - jmethodID resetRegistration = env->GetStaticMethodID (typeManager, "resetRegistration", "()V"); - env->CallStaticVoidMethod (typeManager, resetRegistration); - - env->DeleteLocalRef (typeManager); -} - -inline jint -MonodroidRuntime::Java_mono_android_Runtime_createNewContextWithData (JNIEnv *env, jclass klass, jobjectArray runtimeApksJava, jobjectArray assembliesJava, - jobjectArray assembliesBytes, jobjectArray assembliesPaths, jobject loader, jboolean force_preload_assemblies) -{ - log_info (LOG_DEFAULT, "CREATING NEW CONTEXT"); - reinitialize_android_runtime_type_manager (env); - MonoDomain *root_domain = mono_get_root_domain (); - mono_jit_thread_attach (root_domain); - - jstring_array_wrapper runtimeApks (env, runtimeApksJava); - jstring_array_wrapper assemblies (env, assembliesJava); - jstring_array_wrapper assembliePaths (env, assembliesPaths); - MonoDomain *domain = create_and_initialize_domain (env, klass, runtimeApks, assemblies, assembliesBytes, assembliePaths, loader, /*is_root_domain:*/ false, force_preload_assemblies); - mono_domain_set (domain, FALSE); - int domain_id = mono_domain_get_id (domain); - current_context_id = domain_id; - log_info (LOG_DEFAULT, "Created new context with id %d\n", domain_id); - return domain_id; -} - -inline void -MonodroidRuntime::Java_mono_android_Runtime_switchToContext (JNIEnv *env, jint contextID) -{ - log_info (LOG_DEFAULT, "SWITCHING CONTEXT"); - MonoDomain *domain = mono_domain_get_by_id ((int)contextID); - if (current_context_id != (int)contextID) { - mono_domain_set (domain, TRUE); - // Reinitialize TypeManager so that its JNI handle goes into the right domain - reinitialize_android_runtime_type_manager (env); - } - current_context_id = (int)contextID; -} - -inline void -MonodroidRuntime::Java_mono_android_Runtime_destroyContexts (JNIEnv *env, jintArray array) -{ - MonoDomain *root_domain = mono_get_root_domain (); - mono_jit_thread_attach (root_domain); - current_context_id = -1; - - jint *contextIDs = env->GetIntArrayElements (array, nullptr); - jsize count = env->GetArrayLength (array); - - log_info (LOG_DEFAULT, "Cleaning %d domains", count); - - for (jsize i = 0; i < count; i++) { - int domain_id = contextIDs[i]; - MonoDomain *domain = mono_domain_get_by_id (domain_id); - - if (domain == nullptr) - continue; - log_info (LOG_DEFAULT, "Shutting down domain `%d'", contextIDs[i]); - shutdown_android_runtime (domain); - osBridge.remove_monodroid_domain (domain); -#ifndef ANDROID - designerAssemblies.clear_for_domain (domain); -#endif - } - osBridge.on_destroy_contexts (); -#ifndef ANDROID - for (jsize i = 0; i < count; i++) { - int domain_id = contextIDs[i]; - MonoDomain *domain = mono_domain_get_by_id (domain_id); - - if (domain == nullptr) - continue; - log_info (LOG_DEFAULT, "Unloading domain `%d'", contextIDs[i]); - mono_domain_unload (domain); - } -#endif // !defined(ANDROID) - env->ReleaseIntArrayElements (array, contextIDs, JNI_ABORT); - - reinitialize_android_runtime_type_manager (env); - - log_info (LOG_DEFAULT, "All domain cleaned up"); -} - char* MonodroidRuntime::get_java_class_name_for_TypeManager (jclass klass) { @@ -2058,49 +2044,6 @@ get_jnienv (void) return osBridge.ensure_jnienv (); } -JNIEXPORT jint -JNICALL Java_mono_android_Runtime_createNewContextWithData (JNIEnv *env, jclass klass, jobjectArray runtimeApksJava, jobjectArray assembliesJava, jobjectArray assembliesBytes, jobjectArray assembliesPaths, jobject loader, jboolean force_preload_assemblies) -{ - return monodroidRuntime.Java_mono_android_Runtime_createNewContextWithData ( - env, - klass, - runtimeApksJava, - assembliesJava, - assembliesBytes, - assembliesPaths, - loader, - force_preload_assemblies - ); -} - -/* !DO NOT REMOVE! Used by older versions of the Android Designer (pre-16.4) */ -JNIEXPORT jint -JNICALL Java_mono_android_Runtime_createNewContext (JNIEnv *env, jclass klass, jobjectArray runtimeApksJava, jobjectArray assembliesJava, jobject loader) -{ - return monodroidRuntime.Java_mono_android_Runtime_createNewContextWithData ( - env, - klass, - runtimeApksJava, - assembliesJava, - nullptr, // assembliesBytes - nullptr, // assembliesPaths - loader, - false // force_preload_assemblies - ); -} - -JNIEXPORT void -JNICALL Java_mono_android_Runtime_switchToContext (JNIEnv *env, [[maybe_unused]] jclass klass, jint contextID) -{ - monodroidRuntime.Java_mono_android_Runtime_switchToContext (env, contextID); -} - -JNIEXPORT void -JNICALL Java_mono_android_Runtime_destroyContexts (JNIEnv *env, [[maybe_unused]] jclass klass, jintArray array) -{ - monodroidRuntime.Java_mono_android_Runtime_destroyContexts (env, array); -} - JNIEXPORT void JNICALL Java_mono_android_Runtime_propagateUncaughtException (JNIEnv *env, [[maybe_unused]] jclass klass, jobject javaThread, jthrowable javaException) { diff --git a/src/monodroid/jni/monodroid-glue.hh b/src/monodroid/jni/monodroid-glue.hh index 1f0adad5020..956f93ac5c6 100644 --- a/src/monodroid/jni/monodroid-glue.hh +++ b/src/monodroid/jni/monodroid-glue.hh @@ -8,14 +8,17 @@ #include #include +#if !defined (NET6) #ifdef __cplusplus extern "C" { -#endif +#endif // __cplusplus MONO_API int monodroid_get_system_property (const char *name, char **value); MONO_API int monodroid_getpagesize (void); #ifdef __cplusplus } -#endif +#endif // __cplusplus +#endif // NET6 + int monodroid_get_system_property_from_overrides (const char *name, char ** value); JNIEnv* get_jnienv (void); diff --git a/src/monodroid/jni/pinvoke-override-api.cc b/src/monodroid/jni/pinvoke-override-api.cc new file mode 100644 index 00000000000..fa2e1837a3f --- /dev/null +++ b/src/monodroid/jni/pinvoke-override-api.cc @@ -0,0 +1,714 @@ +#include +#include +#include +#include + +extern "C" { +#include "java_interop_api.h" +} + +#include "globals.hh" +#include "monodroid-glue.hh" +#include "monodroid-glue-internal.hh" +#include "timing.hh" +#include "java-interop.h" +#include "cpu-arch.hh" + +extern "C" { + int _monodroid_getifaddrs (struct _monodroid_ifaddrs **ifap); + void _monodroid_freeifaddrs (struct _monodroid_ifaddrs *ifa); +} + +mono_bool _monodroid_get_network_interface_up_state (const char *ifname, mono_bool *is_up); +mono_bool _monodroid_get_network_interface_supports_multicast (const char *ifname, mono_bool *supports_multicast); +int _monodroid_get_dns_servers (void **dns_servers_array); + +using namespace xamarin::android; +using namespace xamarin::android::internal; + +static unsigned int +monodroid_get_log_categories () +{ + return log_categories; +} + +static int +monodroid_get_system_property (const char *name, char **value) +{ + return androidSystem.monodroid_get_system_property (name, value); +} + +static int +monodroid_embedded_assemblies_set_assemblies_prefix (const char *prefix) +{ + embeddedAssemblies.set_assemblies_prefix (prefix); + return 0; +} + +static void +monodroid_log (LogLevel level, LogCategories category, const char *message) +{ + switch (level) { + case LogLevel::Verbose: + case LogLevel::Debug: + log_debug_nocheck (category, message); + break; + + case LogLevel::Info: + log_info_nocheck (category, message); + break; + + case LogLevel::Warn: + case LogLevel::Silent: // warn is always printed + log_warn (category, message); + break; + + case LogLevel::Error: + log_error (category, message); + break; + + case LogLevel::Fatal: + log_fatal (category, message); + break; + + default: + case LogLevel::Unknown: + case LogLevel::Default: + log_info_nocheck (category, message); + break; + } +} + +static void +monodroid_free (void *ptr) +{ + free (ptr); +} + +static int +_monodroid_max_gref_get () +{ + return static_cast(androidSystem.get_max_gref_count ()); +} + +static int +_monodroid_gref_get () +{ + return osBridge.get_gc_gref_count (); +} + + +static void +_monodroid_gref_log (const char *message) +{ + osBridge._monodroid_gref_log (message); +} + +static int +_monodroid_gref_log_new (jobject curHandle, char curType, jobject newHandle, char newType, const char *threadName, int threadId, const char *from, int from_writable) +{ + return osBridge._monodroid_gref_log_new (curHandle, curType, newHandle, newType, threadName, threadId, from, from_writable); +} + +static void +_monodroid_gref_log_delete (jobject handle, char type, const char *threadName, int threadId, const char *from, int from_writable) +{ + osBridge._monodroid_gref_log_delete (handle, type, threadName, threadId, from, from_writable); +} + +static void +_monodroid_weak_gref_new (jobject curHandle, char curType, jobject newHandle, char newType, const char *threadName, int threadId, const char *from, int from_writable) +{ + osBridge._monodroid_weak_gref_new (curHandle, curType, newHandle, newType, threadName, threadId, from, from_writable); +} + +static void +_monodroid_weak_gref_delete (jobject handle, char type, const char *threadName, int threadId, const char *from, int from_writable) +{ + osBridge._monodroid_weak_gref_delete (handle, type, threadName, threadId, from, from_writable); +} + +static void +_monodroid_lref_log_new (int lrefc, jobject handle, char type, const char *threadName, int threadId, const char *from, int from_writable) +{ + osBridge._monodroid_lref_log_new (lrefc, handle, type, threadName, threadId, from, from_writable); +} + +static void +_monodroid_lref_log_delete (int lrefc, jobject handle, char type, const char *threadName, int threadId, const char *from, int from_writable) +{ + osBridge._monodroid_lref_log_delete (lrefc, handle, type, threadName, threadId, from, from_writable); +} + +static void +_monodroid_gc_wait_for_bridge_processing () +{ + mono_gc_wait_for_bridge_processing (); +} + +static int +_monodroid_get_android_api_level () +{ + return monodroidRuntime.get_android_api_level (); +} + +static void +monodroid_clear_gdb_wait () +{ + monodroidRuntime.set_monodroid_gdb_wait (false); +} + +static void* +_monodroid_get_identity_hash_code (JNIEnv *env, void *v) +{ + intptr_t rv = env->CallStaticIntMethod (monodroidRuntime.get_java_class_System (), monodroidRuntime.get_java_class_method_System_identityHashCode (), v); + return (void*) rv; +} + +static void* +_monodroid_timezone_get_default_id () +{ + JNIEnv *env = osBridge.ensure_jnienv (); + jmethodID getDefault = env->GetStaticMethodID (monodroidRuntime.get_java_class_TimeZone (), "getDefault", "()Ljava/util/TimeZone;"); + jmethodID getID = env->GetMethodID (monodroidRuntime.get_java_class_TimeZone (), "getID", "()Ljava/lang/String;"); + jobject d = env->CallStaticObjectMethod (monodroidRuntime.get_java_class_TimeZone (), getDefault); + jstring id = reinterpret_cast (env->CallObjectMethod (d, getID)); + const char *mutf8 = env->GetStringUTFChars (id, nullptr); + + if (mutf8 == nullptr) { + log_error (LOG_DEFAULT, "Failed to convert Java TimeZone ID to UTF8 (out of memory?)"); + env->DeleteLocalRef (id); + env->DeleteLocalRef (d); + return nullptr; + } + + char *def_id = strdup (mutf8); + + env->ReleaseStringUTFChars (id, mutf8); + env->DeleteLocalRef (id); + env->DeleteLocalRef (d); + + return def_id; +} + +static void +_monodroid_counters_dump (const char *format, va_list args) +{ + monodroidRuntime.dump_counters_v (format, args); +} + +static managed_timing_sequence* +monodroid_timing_start (const char *message) +{ + if (timing == nullptr) + return nullptr; + + managed_timing_sequence *ret = timing->get_available_sequence (); + if (message != nullptr) { + log_info (LOG_TIMING, message); + } + ret->period.mark_start (); + + return ret; +} + +static void +monodroid_timing_stop (managed_timing_sequence *sequence, const char *message) +{ + static constexpr const char DEFAULT_MESSAGE[] = "Managed Timing"; + + if (sequence == nullptr) + return; + + sequence->period.mark_end (); + Timing::info (sequence->period, message == nullptr ? DEFAULT_MESSAGE : message); + timing->release_sequence (sequence); +} + +static char** +monodroid_strsplit (const char *str, const char *delimiter, size_t max_tokens) +{ + return utils.monodroid_strsplit (str, delimiter, max_tokens); +} + +static void +monodroid_strfreev (char **str_array) +{ + utils.monodroid_strfreev (str_array); +} + +static char* +monodroid_strdup_printf (const char *format, ...) +{ + va_list args; + + va_start (args, format); + char *ret = utils.monodroid_strdup_vprintf (format, args); + va_end (args); + + return ret; +} + +static char* +monodroid_TypeManager_get_java_class_name (jclass klass) +{ + return monodroidRuntime.get_java_class_name_for_TypeManager (klass); +} + +static void +monodroid_store_package_name (const char *name) +{ + utils.monodroid_store_package_name (name); +} + +static int +monodroid_get_namespaced_system_property (const char *name, char **value) +{ + return static_cast(androidSystem.monodroid_get_system_property (name, value)); +} + +static FILE* +monodroid_fopen (const char* filename, const char* mode) +{ + return utils.monodroid_fopen (filename, mode); +} + +static int +send_uninterrupted (int fd, void *buf, int len) +{ + if (len < 0) + len = 0; + return utils.send_uninterrupted (fd, buf, static_cast(len)); +} + +static int +recv_uninterrupted (int fd, void *buf, int len) +{ + if (len < 0) + len = 0; + return static_cast(utils.recv_uninterrupted (fd, buf, static_cast(len))); +} + +static void +set_world_accessable (const char *path) +{ + utils.set_world_accessable (path); +} + +static void +create_public_directory (const char *dir) +{ + utils.create_public_directory (dir); +} + +static char* +path_combine (const char *path1, const char *path2) +{ + return utils.path_combine (path1, path2); +} + +static void* +monodroid_dylib_mono_new ([[maybe_unused]] const char *libmono_path) +{ + return nullptr; +} + +static void +monodroid_dylib_mono_free ([[maybe_unused]] void *mono_imports) +{ + // no-op +} + +/* + this function is used from JavaInterop and should be treated as public API + https://github.com/xamarin/java.interop/blob/master/src/java-interop/java-interop-gc-bridge-mono.c#L266 + + it should also accept libmono_path = nullptr parameter +*/ +static int +monodroid_dylib_mono_init (void *mono_imports, [[maybe_unused]] const char *libmono_path) +{ + if (mono_imports == nullptr) + return FALSE; + return TRUE; +} + +static void* +monodroid_get_dylib (void) +{ + return nullptr; +} + +#define PINVOKE_SYMBOL(_sym_) { #_sym_, reinterpret_cast(&_sym_) } + +MonodroidRuntime::pinvoke_api_map MonodroidRuntime::xa_pinvoke_map = { + PINVOKE_SYMBOL (create_public_directory), + PINVOKE_SYMBOL (java_interop_free), + PINVOKE_SYMBOL (java_interop_jnienv_alloc_object), + PINVOKE_SYMBOL (java_interop_jnienv_call_boolean_method), + PINVOKE_SYMBOL (java_interop_jnienv_call_boolean_method_a), + PINVOKE_SYMBOL (java_interop_jnienv_call_byte_method), + PINVOKE_SYMBOL (java_interop_jnienv_call_byte_method_a), + PINVOKE_SYMBOL (java_interop_jnienv_call_char_method), + PINVOKE_SYMBOL (java_interop_jnienv_call_char_method_a), + PINVOKE_SYMBOL (java_interop_jnienv_call_double_method), + PINVOKE_SYMBOL (java_interop_jnienv_call_double_method_a), + PINVOKE_SYMBOL (java_interop_jnienv_call_float_method), + PINVOKE_SYMBOL (java_interop_jnienv_call_float_method_a), + PINVOKE_SYMBOL (java_interop_jnienv_call_int_method), + PINVOKE_SYMBOL (java_interop_jnienv_call_int_method_a), + PINVOKE_SYMBOL (java_interop_jnienv_call_long_method), + PINVOKE_SYMBOL (java_interop_jnienv_call_long_method_a), + PINVOKE_SYMBOL (java_interop_jnienv_call_nonvirtual_boolean_method), + PINVOKE_SYMBOL (java_interop_jnienv_call_nonvirtual_boolean_method_a), + PINVOKE_SYMBOL (java_interop_jnienv_call_nonvirtual_byte_method), + PINVOKE_SYMBOL (java_interop_jnienv_call_nonvirtual_byte_method_a), + PINVOKE_SYMBOL (java_interop_jnienv_call_nonvirtual_char_method), + PINVOKE_SYMBOL (java_interop_jnienv_call_nonvirtual_char_method_a), + PINVOKE_SYMBOL (java_interop_jnienv_call_nonvirtual_double_method), + PINVOKE_SYMBOL (java_interop_jnienv_call_nonvirtual_double_method_a), + PINVOKE_SYMBOL (java_interop_jnienv_call_nonvirtual_float_method), + PINVOKE_SYMBOL (java_interop_jnienv_call_nonvirtual_float_method_a), + PINVOKE_SYMBOL (java_interop_jnienv_call_nonvirtual_int_method), + PINVOKE_SYMBOL (java_interop_jnienv_call_nonvirtual_int_method_a), + PINVOKE_SYMBOL (java_interop_jnienv_call_nonvirtual_long_method), + PINVOKE_SYMBOL (java_interop_jnienv_call_nonvirtual_long_method_a), + PINVOKE_SYMBOL (java_interop_jnienv_call_nonvirtual_object_method), + PINVOKE_SYMBOL (java_interop_jnienv_call_nonvirtual_object_method_a), + PINVOKE_SYMBOL (java_interop_jnienv_call_nonvirtual_short_method), + PINVOKE_SYMBOL (java_interop_jnienv_call_nonvirtual_short_method_a), + PINVOKE_SYMBOL (java_interop_jnienv_call_nonvirtual_void_method), + PINVOKE_SYMBOL (java_interop_jnienv_call_nonvirtual_void_method_a), + PINVOKE_SYMBOL (java_interop_jnienv_call_object_method), + PINVOKE_SYMBOL (java_interop_jnienv_call_object_method_a), + PINVOKE_SYMBOL (java_interop_jnienv_call_short_method), + PINVOKE_SYMBOL (java_interop_jnienv_call_short_method_a), + PINVOKE_SYMBOL (java_interop_jnienv_call_static_boolean_method), + PINVOKE_SYMBOL (java_interop_jnienv_call_static_boolean_method_a), + PINVOKE_SYMBOL (java_interop_jnienv_call_static_byte_method), + PINVOKE_SYMBOL (java_interop_jnienv_call_static_byte_method_a), + PINVOKE_SYMBOL (java_interop_jnienv_call_static_char_method), + PINVOKE_SYMBOL (java_interop_jnienv_call_static_char_method_a), + PINVOKE_SYMBOL (java_interop_jnienv_call_static_double_method), + PINVOKE_SYMBOL (java_interop_jnienv_call_static_double_method_a), + PINVOKE_SYMBOL (java_interop_jnienv_call_static_float_method), + PINVOKE_SYMBOL (java_interop_jnienv_call_static_float_method_a), + PINVOKE_SYMBOL (java_interop_jnienv_call_static_int_method), + PINVOKE_SYMBOL (java_interop_jnienv_call_static_int_method_a), + PINVOKE_SYMBOL (java_interop_jnienv_call_static_long_method), + PINVOKE_SYMBOL (java_interop_jnienv_call_static_long_method_a), + PINVOKE_SYMBOL (java_interop_jnienv_call_static_object_method), + PINVOKE_SYMBOL (java_interop_jnienv_call_static_object_method_a), + PINVOKE_SYMBOL (java_interop_jnienv_call_static_short_method), + PINVOKE_SYMBOL (java_interop_jnienv_call_static_short_method_a), + PINVOKE_SYMBOL (java_interop_jnienv_call_static_void_method), + PINVOKE_SYMBOL (java_interop_jnienv_call_static_void_method_a), + PINVOKE_SYMBOL (java_interop_jnienv_call_void_method), + PINVOKE_SYMBOL (java_interop_jnienv_call_void_method_a), + PINVOKE_SYMBOL (java_interop_jnienv_define_class), + PINVOKE_SYMBOL (java_interop_jnienv_delete_global_ref), + PINVOKE_SYMBOL (java_interop_jnienv_delete_local_ref), + PINVOKE_SYMBOL (java_interop_jnienv_delete_weak_global_ref), + PINVOKE_SYMBOL (java_interop_jnienv_ensure_local_capacity), + PINVOKE_SYMBOL (java_interop_jnienv_exception_check), + PINVOKE_SYMBOL (java_interop_jnienv_exception_clear), + PINVOKE_SYMBOL (java_interop_jnienv_exception_describe), + PINVOKE_SYMBOL (java_interop_jnienv_exception_occurred), + PINVOKE_SYMBOL (java_interop_jnienv_fatal_error), + PINVOKE_SYMBOL (java_interop_jnienv_find_class), + PINVOKE_SYMBOL (java_interop_jnienv_get_array_length), + PINVOKE_SYMBOL (java_interop_jnienv_get_boolean_array_elements), + PINVOKE_SYMBOL (java_interop_jnienv_get_boolean_array_region), + PINVOKE_SYMBOL (java_interop_jnienv_get_boolean_field), + PINVOKE_SYMBOL (java_interop_jnienv_get_byte_array_elements), + PINVOKE_SYMBOL (java_interop_jnienv_get_byte_array_region), + PINVOKE_SYMBOL (java_interop_jnienv_get_byte_field), + PINVOKE_SYMBOL (java_interop_jnienv_get_char_array_elements), + PINVOKE_SYMBOL (java_interop_jnienv_get_char_array_region), + PINVOKE_SYMBOL (java_interop_jnienv_get_char_field), + PINVOKE_SYMBOL (java_interop_jnienv_get_direct_buffer_address), + PINVOKE_SYMBOL (java_interop_jnienv_get_direct_buffer_capacity), + PINVOKE_SYMBOL (java_interop_jnienv_get_double_array_elements), + PINVOKE_SYMBOL (java_interop_jnienv_get_double_array_region), + PINVOKE_SYMBOL (java_interop_jnienv_get_double_field), + PINVOKE_SYMBOL (java_interop_jnienv_get_field_id), + PINVOKE_SYMBOL (java_interop_jnienv_get_float_array_elements), + PINVOKE_SYMBOL (java_interop_jnienv_get_float_array_region), + PINVOKE_SYMBOL (java_interop_jnienv_get_float_field), + PINVOKE_SYMBOL (java_interop_jnienv_get_int_array_elements), + PINVOKE_SYMBOL (java_interop_jnienv_get_int_array_region), + PINVOKE_SYMBOL (java_interop_jnienv_get_int_field), + PINVOKE_SYMBOL (java_interop_jnienv_get_java_vm), + PINVOKE_SYMBOL (java_interop_jnienv_get_long_array_elements), + PINVOKE_SYMBOL (java_interop_jnienv_get_long_array_region), + PINVOKE_SYMBOL (java_interop_jnienv_get_long_field), + PINVOKE_SYMBOL (java_interop_jnienv_get_method_id), + PINVOKE_SYMBOL (java_interop_jnienv_get_object_array_element), + PINVOKE_SYMBOL (java_interop_jnienv_get_object_class), + PINVOKE_SYMBOL (java_interop_jnienv_get_object_field), + PINVOKE_SYMBOL (java_interop_jnienv_get_object_ref_type), + PINVOKE_SYMBOL (java_interop_jnienv_get_primitive_array_critical), + PINVOKE_SYMBOL (java_interop_jnienv_get_short_array_elements), + PINVOKE_SYMBOL (java_interop_jnienv_get_short_array_region), + PINVOKE_SYMBOL (java_interop_jnienv_get_short_field), + PINVOKE_SYMBOL (java_interop_jnienv_get_static_boolean_field), + PINVOKE_SYMBOL (java_interop_jnienv_get_static_byte_field), + PINVOKE_SYMBOL (java_interop_jnienv_get_static_char_field), + PINVOKE_SYMBOL (java_interop_jnienv_get_static_double_field), + PINVOKE_SYMBOL (java_interop_jnienv_get_static_field_id), + PINVOKE_SYMBOL (java_interop_jnienv_get_static_float_field), + PINVOKE_SYMBOL (java_interop_jnienv_get_static_int_field), + PINVOKE_SYMBOL (java_interop_jnienv_get_static_long_field), + PINVOKE_SYMBOL (java_interop_jnienv_get_static_method_id), + PINVOKE_SYMBOL (java_interop_jnienv_get_static_object_field), + PINVOKE_SYMBOL (java_interop_jnienv_get_static_short_field), + PINVOKE_SYMBOL (java_interop_jnienv_get_string_chars), + PINVOKE_SYMBOL (java_interop_jnienv_get_string_length), + PINVOKE_SYMBOL (java_interop_jnienv_get_superclass), + PINVOKE_SYMBOL (java_interop_jnienv_get_version), + PINVOKE_SYMBOL (java_interop_jnienv_is_assignable_from), + PINVOKE_SYMBOL (java_interop_jnienv_is_instance_of), + PINVOKE_SYMBOL (java_interop_jnienv_is_same_object), + PINVOKE_SYMBOL (java_interop_jnienv_monitor_enter), + PINVOKE_SYMBOL (java_interop_jnienv_monitor_exit), + PINVOKE_SYMBOL (java_interop_jnienv_new_boolean_array), + PINVOKE_SYMBOL (java_interop_jnienv_new_byte_array), + PINVOKE_SYMBOL (java_interop_jnienv_new_char_array), + PINVOKE_SYMBOL (java_interop_jnienv_new_direct_byte_buffer), + PINVOKE_SYMBOL (java_interop_jnienv_new_double_array), + PINVOKE_SYMBOL (java_interop_jnienv_new_float_array), + PINVOKE_SYMBOL (java_interop_jnienv_new_global_ref), + PINVOKE_SYMBOL (java_interop_jnienv_new_int_array), + PINVOKE_SYMBOL (java_interop_jnienv_new_local_ref), + PINVOKE_SYMBOL (java_interop_jnienv_new_long_array), + PINVOKE_SYMBOL (java_interop_jnienv_new_object), + PINVOKE_SYMBOL (java_interop_jnienv_new_object_a), + PINVOKE_SYMBOL (java_interop_jnienv_new_object_array), + PINVOKE_SYMBOL (java_interop_jnienv_new_short_array), + PINVOKE_SYMBOL (java_interop_jnienv_new_string), + PINVOKE_SYMBOL (java_interop_jnienv_new_weak_global_ref), + PINVOKE_SYMBOL (java_interop_jnienv_pop_local_frame), + PINVOKE_SYMBOL (java_interop_jnienv_push_local_frame), + PINVOKE_SYMBOL (java_interop_jnienv_register_natives), + PINVOKE_SYMBOL (java_interop_jnienv_release_boolean_array_elements), + PINVOKE_SYMBOL (java_interop_jnienv_release_byte_array_elements), + PINVOKE_SYMBOL (java_interop_jnienv_release_char_array_elements), + PINVOKE_SYMBOL (java_interop_jnienv_release_double_array_elements), + PINVOKE_SYMBOL (java_interop_jnienv_release_float_array_elements), + PINVOKE_SYMBOL (java_interop_jnienv_release_int_array_elements), + PINVOKE_SYMBOL (java_interop_jnienv_release_long_array_elements), + PINVOKE_SYMBOL (java_interop_jnienv_release_primitive_array_critical), + PINVOKE_SYMBOL (java_interop_jnienv_release_short_array_elements), + PINVOKE_SYMBOL (java_interop_jnienv_release_string_chars), + PINVOKE_SYMBOL (java_interop_jnienv_set_boolean_array_region), + PINVOKE_SYMBOL (java_interop_jnienv_set_boolean_field), + PINVOKE_SYMBOL (java_interop_jnienv_set_byte_array_region), + PINVOKE_SYMBOL (java_interop_jnienv_set_byte_field), + PINVOKE_SYMBOL (java_interop_jnienv_set_char_array_region), + PINVOKE_SYMBOL (java_interop_jnienv_set_char_field), + PINVOKE_SYMBOL (java_interop_jnienv_set_double_array_region), + PINVOKE_SYMBOL (java_interop_jnienv_set_double_field), + PINVOKE_SYMBOL (java_interop_jnienv_set_float_array_region), + PINVOKE_SYMBOL (java_interop_jnienv_set_float_field), + PINVOKE_SYMBOL (java_interop_jnienv_set_int_array_region), + PINVOKE_SYMBOL (java_interop_jnienv_set_int_field), + PINVOKE_SYMBOL (java_interop_jnienv_set_long_array_region), + PINVOKE_SYMBOL (java_interop_jnienv_set_long_field), + PINVOKE_SYMBOL (java_interop_jnienv_set_object_array_element), + PINVOKE_SYMBOL (java_interop_jnienv_set_object_field), + PINVOKE_SYMBOL (java_interop_jnienv_set_short_array_region), + PINVOKE_SYMBOL (java_interop_jnienv_set_short_field), + PINVOKE_SYMBOL (java_interop_jnienv_set_static_boolean_field), + PINVOKE_SYMBOL (java_interop_jnienv_set_static_byte_field), + PINVOKE_SYMBOL (java_interop_jnienv_set_static_char_field), + PINVOKE_SYMBOL (java_interop_jnienv_set_static_double_field), + PINVOKE_SYMBOL (java_interop_jnienv_set_static_float_field), + PINVOKE_SYMBOL (java_interop_jnienv_set_static_int_field), + PINVOKE_SYMBOL (java_interop_jnienv_set_static_long_field), + PINVOKE_SYMBOL (java_interop_jnienv_set_static_object_field), + PINVOKE_SYMBOL (java_interop_jnienv_set_static_short_field), + PINVOKE_SYMBOL (java_interop_jnienv_throw), + PINVOKE_SYMBOL (java_interop_jnienv_throw_new), + PINVOKE_SYMBOL (java_interop_jnienv_to_reflected_field), + PINVOKE_SYMBOL (java_interop_jnienv_to_reflected_method), + PINVOKE_SYMBOL (java_interop_jnienv_unregister_natives), + PINVOKE_SYMBOL (java_interop_strdup), + PINVOKE_SYMBOL (monodroid_clear_gdb_wait), + PINVOKE_SYMBOL (_monodroid_counters_dump), + PINVOKE_SYMBOL (_monodroid_detect_cpu_and_architecture), + PINVOKE_SYMBOL (monodroid_dylib_mono_free), + PINVOKE_SYMBOL (monodroid_dylib_mono_init), + PINVOKE_SYMBOL (monodroid_dylib_mono_new), + PINVOKE_SYMBOL (monodroid_embedded_assemblies_set_assemblies_prefix), + PINVOKE_SYMBOL (monodroid_fopen), + PINVOKE_SYMBOL (monodroid_free), + PINVOKE_SYMBOL (_monodroid_freeifaddrs), + PINVOKE_SYMBOL (_monodroid_gc_wait_for_bridge_processing), + PINVOKE_SYMBOL (_monodroid_get_android_api_level), + PINVOKE_SYMBOL (_monodroid_get_dns_servers), + PINVOKE_SYMBOL (monodroid_get_dylib), + PINVOKE_SYMBOL (_monodroid_get_identity_hash_code), + PINVOKE_SYMBOL (_monodroid_getifaddrs), + PINVOKE_SYMBOL (monodroid_get_log_categories), + PINVOKE_SYMBOL (monodroid_get_namespaced_system_property), + PINVOKE_SYMBOL (_monodroid_get_network_interface_supports_multicast), + PINVOKE_SYMBOL (_monodroid_get_network_interface_up_state), + PINVOKE_SYMBOL (monodroid_get_system_property), + PINVOKE_SYMBOL (_monodroid_gref_get), + PINVOKE_SYMBOL (_monodroid_gref_log), + PINVOKE_SYMBOL (_monodroid_gref_log_delete), + PINVOKE_SYMBOL (_monodroid_gref_log_new), + PINVOKE_SYMBOL (monodroid_log), + PINVOKE_SYMBOL (_monodroid_lref_log_delete), + PINVOKE_SYMBOL (_monodroid_lref_log_new), + PINVOKE_SYMBOL (_monodroid_max_gref_get), + PINVOKE_SYMBOL (monodroid_store_package_name), + PINVOKE_SYMBOL (monodroid_strdup_printf), + PINVOKE_SYMBOL (monodroid_strfreev), + PINVOKE_SYMBOL (monodroid_strsplit), + PINVOKE_SYMBOL (_monodroid_timezone_get_default_id), + PINVOKE_SYMBOL (monodroid_timing_start), + PINVOKE_SYMBOL (monodroid_timing_stop), + PINVOKE_SYMBOL (monodroid_TypeManager_get_java_class_name), + PINVOKE_SYMBOL (_monodroid_weak_gref_delete), + PINVOKE_SYMBOL (_monodroid_weak_gref_new), + PINVOKE_SYMBOL (path_combine), + PINVOKE_SYMBOL (recv_uninterrupted), + PINVOKE_SYMBOL (send_uninterrupted), + PINVOKE_SYMBOL (set_world_accessable), +}; + +MonodroidRuntime::pinvoke_library_map MonodroidRuntime::other_pinvoke_map (MonodroidRuntime::LIBRARY_MAP_INITIAL_BUCKET_COUNT); + +// `pinvoke_map_write_lock` MUST be held when calling this method +force_inline void* +MonodroidRuntime::load_library_entry (std::string const& library_name, std::string const& entrypoint_name, pinvoke_api_map_ptr api_map) +{ + // Make sure some other thread hasn't just added the entry + auto iter = api_map->find (entrypoint_name); + if (iter != api_map->end () && iter->second != nullptr) { + return iter->second; + } + + void *lib_handle = monodroid_dlopen (library_name.c_str (), MONO_DL_LOCAL, nullptr, nullptr); + if (lib_handle == nullptr) { + log_warn (LOG_ASSEMBLY, "Shared library '%s' not loaded, p/invoke '%s' may fail", library_name.c_str (), entrypoint_name.c_str ()); + return nullptr; + } + + void *entry_handle = monodroid_dlsym (lib_handle, entrypoint_name.c_str (), nullptr, nullptr); + if (entry_handle == nullptr) { + log_warn (LOG_ASSEMBLY, "Symbol '%s' not found in shared library '%s', p/invoke may fail", entrypoint_name.c_str (), library_name.c_str ()); + return nullptr; + } + + log_warn (LOG_ASSEMBLY, "Caching p/invoke entry %s @ %s", library_name.c_str (), entrypoint_name.c_str ()); + (*api_map)[entrypoint_name] = entry_handle; + return entry_handle; +} + +force_inline void* +MonodroidRuntime::fetch_or_create_pinvoke_map_entry (std::string const& library_name, std::string const& entrypoint_name, pinvoke_api_map_ptr api_map, bool need_lock) +{ + auto iter = api_map->find (entrypoint_name); + if (iter != api_map->end () && iter->second != nullptr) { + return iter->second; + } + + if (!need_lock) { + return load_library_entry (library_name, entrypoint_name, api_map); + } + + std::lock_guard lock (pinvoke_map_write_lock); + return load_library_entry (library_name, entrypoint_name, api_map); +} + +void* +MonodroidRuntime::monodroid_pinvoke_override (const char *library_name, const char *entrypoint_name) +{ + log_warn (LOG_DEFAULT, "MonodroidRuntime::monodroid_pinvoke_override (\"%s\", \"%s\")", library_name, entrypoint_name); + + timing_period total_time; + if (XA_UNLIKELY (utils.should_log (LOG_TIMING))) { + total_time.mark_start (); + } + + if (library_name == nullptr || *library_name == '\0' || entrypoint_name == nullptr || *entrypoint_name == '\0') { + return nullptr; + } + + bool is_internal; + switch (library_name[0]) { + case 'j': + is_internal = strcmp ("java-interop", library_name) == 0; + break; + + case 'x': + is_internal = strcmp ("xa-internal-api", library_name) == 0; + break; + + default: + is_internal = false; + break; + } + + if (!is_internal) { + std::string lib_name (library_name); + std::string func_name (entrypoint_name); + + auto iter = other_pinvoke_map.find (lib_name); + void *handle = nullptr; + if (iter == other_pinvoke_map.end ()) { + std::lock_guard lock (pinvoke_map_write_lock); + + pinvoke_api_map_ptr lib_map; + // Make sure some other thread hasn't just added the map + iter = other_pinvoke_map.find (lib_name); + if (iter == other_pinvoke_map.end () || iter->second == nullptr) { + lib_map = new pinvoke_api_map (1); + other_pinvoke_map[lib_name] = lib_map; + } else { + lib_map = iter->second; + } + + handle = fetch_or_create_pinvoke_map_entry (lib_name, func_name, lib_map, /* need_lock */ false); + } else { + if (XA_UNLIKELY (iter->second == nullptr)) { + log_warn (LOG_ASSEMBLY, "Internal error: null entry in p/invoke map for key '%s'", library_name); + return nullptr; // fall back to `monodroid_dlopen` + } + + handle = fetch_or_create_pinvoke_map_entry (lib_name, func_name, iter->second, /* need_lock */ true); + } + + if (XA_UNLIKELY (utils.should_log (LOG_TIMING))) { + total_time.mark_end (); + + TIMING_LOG_INFO (total_time, "p/invoke override for '%s' (foreign)", entrypoint_name); + } + + return handle; + } + + timing_period lookup_time; + if (XA_UNLIKELY (utils.should_log (LOG_TIMING))) { + lookup_time.mark_start (); + } + auto iter = xa_pinvoke_map.find (entrypoint_name); + if (iter == xa_pinvoke_map.end ()) { + // TODO: perhaps it should be fatal? + log_fatal (LOG_ASSEMBLY, "Internal p/invoke symbol '%s @ %s' not found in compile-time map.", library_name, entrypoint_name); + abort (); + return nullptr; + } + + if (XA_UNLIKELY (utils.should_log (LOG_TIMING))) { + lookup_time.mark_end (); + total_time.mark_end (); + + TIMING_LOG_INFO (lookup_time, "p/invoke cache lookup for '%s' (internal)", entrypoint_name); + TIMING_LOG_INFO (total_time, "p/invoke override for '%s' (internal)", entrypoint_name); + } + log_warn (LOG_DEFAULT, "Found %s@%s in internal p/invoke map (%p)", library_name, entrypoint_name, iter->second); + return iter->second; +} diff --git a/src/monodroid/jni/util.hh b/src/monodroid/jni/util.hh index 936a0d3380c..15b2fa02938 100644 --- a/src/monodroid/jni/util.hh +++ b/src/monodroid/jni/util.hh @@ -42,6 +42,7 @@ constexpr int FALSE = 0; #include "java-interop-util.h" #include "logger.hh" +#if !defined (NET6) #ifdef __cplusplus extern "C" { #endif // __cplusplus @@ -59,7 +60,10 @@ extern "C" { MONO_API char *path_combine (const char *path1, const char *path2); #ifdef __cplusplus } +#endif // __cplusplus +#endif // NET6 +#ifdef __cplusplus namespace xamarin::android { class Util : public BasicUtilities diff --git a/src/monodroid/monodroid.targets b/src/monodroid/monodroid.targets index 662ece0d650..9610c46361d 100644 --- a/src/monodroid/monodroid.targets +++ b/src/monodroid/monodroid.targets @@ -42,7 +42,9 @@ <_ConfigureRuntimesInputs Include="CMakeLists.txt" /> <_ConfigureRuntimesInputs Include="..\..\build-tools\scripts\Ndk.targets" /> <_ConfigureRuntimesOutputs Include="@(AndroidSupportedTargetJitAbi->'$(IntermediateOutputPath)\%(Identity)-Debug\CMakeCache.txt')" /> + <_ConfigureRuntimesOutputs Include="@(AndroidSupportedTargetJitAbi->'$(IntermediateOutputPath)\%(Identity)-net6-Debug\CMakeCache.txt')" /> <_ConfigureRuntimesOutputs Include="@(AndroidSupportedTargetJitAbi->'$(IntermediateOutputPath)\%(Identity)-Release\CMakeCache.txt')" /> + <_ConfigureRuntimesOutputs Include="@(AndroidSupportedTargetJitAbi->'$(IntermediateOutputPath)\%(Identity)-net6-Release\CMakeCache.txt')" /> <_ConfigureRuntimesOutputs Include="@(_HostRuntime->'$(IntermediateOutputPath)%(OutputDirectory)-Debug\CMakeCache.txt')" /> <_ConfigureRuntimesOutputs Include="@(_HostRuntime->'$(IntermediateOutputPath)%(OutputDirectory)-Release\CMakeCache.txt')" /> @@ -66,17 +68,27 @@ DependsOnTargets="_FindMonoDroidSources"> <_BuildAndroidRuntimesInputs Include="@(AndroidSupportedTargetJitAbi->'$(IntermediateOutputPath)\%(Identity)-Debug\CMakeCache.txt')" /> + <_BuildAndroidRuntimesInputs Include="@(AndroidSupportedTargetJitAbi->'$(IntermediateOutputPath)\%(Identity)-net6-Debug\CMakeCache.txt')" /> <_BuildAndroidRuntimesInputs Include="@(AndroidSupportedTargetJitAbi->'$(IntermediateOutputPath)\%(Identity)-Release\CMakeCache.txt')" /> + <_BuildAndroidRuntimesInputs Include="@(AndroidSupportedTargetJitAbi->'$(IntermediateOutputPath)\%(Identity)-net6-Release\CMakeCache.txt')" /> <_BuildAndroidRuntimesInputs Include="@(_MonoDroidSources)" /> <_BuildAndroidRuntimesInputs Include="..\..\build-tools\scripts\Ndk.targets" /> <_BuildAndroidRuntimesOutputs Include="@(AndroidSupportedTargetJitAbi->'$(OutputPath)\%(Identity)\libmono-android.debug.so')" /> + <_BuildAndroidRuntimesOutputs Include="@(AndroidSupportedTargetJitAbi->'$(OutputPath)\%(Identity)-net6\libmono-android.debug.so')" /> <_BuildAndroidRuntimesOutputs Include="@(AndroidSupportedTargetJitAbi->'$(OutputPath)\%(Identity)\libmono-android-checked+ubsan.debug.so')" /> + <_BuildAndroidRuntimesOutputs Include="@(AndroidSupportedTargetJitAbi->'$(OutputPath)\%(Identity)-net6\libmono-android-checked+ubsan.debug.so')" /> <_BuildAndroidRuntimesOutputs Include="@(AndroidSupportedTargetJitAbi->'$(OutputPath)\%(Identity)\libmono-android-checked+asan.debug.so')" /> + <_BuildAndroidRuntimesOutputs Include="@(AndroidSupportedTargetJitAbi->'$(OutputPath)\%(Identity)-net6\libmono-android-checked+asan.debug.so')" /> <_BuildAndroidRuntimesOutputs Include="@(AndroidSupportedTargetJitAbi->'$(OutputPath)\%(Identity)\libmono-android.release.so')" /> + <_BuildAndroidRuntimesOutputs Include="@(AndroidSupportedTargetJitAbi->'$(OutputPath)\%(Identity)-net6\libmono-android.release.so')" /> <_BuildAndroidRuntimesOutputs Include="@(AndroidSupportedTargetJitAbi->'$(OutputPath)\%(Identity)\libmono-android-checked+asan.release.so')" /> + <_BuildAndroidRuntimesOutputs Include="@(AndroidSupportedTargetJitAbi->'$(OutputPath)\%(Identity)-net6\libmono-android-checked+asan.release.so')" /> <_BuildAndroidRuntimesOutputs Include="@(AndroidSupportedTargetJitAbi->'$(OutputPath)\%(Identity)\libmono-android-checked+ubsan.release.so')" /> + <_BuildAndroidRuntimesOutputs Include="@(AndroidSupportedTargetJitAbi->'$(OutputPath)\%(Identity)-net6\libmono-android-checked+ubsan.release.so')" /> <_BuildAndroidRuntimesOutputs Include="@(AndroidSupportedTargetJitAbi->'$(OutputPath)\%(Identity)\Debug\libxamarin-app.so')" /> + <_BuildAndroidRuntimesOutputs Include="@(AndroidSupportedTargetJitAbi->'$(OutputPath)\%(Identity)-net6\Debug\libxamarin-app.so')" /> <_BuildAndroidRuntimesOutputs Include="@(AndroidSupportedTargetJitAbi->'$(OutputPath)\%(Identity)\Release\libxamarin-app.so')" /> + <_BuildAndroidRuntimesOutputs Include="@(AndroidSupportedTargetJitAbi->'$(OutputPath)\%(Identity)-net6\Release\libxamarin-app.so')" /> @@ -89,31 +101,61 @@ WorkingDirectory="$(IntermediateOutputPath)%(AndroidSupportedTargetJitAbi.Identity)-Debug" /> + + + + + + + + + + + +