|
|
|
@ -20,6 +20,7 @@ using System; |
|
|
|
|
using System.Collections.Concurrent; |
|
|
|
|
using System.Diagnostics; |
|
|
|
|
using System.IO; |
|
|
|
|
using System.Linq; |
|
|
|
|
using System.Reflection; |
|
|
|
|
using System.Runtime.InteropServices; |
|
|
|
|
using System.Threading; |
|
|
|
@ -32,7 +33,11 @@ namespace Grpc.Core.Internal |
|
|
|
|
/// </summary> |
|
|
|
|
internal static class PlatformApis |
|
|
|
|
{ |
|
|
|
|
const string UnityEngineApplicationClassName = "UnityEngine.Application, UnityEngine"; |
|
|
|
|
const string UnityEngineAssemblyName = "UnityEngine"; |
|
|
|
|
|
|
|
|
|
const string UnityEngineApplicationClassName = "UnityEngine.Application"; |
|
|
|
|
|
|
|
|
|
const string UnityIPhonePlayer = "IPhonePlayer"; |
|
|
|
|
const string XamarinAndroidObjectClassName = "Java.Lang.Object, Mono.Android"; |
|
|
|
|
const string XamarinIOSObjectClassName = "Foundation.NSObject, Xamarin.iOS"; |
|
|
|
|
|
|
|
|
@ -41,8 +46,7 @@ namespace Grpc.Core.Internal |
|
|
|
|
static readonly bool isWindows; |
|
|
|
|
static readonly bool isMono; |
|
|
|
|
static readonly bool isNetCore; |
|
|
|
|
static readonly bool isUnity; |
|
|
|
|
static readonly bool isUnityIOS; |
|
|
|
|
static readonly string unityApplicationPlatform; |
|
|
|
|
static readonly bool isXamarin; |
|
|
|
|
static readonly bool isXamarinIOS; |
|
|
|
|
static readonly bool isXamarinAndroid; |
|
|
|
@ -70,21 +74,7 @@ namespace Grpc.Core.Internal |
|
|
|
|
isMono = Type.GetType("Mono.Runtime") != null; |
|
|
|
|
|
|
|
|
|
// Unity |
|
|
|
|
var unityApplicationClass = Type.GetType(UnityEngineApplicationClassName); |
|
|
|
|
if (unityApplicationClass != null) |
|
|
|
|
{ |
|
|
|
|
isUnity = true; |
|
|
|
|
// Consult value of Application.platform via reflection |
|
|
|
|
// https://docs.unity3d.com/ScriptReference/Application-platform.html |
|
|
|
|
var platformProperty = unityApplicationClass.GetTypeInfo().GetProperty("platform"); |
|
|
|
|
var unityRuntimePlatform = platformProperty?.GetValue(null)?.ToString(); |
|
|
|
|
isUnityIOS = (unityRuntimePlatform == "IPhonePlayer"); |
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
{ |
|
|
|
|
isUnity = false; |
|
|
|
|
isUnityIOS = false; |
|
|
|
|
} |
|
|
|
|
unityApplicationPlatform = TryGetUnityApplicationPlatform(); |
|
|
|
|
|
|
|
|
|
// Xamarin |
|
|
|
|
isXamarinIOS = Type.GetType(XamarinIOSObjectClassName) != null; |
|
|
|
@ -92,79 +82,46 @@ namespace Grpc.Core.Internal |
|
|
|
|
isXamarin = isXamarinIOS || isXamarinAndroid; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public static bool IsLinux |
|
|
|
|
{ |
|
|
|
|
get { return isLinux; } |
|
|
|
|
} |
|
|
|
|
public static bool IsLinux => isLinux; |
|
|
|
|
|
|
|
|
|
public static bool IsMacOSX |
|
|
|
|
{ |
|
|
|
|
get { return isMacOSX; } |
|
|
|
|
} |
|
|
|
|
public static bool IsMacOSX => isMacOSX; |
|
|
|
|
|
|
|
|
|
public static bool IsWindows |
|
|
|
|
{ |
|
|
|
|
get { return isWindows; } |
|
|
|
|
} |
|
|
|
|
public static bool IsWindows => isWindows; |
|
|
|
|
|
|
|
|
|
public static bool IsMono |
|
|
|
|
{ |
|
|
|
|
get { return isMono; } |
|
|
|
|
} |
|
|
|
|
public static bool IsMono => isMono; |
|
|
|
|
|
|
|
|
|
/// <summary> |
|
|
|
|
/// true if running on Unity platform. |
|
|
|
|
/// </summary> |
|
|
|
|
public static bool IsUnity |
|
|
|
|
{ |
|
|
|
|
get { return isUnity; } |
|
|
|
|
} |
|
|
|
|
public static bool IsUnity => unityApplicationPlatform != null; |
|
|
|
|
|
|
|
|
|
/// <summary> |
|
|
|
|
/// true if running on Unity iOS, false otherwise. |
|
|
|
|
/// </summary> |
|
|
|
|
public static bool IsUnityIOS |
|
|
|
|
{ |
|
|
|
|
get { return isUnityIOS; } |
|
|
|
|
} |
|
|
|
|
public static bool IsUnityIOS => unityApplicationPlatform == UnityIPhonePlayer; |
|
|
|
|
|
|
|
|
|
/// <summary> |
|
|
|
|
/// true if running on a Xamarin platform (either Xamarin.Android or Xamarin.iOS), |
|
|
|
|
/// false otherwise. |
|
|
|
|
/// </summary> |
|
|
|
|
public static bool IsXamarin |
|
|
|
|
{ |
|
|
|
|
get { return isXamarin; } |
|
|
|
|
} |
|
|
|
|
public static bool IsXamarin => isXamarin; |
|
|
|
|
|
|
|
|
|
/// <summary> |
|
|
|
|
/// true if running on Xamarin.iOS, false otherwise. |
|
|
|
|
/// </summary> |
|
|
|
|
public static bool IsXamarinIOS |
|
|
|
|
{ |
|
|
|
|
get { return isXamarinIOS; } |
|
|
|
|
} |
|
|
|
|
public static bool IsXamarinIOS => isXamarinIOS; |
|
|
|
|
|
|
|
|
|
/// <summary> |
|
|
|
|
/// true if running on Xamarin.Android, false otherwise. |
|
|
|
|
/// </summary> |
|
|
|
|
public static bool IsXamarinAndroid |
|
|
|
|
{ |
|
|
|
|
get { return isXamarinAndroid; } |
|
|
|
|
} |
|
|
|
|
public static bool IsXamarinAndroid => isXamarinAndroid; |
|
|
|
|
|
|
|
|
|
/// <summary> |
|
|
|
|
/// true if running on .NET Core (CoreCLR), false otherwise. |
|
|
|
|
/// </summary> |
|
|
|
|
public static bool IsNetCore |
|
|
|
|
{ |
|
|
|
|
get { return isNetCore; } |
|
|
|
|
} |
|
|
|
|
public static bool IsNetCore => isNetCore; |
|
|
|
|
|
|
|
|
|
public static bool Is64Bit |
|
|
|
|
{ |
|
|
|
|
get { return IntPtr.Size == 8; } |
|
|
|
|
} |
|
|
|
|
public static bool Is64Bit => IntPtr.Size == 8; |
|
|
|
|
|
|
|
|
|
/// <summary> |
|
|
|
|
/// Returns <c>UnityEngine.Application.platform</c> as a string. |
|
|
|
@ -172,14 +129,49 @@ namespace Grpc.Core.Internal |
|
|
|
|
/// Value is obtained via reflection to avoid compile-time dependency on Unity. |
|
|
|
|
/// This method should only be called if <c>IsUnity</c> is <c>true</c>. |
|
|
|
|
/// </summary> |
|
|
|
|
public static string GetUnityRuntimePlatform() |
|
|
|
|
public static string GetUnityApplicationPlatform() |
|
|
|
|
{ |
|
|
|
|
GrpcPreconditions.CheckState(IsUnity, "Not running on Unity."); |
|
|
|
|
#if NETSTANDARD |
|
|
|
|
return Type.GetType(UnityEngineApplicationClassName).GetTypeInfo().GetProperty("platform").GetValue(null).ToString(); |
|
|
|
|
#else |
|
|
|
|
return Type.GetType(UnityEngineApplicationClassName).GetProperty("platform").GetValue(null).ToString(); |
|
|
|
|
return unityApplicationPlatform; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/// <summary> |
|
|
|
|
/// Returns <c>UnityEngine.Application.platform</c> as a string or <c>null</c> |
|
|
|
|
/// if not running on Unity. |
|
|
|
|
/// Value is obtained via reflection to avoid compile-time dependency on Unity. |
|
|
|
|
/// </summary> |
|
|
|
|
static string TryGetUnityApplicationPlatform() |
|
|
|
|
{ |
|
|
|
|
Assembly unityAssembly = null; |
|
|
|
|
#if !NETSTANDARD1_5 |
|
|
|
|
// On netstandard1.5, AppDomain is not available and we just short-circuit the logic there. |
|
|
|
|
// This is fine because only the net45 or netstandard2.0 version Grpc.Core assembly is going to used in Unity. |
|
|
|
|
// NOTE: Instead of trying to load the UnityEngine.Application class via <c>Type.GetType()</c> |
|
|
|
|
// we are using a more sneaky approach to avoid inadvertently loading the UnityEngine |
|
|
|
|
// assembly (that might be available even when we are not actually on Unity, resulting |
|
|
|
|
// in false positive). See https://github.com/grpc/grpc/issues/18801 |
|
|
|
|
unityAssembly = AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault(assembly => assembly.GetName().Name == UnityEngineAssemblyName); |
|
|
|
|
#endif |
|
|
|
|
var applicationClass = unityAssembly?.GetType(UnityEngineApplicationClassName); |
|
|
|
|
var platformProperty = applicationClass?.GetTypeInfo().GetProperty("platform", BindingFlags.Static | BindingFlags.Public); |
|
|
|
|
try |
|
|
|
|
{ |
|
|
|
|
// Consult value of Application.platform via reflection |
|
|
|
|
// https://docs.unity3d.com/ScriptReference/Application-platform.html |
|
|
|
|
return platformProperty?.GetValue(null)?.ToString(); |
|
|
|
|
} |
|
|
|
|
catch (TargetInvocationException) |
|
|
|
|
{ |
|
|
|
|
// The getter for Application.platform is defined as "extern", so if UnityEngine assembly is loaded outside of a Unity application, |
|
|
|
|
// the definition for the getter will be missing - note that this is a sneaky trick that helps us tell a real Unity application from a non-unity |
|
|
|
|
// application which just happens to have loaded the UnityEngine.dll assembly. |
|
|
|
|
// https://github.com/Unity-Technologies/UnityCsReference/blob/61f92bd79ae862c4465d35270f9d1d57befd1761/Runtime/Export/Application/Application.bindings.cs#L375 |
|
|
|
|
// See https://github.com/grpc/grpc/issues/23334 |
|
|
|
|
|
|
|
|
|
// If TargetInvocationException was thrown, it most likely means that the method definition for the extern method is missing, |
|
|
|
|
// and we are going to interpret this as "not running on Unity". |
|
|
|
|
return null; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
[DllImport("libc")] |
|
|
|
|