diff --git a/build-tools/create-packs/Microsoft.Android.Runtime.proj b/build-tools/create-packs/Microsoft.Android.Runtime.proj
index 6712bd2137d..1d5dfc4083a 100644
--- a/build-tools/create-packs/Microsoft.Android.Runtime.proj
+++ b/build-tools/create-packs/Microsoft.Android.Runtime.proj
@@ -38,6 +38,7 @@ projects that use the Microsoft.Android framework in .NET 5.
<_AndroidRuntimePackAssets Include="$(XamarinAndroidSourcePath)bin\$(Configuration)\lib\xamarin.android\xbuild\Xamarin\Android\lib\$(AndroidABI)\libmono-android.debug.so" />
<_AndroidRuntimePackAssets Include="$(XamarinAndroidSourcePath)bin\$(Configuration)\lib\xamarin.android\xbuild\Xamarin\Android\lib\$(AndroidABI)\libmono-android.release.so" />
+ <_AndroidRuntimePackAssets Include="$(XamarinAndroidSourcePath)bin\$(Configuration)\lib\xamarin.android\xbuild\Xamarin\Android\lib\$(AndroidABI)\libxa-internal-api.so" />
<_AndroidRuntimePackAssets Include="$(XamarinAndroidSourcePath)bin\$(Configuration)\lib\xamarin.android\xbuild\Xamarin\Android\lib\$(AndroidABI)\libsqlite3_xamarin.so" />
<_AndroidRuntimePackAssets Include="$(XamarinAndroidSourcePath)bin\$(Configuration)\lib\xamarin.android\xbuild\Xamarin\Android\lib\$(AndroidABI)\libxamarin-debug-app-helper.so" />
diff --git a/build-tools/installers/create-installers.targets b/build-tools/installers/create-installers.targets
index 226b63465db..e5abae9efd3 100644
--- a/build-tools/installers/create-installers.targets
+++ b/build-tools/installers/create-installers.targets
@@ -159,6 +159,7 @@
<_MSBuildFiles Include="$(MSBuildSrcDir)\LayoutBinding.cs" />
<_MSBuildFiles Include="@(AndroidSupportedTargetJitAbi->'$(MSBuildSrcDir)\lib\%(Identity)\libmono-android.debug.so')" Condition=" '$(PackageId)' != 'Microsoft.Android.Sdk' " />
<_MSBuildFiles Include="@(AndroidSupportedTargetJitAbi->'$(MSBuildSrcDir)\lib\%(Identity)\libmono-android.release.so')" Condition=" '$(PackageId)' != 'Microsoft.Android.Sdk' " />
+ <_MSBuildFiles Include="@(AndroidSupportedTargetJitAbi->'$(MSBuildSrcDir)\lib\%(Identity)\libxa-internal-api.so')" Condition=" '$(PackageId)' != 'Microsoft.Android.Sdk' " />
<_MSBuildFiles Include="@(AndroidSupportedTargetJitAbi->'$(MSBuildSrcDir)\lib\%(Identity)\libmono-btls-shared.so')" Condition=" '$(PackageId)' != 'Microsoft.Android.Sdk' " />
<_MSBuildFiles Include="@(AndroidSupportedTargetJitAbi->'$(MSBuildSrcDir)\lib\%(Identity)\libmono-profiler-aot.so')" Condition=" '$(PackageId)' != 'Microsoft.Android.Sdk' " />
<_MSBuildFiles Include="@(AndroidSupportedTargetJitAbi->'$(MSBuildSrcDir)\lib\%(Identity)\libmono-profiler-log.so')" Condition=" '$(PackageId)' != 'Microsoft.Android.Sdk' " />
@@ -294,6 +295,7 @@
<_MSBuildLibHostFilesWin Include="$(MSBuildSrcDir)\lib\host-mxe-Win64\libMonoPosixHelper.dll" />
<_MSBuildLibHostFilesWin Include="$(MSBuildSrcDir)\lib\host-mxe-Win64\libmonosgen-2.0.dll" />
<_MSBuildLibHostFilesWin Include="$(MSBuildSrcDir)\lib\host-mxe-Win64\libxamarin-app.dll" Condition=" '$(HostOS)' != 'Windows' " />
+ <_MSBuildLibHostFilesWin Include="$(MSBuildSrcDir)\lib\host-mxe-Win64\libxa-internal-api.dll" Condition=" '$(HostOS)' != 'Windows' " />
<_MSBuildFilesUnixSign>
@@ -333,6 +335,7 @@
<_MSBuildFilesUnixSign Include="$(MSBuildSrcDir)\lib\host-$(HostOS)\libMonoPosixHelper.$(LibExtension)" Condition=" '$(PackageId)' != 'Microsoft.Android.Sdk' " />
<_MSBuildFilesUnixSign Include="$(MSBuildSrcDir)\lib\host-$(HostOS)\libmonosgen-2.0.$(LibExtension)" Condition=" '$(PackageId)' != 'Microsoft.Android.Sdk' " />
<_MSBuildFilesUnixSign Include="$(MSBuildSrcDir)\lib\host-$(HostOS)\libxamarin-app.$(LibExtension)" Condition=" '$(PackageId)' != 'Microsoft.Android.Sdk' " />
+ <_MSBuildFilesUnixSign Include="$(MSBuildSrcDir)\lib\host-$(HostOS)\libxa-internal-api.$(LibExtension)" Condition=" '$(PackageId)' != 'Microsoft.Android.Sdk' " />
<_MSBuildFilesUnixSign Include="$(MSBuildSrcDir)\libzip.$(LibExtension)" />
<_MSBuildFilesUnix Include="$(MSBuildSrcDir)\proguard\bin\proguard.sh" />
diff --git a/samples/HelloWorld/Properties/AndroidManifest.xml b/samples/HelloWorld/Properties/AndroidManifest.xml
index dd591420769..3561f38df32 100644
--- a/samples/HelloWorld/Properties/AndroidManifest.xml
+++ b/samples/HelloWorld/Properties/AndroidManifest.xml
@@ -1,6 +1,6 @@
-
+
diff --git a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets
index b62574e2e5a..dbcc8433efe 100644
--- a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets
+++ b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets
@@ -1890,6 +1890,7 @@ because xbuild doesn't support framework reference assemblies.
<_AndroidNativeLibraryForFastDev Condition=" '$(_InstantRunEnabled)' == 'True' And '$(AndroidUseDebugRuntime)' == 'True' " Include="%(_TargetLibDir.Identity)\libxamarin-debug-app-helper.so" />
+
diff --git a/src/monodroid/CMakeLists.txt b/src/monodroid/CMakeLists.txt
index b889ea33694..191a4e2f55f 100644
--- a/src/monodroid/CMakeLists.txt
+++ b/src/monodroid/CMakeLists.txt
@@ -228,6 +228,8 @@ else()
endif()
endif()
+string(STRIP "${EXTRA_LINKER_FLAGS}" EXTRA_LINKER_FLAGS)
+
if (ENABLE_TIMING)
add_definitions("-DMONODROID_TIMING=1")
endif()
@@ -285,11 +287,10 @@ set(MONODROID_SOURCES
${SOURCES_DIR}/debug-constants.cc
${SOURCES_DIR}/embedded-assemblies.cc
${SOURCES_DIR}/embedded-assemblies-zip.cc
- ${SOURCES_DIR}/external-api.cc
${SOURCES_DIR}/globals.cc
- ${SOURCES_DIR}/jni.c
${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
@@ -299,6 +300,12 @@ set(MONODROID_SOURCES
${JAVA_INTEROP_SRC_PATH}/java-interop-util.cc
)
+set(XA_INTERNAL_API_SOURCES
+ ${SOURCES_DIR}/jni.c
+ ${SOURCES_DIR}/internal-pinvoke-api.cc
+ ${JAVA_INTEROP_SRC_PATH}/java-interop-util.cc
+ )
+
if(ENABLE_NDK)
set(MONODROID_SOURCES
${MONODROID_SOURCES}
@@ -314,6 +321,15 @@ if(UNIX)
)
endif()
+add_library(xa-internal-api SHARED ${XA_INTERNAL_API_SOURCES})
+target_link_libraries(xa-internal-api ${EXTRA_LINKER_FLAGS})
+set_target_properties(
+ xa-internal-api
+ PROPERTIES
+ COMPILE_FLAGS -fvisibility=default
+ LINK_FLAGS -fvisibility=default
+ )
+
set(XAMARIN_APP_STUB_SOURCES ${SOURCES_DIR}/application_dso_stub.cc)
add_library(xamarin-app SHARED ${XAMARIN_APP_STUB_SOURCES})
if (ENABLE_NDK)
diff --git a/src/monodroid/jni/cpu-arch-detect.cc b/src/monodroid/jni/cpu-arch-detect.cc
index 2112e159788..e93d2daea84 100644
--- a/src/monodroid/jni/cpu-arch-detect.cc
+++ b/src/monodroid/jni/cpu-arch-detect.cc
@@ -225,7 +225,7 @@ get_running_on_cpu (unsigned short *running_on_cpu)
*running_on_cpu = CPU_KIND_UNKNOWN;
}
-MONO_API void
+void
_monodroid_detect_cpu_and_architecture (unsigned short *built_for_cpu, unsigned short *running_on_cpu, unsigned char *is64bit)
{
assert (built_for_cpu);
diff --git a/src/monodroid/jni/embedded-assemblies.cc b/src/monodroid/jni/embedded-assemblies.cc
index 4b861355eaf..5477dbc7c43 100644
--- a/src/monodroid/jni/embedded-assemblies.cc
+++ b/src/monodroid/jni/embedded-assemblies.cc
@@ -597,7 +597,7 @@ EmbeddedAssemblies::md_mmap_apk_file (int fd, uint32_t offset, uint32_t size, co
md_mmap_info file_info;
md_mmap_info mmap_info;
- size_t pageSize = static_cast(monodroid_getpagesize());
+ size_t pageSize = static_cast(utils.monodroid_getpagesize ());
uint32_t offsetFromPage = static_cast(offset % pageSize);
uint32_t offsetPage = offset - offsetFromPage;
uint32_t offsetSize = size + offsetFromPage;
diff --git a/src/monodroid/jni/external-api.cc b/src/monodroid/jni/external-api.cc
deleted file mode 100644
index a835d4a8ca3..00000000000
--- a/src/monodroid/jni/external-api.cc
+++ /dev/null
@@ -1,307 +0,0 @@
-#ifdef WINDOWS
-#include
-#include
-#include
-#include
-#include
-#include
-#endif
-
-#include "globals.hh"
-#include "timing.hh"
-
-using namespace xamarin::android;
-using namespace xamarin::android::internal;
-
-/* Invoked by System.Core.dll!System.IO.MemoryMappedFiles.MemoryMapImpl.getpagesize */
-MONO_API int
-monodroid_getpagesize (void)
-{
-#ifndef WINDOWS
- return getpagesize ();
-#else
- SYSTEM_INFO info;
- GetSystemInfo (&info);
- return info.dwPageSize;
-#endif
-}
-
-/* Invoked by:
- - System.Core.dll!System.TimeZoneInfo.Android.GetDefaultTimeZoneName
- - Mono.Android.dll!Android.Runtime.AndroidEnvironment.GetDefaultTimeZone
-*/
-
-MONO_API void
-monodroid_free (void *ptr)
-{
- free (ptr);
-}
-
-MONO_API int
-monodroid_get_system_property (const char *name, char **value)
-{
- return androidSystem.monodroid_get_system_property (name, value);
-}
-
-MONO_API int
-_monodroid_max_gref_get (void)
-{
- return static_cast(androidSystem.get_max_gref_count ());
-}
-
-MONO_API int
-_monodroid_gref_get (void)
-{
- return osBridge.get_gc_gref_count ();
-}
-
-MONO_API void
-_monodroid_gref_log (const char *message)
-{
- osBridge._monodroid_gref_log (message);
-}
-
-MONO_API 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);
-}
-
-MONO_API 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);
-}
-
-MONO_API 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);
-}
-
-MONO_API 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);
-}
-
-MONO_API 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);
-}
-
-MONO_API 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);
-}
-
-MONO_API void
-_monodroid_gc_wait_for_bridge_processing (void)
-{
- mono_gc_wait_for_bridge_processing ();
-}
-
-/* !DO NOT REMOVE! Used by Mono BCL */
-MONO_API int
-_monodroid_get_android_api_level (void)
-{
- return monodroidRuntime.get_android_api_level ();
-}
-
-/* Can be called by a native debugger to break the wait on startup */
-MONO_API void
-monodroid_clear_gdb_wait (void)
-{
- monodroidRuntime.set_monodroid_gdb_wait (false);
-}
-
-MONO_API 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;
-}
-
-MONO_API void*
-_monodroid_timezone_get_default_id (void)
-{
- 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);
- char *def_id = strdup (mutf8);
-
- env->ReleaseStringUTFChars (id, mutf8);
- env->DeleteLocalRef (id);
- env->DeleteLocalRef (d);
-
- return def_id;
-}
-
-MONO_API void
-_monodroid_counters_dump (const char *format, ...)
-{
- va_list args;
- va_start (args, format);
- monodroidRuntime.dump_counters_v (format, args);
- va_end (args);
-}
-
-/* !DO NOT REMOVE! Used by libgdiplus.so */
-MONO_API int
-_monodroid_get_display_dpi (float *x_dpi, float *y_dpi)
-{
- return monodroidRuntime.get_display_dpi (x_dpi, y_dpi);
-}
-
-MONO_API int monodroid_embedded_assemblies_set_assemblies_prefix (const char *prefix)
-{
- embeddedAssemblies.set_assemblies_prefix (prefix);
- return 0;
-}
-
-MONO_API 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;
-}
-
-MONO_API 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);
-}
-
-MONO_API void
-monodroid_strfreev (char **str_array)
-{
- utils.monodroid_strfreev (str_array);
-}
-
-MONO_API char**
-monodroid_strsplit (const char *str, const char *delimiter, size_t max_tokens)
-{
- return utils.monodroid_strsplit (str, delimiter, max_tokens);
-}
-
-MONO_API 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;
-}
-
-MONO_API char*
-monodroid_TypeManager_get_java_class_name (jclass klass)
-{
- return monodroidRuntime.get_java_class_name_for_TypeManager (klass);
-}
-
-MONO_API void
-monodroid_store_package_name (const char *name)
-{
- utils.monodroid_store_package_name (name);
-}
-
-MONO_API int
-monodroid_get_namespaced_system_property (const char *name, char **value)
-{
- return static_cast(androidSystem.monodroid_get_system_property (name, value));
-}
-
-MONO_API FILE*
-monodroid_fopen (const char* filename, const char* mode)
-{
- return utils.monodroid_fopen (filename, mode);
-}
-
-MONO_API int
-send_uninterrupted (int fd, void *buf, int len)
-{
- if (len < 0)
- len = 0;
- return utils.send_uninterrupted (fd, buf, static_cast(len));
-}
-
-MONO_API 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)));
-}
-
-MONO_API void
-set_world_accessable (const char *path)
-{
- utils.set_world_accessable (path);
-}
-
-MONO_API void
-create_public_directory (const char *dir)
-{
- utils.create_public_directory (dir);
-}
-
-MONO_API char*
-path_combine (const char *path1, const char *path2)
-{
- return utils.path_combine (path1, path2);
-}
-
-MONO_API void*
-monodroid_dylib_mono_new ([[maybe_unused]] const char *libmono_path)
-{
- return nullptr;
-}
-
-MONO_API 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
-*/
-MONO_API int
-monodroid_dylib_mono_init (void *mono_imports, [[maybe_unused]] const char *libmono_path)
-{
- if (mono_imports == nullptr)
- return FALSE;
- return TRUE;
-}
-
-MONO_API void*
-monodroid_get_dylib (void)
-{
- return nullptr;
-}
diff --git a/src/monodroid/jni/internal-pinvoke-api.cc b/src/monodroid/jni/internal-pinvoke-api.cc
new file mode 100644
index 00000000000..d5218de566d
--- /dev/null
+++ b/src/monodroid/jni/internal-pinvoke-api.cc
@@ -0,0 +1,336 @@
+#include
+#include
+#include
+
+#include "xa-internal-api.hh"
+
+constexpr int TRUE = 1;
+constexpr int FALSE = 0;
+
+using namespace xamarin::android;
+
+static MonoAndroidInternalCalls *internal_calls = nullptr;
+
+MONO_API bool
+_monodroid_init_internal_api (MonoAndroidInternalCalls *api)
+{
+ if (api == nullptr)
+ return false;
+
+ delete internal_calls;
+ internal_calls = api;
+ return true;
+}
+
+MONO_API void
+_monodroid_shutdown_internal_api ()
+{
+ if (internal_calls == nullptr)
+ return;
+
+ delete internal_calls;
+ internal_calls = nullptr;
+}
+
+MONO_API int
+_monodroid_getifaddrs (struct _monodroid_ifaddrs **ifap)
+{
+ return internal_calls->monodroid_getifaddrs (ifap);
+}
+
+MONO_API void
+_monodroid_freeifaddrs (struct _monodroid_ifaddrs *ifa)
+{
+ internal_calls->monodroid_freeifaddrs (ifa);
+}
+
+MONO_API void
+_monodroid_detect_cpu_and_architecture (unsigned short *built_for_cpu, unsigned short *running_on_cpu, unsigned char *is64bit)
+{
+ internal_calls->monodroid_detect_cpu_and_architecture (built_for_cpu, running_on_cpu, is64bit);
+}
+
+// !DO NOT REMOVE! Used by Mono BCL (System.Net.NetworkInformation.NetworkInterface)
+// https://github.com/mono/mono/blob/e59c1cd70f4a7171a0ff5e1f9f4937985d6a4d8d/mcs/class/System/System.Net.NetworkInformation/LinuxNetworkInterface.cs#L250-L261
+MONO_API mono_bool
+_monodroid_get_network_interface_up_state (const char *ifname, mono_bool *is_up)
+{
+ return internal_calls->monodroid_get_network_interface_up_state (ifname, is_up);
+}
+
+/* !DO NOT REMOVE! Used by Mono BCL (System.Net.NetworkInformation.NetworkInterface) */
+MONO_API mono_bool
+_monodroid_get_network_interface_supports_multicast (const char *ifname, mono_bool *supports_multicast)
+{
+ return internal_calls->monodroid_get_network_interface_supports_multicast (ifname, supports_multicast);
+}
+
+/* !DO NOT REMOVE! Used by Mono BCL (System.Net.NetworkInformation.UnixIPInterfaceProperties) */
+MONO_API int
+_monodroid_get_dns_servers (void **dns_servers_array)
+{
+ return internal_calls->monodroid_get_dns_servers (dns_servers_array);
+}
+
+//
+// DO NOT REMOVE: used by Android.Runtime.Logger
+//
+MONO_API unsigned int
+monodroid_get_log_categories ()
+{
+ return internal_calls->monodroid_get_log_categories ();
+}
+
+//
+// DO NOT REMOVE: used by Android.Runtime.JNIEnv
+//
+MONO_API void
+monodroid_log (LogLevel level, LogCategories category, const char *message)
+{
+ internal_calls->monodroid_log (level, category, message);
+}
+
+/* Invoked by:
+ - System.Core.dll!System.TimeZoneInfo.Android.GetDefaultTimeZoneName
+ https://github.com/mono/mono/blob/e59c1cd70f4a7171a0ff5e1f9f4937985d6a4d8d/mcs/class/corlib/System/TimeZoneInfo.Android.cs#L569-L594
+ - Mono.Android.dll!Android.Runtime.AndroidEnvironment.GetDefaultTimeZone
+*/
+
+MONO_API void
+monodroid_free (void *ptr)
+{
+ free (ptr);
+}
+
+// Used by https://github.com/mono/mono/blob/e59c1cd70f4a7171a0ff5e1f9f4937985d6a4d8d/mcs/class/corlib/System/TimeZoneInfo.Android.cs#L569-L594
+MONO_API int
+monodroid_get_system_property (const char *name, char **value)
+{
+ return internal_calls->monodroid_get_system_property (name, value);
+}
+
+// Used by Mono.Android.dll!Java.Interop.Runtime.MaxGlobalReferenceCount
+MONO_API int
+_monodroid_max_gref_get (void)
+{
+ return internal_calls->monodroid_max_gref_get ();
+}
+
+// Used by Mono.Android.dll!Java.Interop.Runtime.GlobalReferenceCount
+MONO_API int
+_monodroid_gref_get (void)
+{
+ return internal_calls->monodroid_gref_get ();
+}
+
+// Used by Mono.Android.dll!Android.Runtime.JNIEnv
+MONO_API void
+_monodroid_gref_log (const char *message)
+{
+ internal_calls->monodroid_gref_log (message);
+}
+
+MONO_API 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 internal_calls->monodroid_gref_log_new (curHandle, curType, newHandle, newType, threadName, threadId, from, from_writable);
+}
+
+MONO_API void
+_monodroid_gref_log_delete (jobject handle, char type, const char *threadName, int threadId, const char *from, int from_writable)
+{
+ internal_calls->monodroid_gref_log_delete (handle, type, threadName, threadId, from, from_writable);
+}
+
+MONO_API void
+_monodroid_weak_gref_new (jobject curHandle, char curType, jobject newHandle, char newType, const char *threadName, int threadId, const char *from, int from_writable)
+{
+ internal_calls->monodroid_weak_gref_new (curHandle, curType, newHandle, newType, threadName, threadId, from, from_writable);
+}
+
+MONO_API void
+_monodroid_weak_gref_delete (jobject handle, char type, const char *threadName, int threadId, const char *from, int from_writable)
+{
+ internal_calls->monodroid_weak_gref_delete (handle, type, threadName, threadId, from, from_writable);
+}
+
+MONO_API void
+_monodroid_lref_log_new (int lrefc, jobject handle, char type, const char *threadName, int threadId, const char *from, int from_writable)
+{
+ internal_calls->monodroid_lref_log_new (lrefc, handle, type, threadName, threadId, from, from_writable);
+}
+
+MONO_API void
+_monodroid_lref_log_delete (int lrefc, jobject handle, char type, const char *threadName, int threadId, const char *from, int from_writable)
+{
+ internal_calls->monodroid_lref_log_delete (lrefc, handle, type, threadName, threadId, from, from_writable);
+}
+
+MONO_API void
+_monodroid_gc_wait_for_bridge_processing (void)
+{
+ internal_calls->monodroid_gc_wait_for_bridge_processing ();
+}
+
+/* !DO NOT REMOVE! Used by Mono BCL */
+MONO_API int
+_monodroid_get_android_api_level (void)
+{
+ return internal_calls->monodroid_get_android_api_level ();
+}
+
+/* Can be called by a native debugger to break the wait on startup */
+MONO_API void
+monodroid_clear_gdb_wait (void)
+{
+ internal_calls->monodroid_clear_gdb_wait ();
+}
+
+MONO_API void*
+_monodroid_get_identity_hash_code (JNIEnv *env, void *v)
+{
+ return internal_calls->monodroid_get_identity_hash_code (env, v);
+}
+
+MONO_API void*
+_monodroid_timezone_get_default_id (void)
+{
+ return internal_calls->monodroid_timezone_get_default_id ();
+}
+
+MONO_API void
+_monodroid_counters_dump (const char *format, ...)
+{
+ va_list args;
+ va_start (args, format);
+ internal_calls->dump_counters (format, args);
+ va_end (args);
+}
+
+MONO_API int
+monodroid_embedded_assemblies_set_assemblies_prefix (const char *prefix)
+{
+ return internal_calls->monodroid_embedded_assemblies_set_assemblies_prefix (prefix);
+}
+
+MONO_API managed_timing_sequence*
+monodroid_timing_start (const char *message)
+{
+ return internal_calls->monodroid_timing_start (message);
+}
+
+MONO_API void
+monodroid_timing_stop (managed_timing_sequence *sequence, const char *message)
+{
+ internal_calls->monodroid_timing_stop (sequence, message);
+}
+
+MONO_API void
+monodroid_strfreev (char **str_array)
+{
+ internal_calls->monodroid_strfreev (str_array);
+}
+
+MONO_API char**
+monodroid_strsplit (const char *str, const char *delimiter, size_t max_tokens)
+{
+ return internal_calls->monodroid_strsplit (str, delimiter, max_tokens);
+}
+
+MONO_API char*
+monodroid_strdup_printf (const char *format, ...)
+{
+ va_list args;
+
+ va_start (args, format);
+ char *ret = internal_calls->monodroid_strdup_printf (format, args);
+ va_end (args);
+
+ return ret;
+}
+
+MONO_API char*
+monodroid_TypeManager_get_java_class_name (jclass klass)
+{
+ return internal_calls->monodroid_TypeManager_get_java_class_name (klass);
+}
+
+MONO_API void
+monodroid_store_package_name (const char *name)
+{
+ internal_calls->monodroid_store_package_name (name);
+}
+
+MONO_API int
+monodroid_get_namespaced_system_property (const char *name, char **value)
+{
+ return internal_calls->monodroid_get_namespaced_system_property (name, value);
+}
+
+MONO_API FILE*
+monodroid_fopen (const char* filename, const char* mode)
+{
+ return internal_calls->monodroid_fopen (filename, mode);
+}
+
+MONO_API int
+send_uninterrupted (int fd, void *buf, int len)
+{
+ return internal_calls->send_uninterrupted (fd, buf, len);
+}
+
+MONO_API int
+recv_uninterrupted (int fd, void *buf, int len)
+{
+ return internal_calls->recv_uninterrupted (fd, buf, len);
+}
+
+MONO_API void
+set_world_accessable (const char *path)
+{
+ internal_calls->set_world_accessable (path);
+}
+
+MONO_API void
+create_public_directory (const char *dir)
+{
+ internal_calls->create_public_directory (dir);
+}
+
+MONO_API char*
+path_combine (const char *path1, const char *path2)
+{
+ return internal_calls->path_combine (path1, path2);
+}
+
+MONO_API void*
+monodroid_dylib_mono_new ([[maybe_unused]] const char *libmono_path)
+{
+ return nullptr;
+}
+
+MONO_API 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
+*/
+MONO_API int
+monodroid_dylib_mono_init (void *mono_imports, [[maybe_unused]] const char *libmono_path)
+{
+ if (mono_imports == nullptr)
+ return FALSE;
+ return TRUE;
+}
+
+MONO_API void*
+monodroid_get_dylib (void)
+{
+ return nullptr;
+}
diff --git a/src/monodroid/jni/logger.cc b/src/monodroid/jni/logger.cc
index c027d74d3d4..1742de28c80 100644
--- a/src/monodroid/jni/logger.cc
+++ b/src/monodroid/jni/logger.cc
@@ -41,20 +41,6 @@ static const char* log_names[] = {
"*error*",
};
-// Keep in sync with LogLevel defined in JNIEnv.cs
-enum class LogLevel : unsigned int
-{
- Unknown = 0x00,
- Default = 0x01,
- Verbose = 0x02,
- Debug = 0x03,
- Info = 0x04,
- Warn = 0x05,
- Error = 0x06,
- Fatal = 0x07,
- Silent = 0x08
-};
-
#if defined(__i386__) && defined(__GNUC__)
#define ffs(__value__) __builtin_ffs ((__value__))
#elif defined(__x86_64__) && defined(__GNUC__)
@@ -145,7 +131,7 @@ init_logging_categories ()
log_categories = LOG_DEFAULT;
#endif
log_timing_categories = LOG_TIMING_DEFAULT;
- if (monodroid_get_namespaced_system_property (Debug::DEBUG_MONO_LOG_PROPERTY, &value) == 0)
+ if (androidSystem.monodroid_get_system_property (Debug::DEBUG_MONO_LOG_PROPERTY, &value) == 0)
return;
args = utils.monodroid_strsplit (value, ",", 0);
@@ -253,49 +239,3 @@ log_debug_nocheck (LogCategories category, const char *format, ...)
DO_LOG (ANDROID_LOG_DEBUG, category, format, args);
}
-
-//
-// DO NOT REMOVE: used by Android.Runtime.Logger
-//
-MONO_API unsigned int
-monodroid_get_log_categories ()
-{
- return log_categories;
-}
-
-//
-// DO NOT REMOVE: used by Android.Runtime.JNIEnv
-//
-MONO_API 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;
- }
-}
diff --git a/src/monodroid/jni/logger.hh b/src/monodroid/jni/logger.hh
index 75ee3f4a705..8691ab04750 100644
--- a/src/monodroid/jni/logger.hh
+++ b/src/monodroid/jni/logger.hh
@@ -32,4 +32,17 @@ extern unsigned int log_timing_categories;
extern int gc_spew_enabled;
#endif
+// Keep in sync with LogLevel defined in JNIEnv.cs
+enum class LogLevel : unsigned int
+{
+ Unknown = 0x00,
+ Default = 0x01,
+ Verbose = 0x02,
+ Debug = 0x03,
+ Info = 0x04,
+ Warn = 0x05,
+ Error = 0x06,
+ Fatal = 0x07,
+ Silent = 0x08
+};
#endif
diff --git a/src/monodroid/jni/monodroid-glue-internal.hh b/src/monodroid/jni/monodroid-glue-internal.hh
index 0ca8a35f271..9b92ea55382 100644
--- a/src/monodroid/jni/monodroid-glue-internal.hh
+++ b/src/monodroid/jni/monodroid-glue-internal.hh
@@ -61,7 +61,14 @@ 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);
+#elif defined (APPLE_OS_X)
+ static constexpr char API_DSO_NAME[] = MAKE_API_DSO_NAME (dylib);
+#else // !defined(WINDOWS) && !defined(APPLE_OS_X)
+ static constexpr char API_DSO_NAME[] = MAKE_API_DSO_NAME (so);
+#endif // defined(WINDOWS)
public:
static constexpr int XA_LOG_COUNTERS = MONO_COUNTER_JIT | MONO_COUNTER_METADATA | MONO_COUNTER_GC | MONO_COUNTER_GENERICS | MONO_COUNTER_INTERP;
@@ -131,9 +138,13 @@ namespace xamarin::android::internal
private:
int convert_dl_flags (int flags);
+#if defined (WINDOWS) || defined (APPLE_OS_X)
+ static const char* get_my_location ();
+#endif // defined(WINDOWS) || defined(APPLE_OS_X)
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);
+ static void* monodroid_dlopen_log_and_return (void *handle, char **err, const char *full_name, bool free_memory, bool need_api_init = false);
+ static void init_internal_api_dso (void *handle);
int LocalRefsAreIndirect (JNIEnv *env, jclass runtimeClass, int version);
void create_xdg_directory (jstring_wrapper& home, const char *relativePath, const char *environmentVariableName);
void create_xdg_directories_and_environment (jstring_wrapper &homeDir);
@@ -218,6 +229,9 @@ namespace xamarin::android::internal
* able to switch our different contexts from different threads.
*/
int current_context_id = -1;
+
+ static std::mutex api_init_lock;
+ static void *api_dso_handle;
};
}
#endif
diff --git a/src/monodroid/jni/monodroid-glue.cc b/src/monodroid/jni/monodroid-glue.cc
index 181f9d0b36a..a1fbd9ffdc7 100644
--- a/src/monodroid/jni/monodroid-glue.cc
+++ b/src/monodroid/jni/monodroid-glue.cc
@@ -40,6 +40,10 @@
#include
#endif
+#if defined (APPLE_OS_X)
+#include
+#endif // defined(APPLE_OS_X)
+
#ifndef WINDOWS
#include
#include
@@ -70,6 +74,7 @@
#include "globals.hh"
#include "xamarin-app.hh"
#include "timing.hh"
+#include "xa-internal-api-impl.hh"
#ifndef WINDOWS
#include "xamarin_getifaddrs.h"
@@ -87,6 +92,9 @@ using namespace xamarin::android::internal;
#include "config.include"
#include "machine.config.include"
+std::mutex MonodroidRuntime::api_init_lock;
+void *MonodroidRuntime::api_dso_handle = nullptr;
+
#ifdef WINDOWS
static const char* get_xamarin_android_msbuild_path (void);
const char *BasicAndroidSystem::SYSTEM_LIB_PATH = get_xamarin_android_msbuild_path();
@@ -1056,7 +1064,7 @@ setup_gc_logging (void)
}
#endif
-inline int
+force_inline int
MonodroidRuntime::convert_dl_flags (int flags)
{
int lflags = flags & static_cast (MONO_DL_LOCAL) ? 0: RTLD_GLOBAL;
@@ -1068,8 +1076,56 @@ MonodroidRuntime::convert_dl_flags (int flags)
return lflags;
}
-inline void*
-MonodroidRuntime::monodroid_dlopen_log_and_return (void *handle, char **err, const char *full_name, bool free_memory)
+force_inline void
+MonodroidRuntime::init_internal_api_dso (void *handle)
+{
+ if (handle == nullptr) {
+ log_fatal (LOG_DEFAULT, "Internal API library is required");
+ exit (FATAL_EXIT_MONO_MISSING_SYMBOLS);
+ }
+
+ // There's a very, very small chance of a race condition here, but it should be acceptable and we can save some time
+ // by not acquiring the lock on Android systems which don't have the dlopen bug we worked around in
+ // https://github.com/xamarin/xamarin-android/pull/4914
+ //
+ // The race condition will exist only on systems with the above dynamic loader bug and would become a problem only
+ // if an application were loading managed assemblies with p/invokes very quickly from different threads. All in all,
+ // not a very likely scenario.
+ //
+ if (handle == api_dso_handle) {
+ log_debug (LOG_DEFAULT, "Internal API library already loaded, initialization not necessary");
+ return;
+ }
+
+ std::lock_guard lock (api_init_lock);
+ if (api_dso_handle != nullptr) {
+ auto api_shutdown = reinterpret_cast (dlsym (api_dso_handle, MonoAndroidInternalCalls::SHUTDOWN_FUNCTION_NAME));
+ if (api_shutdown == nullptr) {
+ // We COULD ignore this situation, but if the function is missing it means we messed something up and thus
+ // it *is* a fatal error.
+ log_fatal (LOG_DEFAULT, "Unable to properly close Internal API library, shutdown function '%s' not found in the module", MonoAndroidInternalCalls::SHUTDOWN_FUNCTION_NAME);
+ exit (FATAL_EXIT_MONO_MISSING_SYMBOLS);
+ }
+ api_shutdown ();
+ }
+
+ api_dso_handle = handle;
+ auto api = new MonoAndroidInternalCalls_Impl ();
+ auto api_init = reinterpret_cast(dlsym (handle, MonoAndroidInternalCalls::INIT_FUNCTION_NAME));
+ if (api_init == nullptr) {
+ log_fatal (LOG_DEFAULT, "Unable to initialize Internal API library, init function '%s' not found in the module", MonoAndroidInternalCalls::INIT_FUNCTION_NAME);
+ exit (FATAL_EXIT_MONO_MISSING_SYMBOLS);
+ }
+
+ log_debug (LOG_DEFAULT, "Initializing Internal API library %p", handle);
+ if (!api_init (api)) {
+ log_fatal (LOG_DEFAULT, "Failed to initialize Internal API library");
+ exit (FATAL_EXIT_MONO_MISSING_SYMBOLS);
+ }
+}
+
+force_inline void*
+MonodroidRuntime::monodroid_dlopen_log_and_return (void *handle, char **err, const char *full_name, bool free_memory, bool need_api_init)
{
if (handle == nullptr && err != nullptr) {
*err = utils.monodroid_strdup_printf ("Could not load library: Library '%s' not found.", full_name);
@@ -1079,6 +1135,11 @@ MonodroidRuntime::monodroid_dlopen_log_and_return (void *handle, char **err, con
delete[] full_name;
}
+ if (!need_api_init)
+ return handle;
+
+ init_internal_api_dso (handle);
+
return handle;
}
@@ -1088,21 +1149,22 @@ MonodroidRuntime::monodroid_dlopen (const char *name, int flags, char **err, [[m
int dl_flags = monodroidRuntime.convert_dl_flags (flags);
bool libmonodroid_fallback = false;
- /* name is nullptr when we're P/Invoking __Internal, so remap to libmonodroid */
+ /* name is nullptr when we're P/Invoking __Internal, so remap to libxa-internal-api */
if (name == nullptr) {
- name = "libmonodroid.so";
- libmonodroid_fallback = TRUE;
+ name = API_DSO_NAME;
+ libmonodroid_fallback = true;
}
void *h = androidSystem.load_dso_from_any_directories (name, dl_flags);
+
if (h != nullptr) {
- return monodroid_dlopen_log_and_return (h, err, name, false);
+ return monodroid_dlopen_log_and_return (h, err, name, false, libmonodroid_fallback);
}
if (libmonodroid_fallback) {
- char *full_name = utils.path_combine (AndroidSystem::SYSTEM_LIB_PATH, "libmonodroid.so");
+ char *full_name = utils.path_combine (AndroidSystem::SYSTEM_LIB_PATH, API_DSO_NAME);
h = androidSystem.load_dso (full_name, dl_flags, false);
- return monodroid_dlopen_log_and_return (h, err, full_name, true);
+ return monodroid_dlopen_log_and_return (h, err, full_name, true, true);
}
if (!utils.ends_with (name, ".dll.so") && !utils.ends_with (name, ".exe.so")) {
@@ -1418,6 +1480,44 @@ MonodroidRuntime::typemap_managed_to_java (MonoReflectionType *type, const uint8
return embeddedAssemblies.typemap_managed_to_java (type, mvid);
}
+#if defined (WINDOWS)
+const char*
+MonodroidRuntime::get_my_location ()
+{
+ HMODULE hm = NULL;
+
+ DWORD handle_flags = GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT;
+ if (GetModuleHandleExW (handle_flags, (LPCWSTR) &get_xamarin_android_msbuild_path, &hm) == 0) {
+ int ret = GetLastError ();
+ log_warn (LOG_DEFAULT, "Unable to get HANDLE to `libmono-android.debug.dll`; GetModuleHandleExW returned %d\n", ret);
+ return nullptr;
+ }
+
+ WCHAR path[MAX_PATH * 2];
+ if (GetModuleFileNameW (hm, path, sizeof(path)) == 0) {
+ int ret = GetLastError ();
+ log_warn (LOG_DEFAULT, "Unable to get filename to `libmono-android.debug.dll`; GetModuleFileNameW returned %d\n", ret);
+ return nullptr;
+ }
+
+ PathRemoveFileSpecW (path);
+
+ return utils.utf16_to_utf8 (path);
+}
+#elif defined (APPLE_OS_X)
+const char*
+MonodroidRuntime::get_my_location ()
+{
+ Dl_info info;
+ if (dladdr (reinterpret_cast(&MonodroidRuntime::get_my_location), &info) == 0) {
+ log_warn (LOG_DEFAULT, "Could not lookup library containing `MonodroidRuntime::get_my_location()`; dladdr failed: %s", dlerror ());
+ return nullptr;
+ }
+
+ return utils.strdup_new (dirname (const_cast(info.dli_fname)));
+}
+#endif // defined(WINDOWS)
+
inline void
MonodroidRuntime::Java_mono_android_Runtime_initInternal (JNIEnv *env, jclass klass, jstring lang, jobjectArray runtimeApksJava,
jstring runtimeNativeLibDir, jobjectArray appDirs, jobject loader,
@@ -1498,6 +1598,29 @@ MonodroidRuntime::Java_mono_android_Runtime_initInternal (JNIEnv *env, jclass kl
utils.set_world_accessable (counters_path);
}
+ void *api_dso_handle = nullptr;
+#if defined (WINDOWS) || defined (APPLE_OS_X)
+ const char *my_location = get_my_location ();
+ if (my_location != nullptr) {
+ simple_pointer_guard dso_path (utils.path_combine (my_location, API_DSO_NAME));
+ log_info (LOG_DEFAULT, "Attempting to load %s", dso_path.get ());
+ api_dso_handle = dlopen (dso_path.get (), RTLD_NOW);
+#if defined (APPLE_OS_X)
+ delete[] my_location;
+#else // !defined(APPLE_OS_X)
+ free (static_cast(const_cast(my_location))); // JI allocates with `calloc`
+#endif // defined(APPLE_OS_X)
+ }
+
+ if (api_dso_handle == nullptr) {
+ log_info (LOG_DEFAULT, "Attempting to load %s with \"bare\" dlopen", API_DSO_NAME);
+ api_dso_handle = dlopen (API_DSO_NAME, RTLD_NOW);
+ }
+#endif // defined(WINDOWS) || defined(APPLE_OS_X)
+ if (api_dso_handle == nullptr)
+ api_dso_handle = androidSystem.load_dso_from_any_directories (API_DSO_NAME, RTLD_NOW);
+ init_internal_api_dso (api_dso_handle);
+
mono_dl_fallback_register (monodroid_dlopen, monodroid_dlsym, nullptr, nullptr);
set_profile_options ();
diff --git a/src/monodroid/jni/monodroid-networkinfo.cc b/src/monodroid/jni/monodroid-networkinfo.cc
index 9053aae8045..704cf425203 100644
--- a/src/monodroid/jni/monodroid-networkinfo.cc
+++ b/src/monodroid/jni/monodroid-networkinfo.cc
@@ -126,22 +126,19 @@ _monodroid_get_network_interface_state (const char *ifname, mono_bool *is_up, mo
return ret;
}
-/* !DO NOT REMOVE! Used by Mono BCL (System.Net.NetworkInformation.NetworkInterface) */
-MONO_API mono_bool
+mono_bool
_monodroid_get_network_interface_up_state (const char *ifname, mono_bool *is_up)
{
return _monodroid_get_network_interface_state (ifname, is_up, nullptr);
}
-/* !DO NOT REMOVE! Used by Mono BCL (System.Net.NetworkInformation.NetworkInterface) */
-MONO_API mono_bool
+mono_bool
_monodroid_get_network_interface_supports_multicast (const char *ifname, mono_bool *supports_multicast)
{
return _monodroid_get_network_interface_state (ifname, nullptr, supports_multicast);
}
-/* !DO NOT REMOVE! Used by Mono BCL (System.Net.NetworkInformation.UnixIPInterfaceProperties) */
-MONO_API int
+int
_monodroid_get_dns_servers (void **dns_servers_array)
{
if (!dns_servers_array) {
@@ -157,7 +154,7 @@ _monodroid_get_dns_servers (void **dns_servers_array)
char prop_name[] = "net.dnsX";
for (int i = 0; i < 8; i++) {
prop_name [7] = (char)(i + 0x31);
- len = static_cast(monodroid_get_system_property (prop_name, &dns));
+ len = static_cast(androidSystem.monodroid_get_system_property (prop_name, &dns));
if (len == 0) {
dns_servers [i] = nullptr;
continue;
diff --git a/src/monodroid/jni/util.cc b/src/monodroid/jni/util.cc
index 98dc0b0d1e5..9ccbbbd392b 100644
--- a/src/monodroid/jni/util.cc
+++ b/src/monodroid/jni/util.cc
@@ -311,3 +311,15 @@ Util::get_class_from_runtime_field (JNIEnv *env, jclass runtime, const char *nam
return reinterpret_cast (make_gref ? osBridge.lref_to_gref (env, field) : field);
}
+
+int
+Util::monodroid_getpagesize (void)
+{
+#ifndef WINDOWS
+ return getpagesize ();
+#else // defined(WINDOWS)
+ SYSTEM_INFO info;
+ GetSystemInfo (&info);
+ return info.dwPageSize;
+#endif // defined(WINDOWS)
+}
diff --git a/src/monodroid/jni/util.hh b/src/monodroid/jni/util.hh
index 20077fb239b..80bc187dbf7 100644
--- a/src/monodroid/jni/util.hh
+++ b/src/monodroid/jni/util.hh
@@ -74,6 +74,7 @@ namespace xamarin::android
static constexpr uint32_t ms_in_nsec = 1000000ULL;
public:
+ int monodroid_getpagesize ();
void monodroid_store_package_name (const char *name);
MonoAssembly *monodroid_load_assembly (MonoDomain *domain, const char *basename);
MonoObject *monodroid_runtime_invoke (MonoDomain *domain, MonoMethod *method, void *obj, void **params, MonoObject **exc);
diff --git a/src/monodroid/jni/xa-internal-api-impl.hh b/src/monodroid/jni/xa-internal-api-impl.hh
new file mode 100644
index 00000000000..7fdae521174
--- /dev/null
+++ b/src/monodroid/jni/xa-internal-api-impl.hh
@@ -0,0 +1,53 @@
+// Dear Emacs, this is a -*- C++ -*- header
+#ifndef __XA_INTERNAL_API_IMPL_HH
+#define __XA_INTERNAL_API_IMPL_HH
+
+#include "xa-internal-api.hh"
+
+namespace xamarin::android::internal
+{
+ class MonoAndroidInternalCalls_Impl final : public MonoAndroidInternalCalls
+ {
+ public:
+ virtual mono_bool monodroid_get_network_interface_up_state (const char *ifname, mono_bool *is_up) final override;
+ virtual mono_bool monodroid_get_network_interface_supports_multicast (const char *ifname, mono_bool *supports_multicast) final override;
+ virtual int monodroid_get_dns_servers (void **dns_servers_array) final override;
+ virtual int monodroid_getifaddrs (_monodroid_ifaddrs **ifap) final override;
+ virtual void monodroid_freeifaddrs (_monodroid_ifaddrs *ifa) final override;
+ virtual void monodroid_detect_cpu_and_architecture (unsigned short *built_for_cpu, unsigned short *running_on_cpu, unsigned char *is64bit) final override;
+ virtual unsigned int monodroid_get_log_categories () final override;
+ virtual void monodroid_log (LogLevel level, LogCategories category, const char *message) final override;
+ virtual int monodroid_get_system_property (const char *name, char **value) final override;
+ virtual int monodroid_max_gref_get () final override;
+ virtual int monodroid_gref_get () final override;
+ virtual void monodroid_gref_log (const char *message) final override;
+ virtual int monodroid_gref_log_new (jobject curHandle, char curType, jobject newHandle, char newType, const char *threadName, int threadId, const char *from, int from_writable) final override;
+ virtual void monodroid_gref_log_delete (jobject handle, char type, const char *threadName, int threadId, const char *from, int from_writable) final override;
+ virtual void monodroid_weak_gref_new (jobject curHandle, char curType, jobject newHandle, char newType, const char *threadName, int threadId, const char *from, int from_writable) final override;
+ virtual void monodroid_weak_gref_delete (jobject handle, char type, const char *threadName, int threadId, const char *from, int from_writable) final override;
+ virtual void monodroid_lref_log_new (int lrefc, jobject handle, char type, const char *threadName, int threadId, const char *from, int from_writable) final override;
+ virtual void monodroid_lref_log_delete (int lrefc, jobject handle, char type, const char *threadName, int threadId, const char *from, int from_writable) final override;
+ virtual void monodroid_gc_wait_for_bridge_processing () final override;
+ virtual int monodroid_get_android_api_level () final override;
+ virtual void monodroid_clear_gdb_wait () final override;
+ virtual void* monodroid_get_identity_hash_code (JNIEnv *env, void *v) final override;
+ virtual void* monodroid_timezone_get_default_id () final override;
+ virtual void dump_counters (const char *format, va_list args) final override;
+ virtual int monodroid_embedded_assemblies_set_assemblies_prefix (const char *prefix) final override;
+ virtual managed_timing_sequence* monodroid_timing_start (const char *message) final override;
+ virtual void monodroid_timing_stop (managed_timing_sequence *sequence, const char *message) final override;
+ virtual void monodroid_strfreev (char **str_array) final override;
+ virtual char** monodroid_strsplit (const char *str, const char *delimiter, size_t max_tokens) final override;
+ virtual char* monodroid_strdup_printf (const char *format, va_list args) final override;
+ virtual char* monodroid_TypeManager_get_java_class_name (jclass klass) final override;
+ virtual void monodroid_store_package_name (const char *name) final override;
+ virtual int monodroid_get_namespaced_system_property (const char *name, char **value) final override;
+ virtual FILE* monodroid_fopen (const char* filename, const char* mode) final override;
+ virtual int send_uninterrupted (int fd, void *buf, int len) final override;
+ virtual int recv_uninterrupted (int fd, void *buf, int len) final override;
+ virtual void set_world_accessable (const char *path) final override;
+ virtual void create_public_directory (const char *dir) final override;
+ virtual char* path_combine (const char *path1, const char *path2) final override;
+ };
+}
+#endif // __XA_INTERNAL_API_IMPL_HH
diff --git a/src/monodroid/jni/xa-internal-api.cc b/src/monodroid/jni/xa-internal-api.cc
new file mode 100644
index 00000000000..0f68a80fb4a
--- /dev/null
+++ b/src/monodroid/jni/xa-internal-api.cc
@@ -0,0 +1,335 @@
+#ifdef WINDOWS
+#include
+#include
+#include
+#include
+#include
+#include
+#endif // defined(WINDOWS)
+
+#include "globals.hh"
+#include "xa-internal-api-impl.hh"
+
+using namespace xamarin::android;
+using namespace xamarin::android::internal;
+
+void _monodroid_detect_cpu_and_architecture (unsigned short *built_for_cpu, unsigned short *running_on_cpu, unsigned char *is64bit);
+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);
+int _monodroid_getifaddrs (struct _monodroid_ifaddrs **ifap);
+void _monodroid_freeifaddrs (struct _monodroid_ifaddrs *ifa);
+
+mono_bool
+MonoAndroidInternalCalls_Impl::monodroid_get_network_interface_up_state (const char *ifname, mono_bool *is_up)
+{
+#ifdef WINDOWS
+ return FALSE;
+#else // !defined(WINDOWS)
+ return ::_monodroid_get_network_interface_up_state (ifname, is_up);
+#endif // defined(WINDOWS)
+}
+
+mono_bool
+MonoAndroidInternalCalls_Impl::monodroid_get_network_interface_supports_multicast (const char *ifname, mono_bool *supports_multicast)
+{
+#ifdef WINDOWS
+ return FALSE;
+#else // !defined(WINDOWS)
+ return ::_monodroid_get_network_interface_supports_multicast (ifname, supports_multicast);
+#endif // defined(WINDOWS)
+}
+
+int
+MonoAndroidInternalCalls_Impl::monodroid_get_dns_servers (void **dns_servers_array)
+{
+#ifdef WINDOWS
+ return FALSE;
+#else // !defined(WINDOWS)
+ return ::_monodroid_get_dns_servers (dns_servers_array);
+#endif // defined(WINDOWS)
+}
+
+int
+MonoAndroidInternalCalls_Impl::monodroid_getifaddrs (struct _monodroid_ifaddrs **ifap)
+{
+#ifdef WINDOWS
+ return -1;
+#else // !defined(WINDOWS)
+ return ::_monodroid_getifaddrs (ifap);
+#endif // defined(WINDOWS)
+}
+
+void
+MonoAndroidInternalCalls_Impl::monodroid_freeifaddrs (struct _monodroid_ifaddrs *ifa)
+{
+#ifndef WINDOWS
+ ::_monodroid_freeifaddrs (ifa);
+#endif // defined(WINDOWS)
+}
+
+void
+MonoAndroidInternalCalls_Impl::monodroid_detect_cpu_and_architecture (unsigned short *built_for_cpu, unsigned short *running_on_cpu, unsigned char *is64bit)
+{
+ ::_monodroid_detect_cpu_and_architecture (built_for_cpu, running_on_cpu, is64bit);
+}
+
+unsigned int
+MonoAndroidInternalCalls_Impl::monodroid_get_log_categories ()
+{
+ return log_categories;
+}
+
+void
+MonoAndroidInternalCalls_Impl::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;
+ }
+}
+
+int
+MonoAndroidInternalCalls_Impl::monodroid_get_system_property (const char *name, char **value)
+{
+ return androidSystem.monodroid_get_system_property (name, value);
+}
+
+int
+MonoAndroidInternalCalls_Impl::monodroid_max_gref_get ()
+{
+ return static_cast(androidSystem.get_max_gref_count ());
+}
+
+int
+MonoAndroidInternalCalls_Impl::monodroid_gref_get ()
+{
+ return osBridge.get_gc_gref_count ();
+}
+
+void
+MonoAndroidInternalCalls_Impl::monodroid_gref_log (const char *message)
+{
+ osBridge._monodroid_gref_log (message);
+}
+
+int
+MonoAndroidInternalCalls_Impl::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);
+}
+
+void
+MonoAndroidInternalCalls_Impl::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);
+}
+
+void
+MonoAndroidInternalCalls_Impl::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);
+}
+
+void
+MonoAndroidInternalCalls_Impl::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);
+}
+
+void
+MonoAndroidInternalCalls_Impl::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);
+}
+
+void
+MonoAndroidInternalCalls_Impl::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);
+}
+
+void
+MonoAndroidInternalCalls_Impl::monodroid_gc_wait_for_bridge_processing ()
+{
+ mono_gc_wait_for_bridge_processing ();
+}
+
+int
+MonoAndroidInternalCalls_Impl::monodroid_get_android_api_level ()
+{
+ return monodroidRuntime.get_android_api_level ();
+}
+
+void
+MonoAndroidInternalCalls_Impl::monodroid_clear_gdb_wait ()
+{
+ monodroidRuntime.set_monodroid_gdb_wait (false);
+}
+
+void*
+MonoAndroidInternalCalls_Impl::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;
+}
+
+void*
+MonoAndroidInternalCalls_Impl::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);
+ char *def_id = strdup (mutf8);
+
+ env->ReleaseStringUTFChars (id, mutf8);
+ env->DeleteLocalRef (id);
+ env->DeleteLocalRef (d);
+
+ return def_id;
+}
+
+void
+MonoAndroidInternalCalls_Impl::dump_counters (const char *format, va_list args)
+{
+ monodroidRuntime.dump_counters_v (format, args);
+}
+
+int
+MonoAndroidInternalCalls_Impl::monodroid_embedded_assemblies_set_assemblies_prefix (const char *prefix)
+{
+ embeddedAssemblies.set_assemblies_prefix (prefix);
+ return 0;
+}
+
+managed_timing_sequence*
+MonoAndroidInternalCalls_Impl::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;
+}
+
+void
+MonoAndroidInternalCalls_Impl::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);
+}
+
+void
+MonoAndroidInternalCalls_Impl::monodroid_strfreev (char **str_array)
+{
+ utils.monodroid_strfreev (str_array);
+}
+
+char**
+MonoAndroidInternalCalls_Impl::monodroid_strsplit (const char *str, const char *delimiter, size_t max_tokens)
+{
+ return utils.monodroid_strsplit (str, delimiter, max_tokens);
+}
+
+char*
+MonoAndroidInternalCalls_Impl::monodroid_strdup_printf (const char *format, va_list args)
+{
+ return utils.monodroid_strdup_vprintf (format, args);
+}
+
+char*
+MonoAndroidInternalCalls_Impl::monodroid_TypeManager_get_java_class_name (jclass klass)
+{
+ return monodroidRuntime.get_java_class_name_for_TypeManager (klass);
+}
+
+void
+MonoAndroidInternalCalls_Impl::monodroid_store_package_name (const char *name)
+{
+ utils.monodroid_store_package_name (name);
+}
+
+int
+MonoAndroidInternalCalls_Impl::monodroid_get_namespaced_system_property (const char *name, char **value)
+{
+ return static_cast(androidSystem.monodroid_get_system_property (name, value));
+}
+
+FILE*
+MonoAndroidInternalCalls_Impl::monodroid_fopen (const char* filename, const char* mode)
+{
+ return utils.monodroid_fopen (filename, mode);
+}
+
+int
+MonoAndroidInternalCalls_Impl::send_uninterrupted (int fd, void *buf, int len)
+{
+ if (len < 0)
+ len = 0;
+ return utils.send_uninterrupted (fd, buf, static_cast(len));
+}
+
+int
+MonoAndroidInternalCalls_Impl::recv_uninterrupted (int fd, void *buf, int len)
+{
+ if (len < 0)
+ len = 0;
+ return static_cast(utils.recv_uninterrupted (fd, buf, static_cast(len)));
+}
+
+void
+MonoAndroidInternalCalls_Impl::set_world_accessable (const char *path)
+{
+ utils.set_world_accessable (path);
+}
+
+void
+MonoAndroidInternalCalls_Impl::create_public_directory (const char *dir)
+{
+ utils.create_public_directory (dir);
+}
+
+char*
+MonoAndroidInternalCalls_Impl::path_combine (const char *path1, const char *path2)
+{
+ return utils.path_combine (path1, path2);
+}
diff --git a/src/monodroid/jni/xa-internal-api.hh b/src/monodroid/jni/xa-internal-api.hh
new file mode 100644
index 00000000000..7f2c99dcb3f
--- /dev/null
+++ b/src/monodroid/jni/xa-internal-api.hh
@@ -0,0 +1,71 @@
+// Dear Emacs, this is a -*- C++ -*- header
+#ifndef __XA_INTERNAL_API_HH
+#define __XA_INTERNAL_API_HH
+
+#include
+#include
+#include
+
+#include "monodroid.h"
+#include "logger.hh"
+#include "timing.hh"
+#include "xamarin_getifaddrs.h"
+
+namespace xamarin::android
+{
+ class MonoAndroidInternalCalls
+ {
+ public:
+ static constexpr char INIT_FUNCTION_NAME[] = "_monodroid_init_internal_api";
+ static constexpr char SHUTDOWN_FUNCTION_NAME[] = "_monodroid_shutdown_internal_api";
+
+ // To shush compiler warnings
+ virtual ~MonoAndroidInternalCalls ()
+ {}
+
+ public:
+ virtual mono_bool monodroid_get_network_interface_up_state (const char *ifname, mono_bool *is_up) = 0;
+ virtual mono_bool monodroid_get_network_interface_supports_multicast (const char *ifname, mono_bool *supports_multicast) = 0;
+ virtual int monodroid_get_dns_servers (void **dns_servers_array) = 0;
+ virtual int monodroid_getifaddrs (_monodroid_ifaddrs **ifap) = 0;
+ virtual void monodroid_freeifaddrs (_monodroid_ifaddrs *ifa) = 0;
+ virtual void monodroid_detect_cpu_and_architecture (unsigned short *built_for_cpu, unsigned short *running_on_cpu, unsigned char *is64bit) = 0;
+ virtual unsigned int monodroid_get_log_categories () = 0;
+ virtual void monodroid_log (LogLevel level, LogCategories category, const char *message) = 0;
+ virtual int monodroid_get_system_property (const char *name, char **value) = 0;
+ virtual int monodroid_max_gref_get () = 0;
+ virtual int monodroid_gref_get () = 0;
+ virtual void monodroid_gref_log (const char *message) = 0;
+ virtual int monodroid_gref_log_new (jobject curHandle, char curType, jobject newHandle, char newType, const char *threadName, int threadId, const char *from, int from_writable) = 0;
+ virtual void monodroid_gref_log_delete (jobject handle, char type, const char *threadName, int threadId, const char *from, int from_writable) = 0;
+ virtual void monodroid_weak_gref_new (jobject curHandle, char curType, jobject newHandle, char newType, const char *threadName, int threadId, const char *from, int from_writable) = 0;
+ virtual void monodroid_weak_gref_delete (jobject handle, char type, const char *threadName, int threadId, const char *from, int from_writable) = 0;
+ virtual void monodroid_lref_log_new (int lrefc, jobject handle, char type, const char *threadName, int threadId, const char *from, int from_writable) = 0;
+ virtual void monodroid_lref_log_delete (int lrefc, jobject handle, char type, const char *threadName, int threadId, const char *from, int from_writable) = 0;
+ virtual void monodroid_gc_wait_for_bridge_processing () = 0;
+ virtual int monodroid_get_android_api_level () = 0;
+ virtual void monodroid_clear_gdb_wait () = 0;
+ virtual void* monodroid_get_identity_hash_code (JNIEnv *env, void *v) = 0;
+ virtual void* monodroid_timezone_get_default_id () = 0;
+ virtual void dump_counters (const char *format, va_list args) = 0;
+ virtual int monodroid_embedded_assemblies_set_assemblies_prefix (const char *prefix) = 0;
+ virtual managed_timing_sequence* monodroid_timing_start (const char *message) = 0;
+ virtual void monodroid_timing_stop (managed_timing_sequence *sequence, const char *message) = 0;
+ virtual void monodroid_strfreev (char **str_array) = 0;
+ virtual char** monodroid_strsplit (const char *str, const char *delimiter, size_t max_tokens) = 0;
+ virtual char* monodroid_strdup_printf (const char *format, va_list args) = 0;
+ virtual char* monodroid_TypeManager_get_java_class_name (jclass klass) = 0;
+ virtual void monodroid_store_package_name (const char *name) = 0;
+ virtual int monodroid_get_namespaced_system_property (const char *name, char **value) = 0;
+ virtual FILE* monodroid_fopen (const char* filename, const char* mode) = 0;
+ virtual int send_uninterrupted (int fd, void *buf, int len) = 0;
+ virtual int recv_uninterrupted (int fd, void *buf, int len) = 0;
+ virtual void set_world_accessable (const char *path) = 0;
+ virtual void create_public_directory (const char *dir) = 0;
+ virtual char* path_combine (const char *path1, const char *path2) = 0;
+ };
+
+ typedef bool (*external_api_init_fn) (MonoAndroidInternalCalls *api);
+ typedef void (*external_api_shutdown_fn) ();
+}
+#endif // __XA_INTERNAL_API_HH
diff --git a/src/monodroid/jni/xamarin_getifaddrs.h b/src/monodroid/jni/xamarin_getifaddrs.h
index 940a12b46e6..a916d7a7999 100644
--- a/src/monodroid/jni/xamarin_getifaddrs.h
+++ b/src/monodroid/jni/xamarin_getifaddrs.h
@@ -1,4 +1,5 @@
#ifndef __XAMARIN_GETIFADDRS_H
+#define __XAMARIN_GETIFADDRS_H
#include "monodroid.h"