1 #region Copyright notice and license 2 3 // Copyright 2015 gRPC authors. 4 // 5 // Licensed under the Apache License, Version 2.0 (the "License"); 6 // you may not use this file except in compliance with the License. 7 // You may obtain a copy of the License at 8 // 9 // http://www.apache.org/licenses/LICENSE-2.0 10 // 11 // Unless required by applicable law or agreed to in writing, software 12 // distributed under the License is distributed on an "AS IS" BASIS, 13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 // See the License for the specific language governing permissions and 15 // limitations under the License. 16 17 #endregion 18 19 using System; 20 using System.Collections.Concurrent; 21 using System.Diagnostics; 22 using System.IO; 23 using System.Reflection; 24 using System.Runtime.InteropServices; 25 using System.Threading; 26 using Grpc.Core.Utils; 27 28 namespace Grpc.Core.Internal 29 { 30 /// <summary> 31 /// Utility methods for detecting platform and architecture. 32 /// </summary> 33 internal static class PlatformApis 34 { 35 const string UnityEngineApplicationClassName = "UnityEngine.Application, UnityEngine"; 36 const string XamarinAndroidObjectClassName = "Java.Lang.Object, Mono.Android"; 37 const string XamarinIOSObjectClassName = "Foundation.NSObject, Xamarin.iOS"; 38 39 static readonly bool isLinux; 40 static readonly bool isMacOSX; 41 static readonly bool isWindows; 42 static readonly bool isMono; 43 static readonly bool isNetCore; 44 static readonly bool isUnity; 45 static readonly bool isUnityIOS; 46 static readonly bool isXamarin; 47 static readonly bool isXamarinIOS; 48 static readonly bool isXamarinAndroid; 49 PlatformApis()50 static PlatformApis() 51 { 52 #if NETSTANDARD1_5 53 isLinux = RuntimeInformation.IsOSPlatform(OSPlatform.Linux); 54 isMacOSX = RuntimeInformation.IsOSPlatform(OSPlatform.OSX); 55 isWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows); 56 isNetCore = RuntimeInformation.FrameworkDescription.StartsWith(".NET Core"); 57 #else 58 var platform = Environment.OSVersion.Platform; 59 60 // PlatformID.MacOSX is never returned, commonly used trick is to identify Mac is by using uname. 61 isMacOSX = (platform == PlatformID.Unix && GetUname() == "Darwin"); 62 isLinux = (platform == PlatformID.Unix && !isMacOSX); 63 isWindows = (platform == PlatformID.Win32NT || platform == PlatformID.Win32S || platform == PlatformID.Win32Windows); 64 isNetCore = false; 65 #endif 66 isMono = Type.GetType("Mono.Runtime") != null; 67 68 // Unity 69 var unityApplicationClass = Type.GetType(UnityEngineApplicationClassName); 70 if (unityApplicationClass != null) 71 { 72 isUnity = true; 73 // Consult value of Application.platform via reflection 74 // https://docs.unity3d.com/ScriptReference/Application-platform.html 75 var platformProperty = unityApplicationClass.GetTypeInfo().GetProperty("platform"); 76 var unityRuntimePlatform = platformProperty?.GetValue(null)?.ToString(); 77 isUnityIOS = (unityRuntimePlatform == "IPhonePlayer"); 78 } 79 else 80 { 81 isUnity = false; 82 isUnityIOS = false; 83 } 84 85 // Xamarin 86 isXamarinIOS = Type.GetType(XamarinIOSObjectClassName) != null; 87 isXamarinAndroid = Type.GetType(XamarinAndroidObjectClassName) != null; 88 isXamarin = isXamarinIOS || isXamarinAndroid; 89 } 90 91 public static bool IsLinux 92 { 93 get { return isLinux; } 94 } 95 96 public static bool IsMacOSX 97 { 98 get { return isMacOSX; } 99 } 100 101 public static bool IsWindows 102 { 103 get { return isWindows; } 104 } 105 106 public static bool IsMono 107 { 108 get { return isMono; } 109 } 110 111 /// <summary> 112 /// true if running on Unity platform. 113 /// </summary> 114 public static bool IsUnity 115 { 116 get { return isUnity; } 117 } 118 119 /// <summary> 120 /// true if running on Unity iOS, false otherwise. 121 /// </summary> 122 public static bool IsUnityIOS 123 { 124 get { return isUnityIOS; } 125 } 126 127 /// <summary> 128 /// true if running on a Xamarin platform (either Xamarin.Android or Xamarin.iOS), 129 /// false otherwise. 130 /// </summary> 131 public static bool IsXamarin 132 { 133 get { return isXamarin; } 134 } 135 136 /// <summary> 137 /// true if running on Xamarin.iOS, false otherwise. 138 /// </summary> 139 public static bool IsXamarinIOS 140 { 141 get { return isXamarinIOS; } 142 } 143 144 /// <summary> 145 /// true if running on Xamarin.Android, false otherwise. 146 /// </summary> 147 public static bool IsXamarinAndroid 148 { 149 get { return isXamarinAndroid; } 150 } 151 152 /// <summary> 153 /// true if running on .NET Core (CoreCLR), false otherwise. 154 /// </summary> 155 public static bool IsNetCore 156 { 157 get { return isNetCore; } 158 } 159 160 public static bool Is64Bit 161 { 162 get { return IntPtr.Size == 8; } 163 } 164 165 /// <summary> 166 /// Returns <c>UnityEngine.Application.platform</c> as a string. 167 /// See https://docs.unity3d.com/ScriptReference/Application-platform.html for possible values. 168 /// Value is obtained via reflection to avoid compile-time dependency on Unity. 169 /// This method should only be called if <c>IsUnity</c> is <c>true</c>. 170 /// </summary> GetUnityRuntimePlatform()171 public static string GetUnityRuntimePlatform() 172 { 173 GrpcPreconditions.CheckState(IsUnity, "Not running on Unity."); 174 #if NETSTANDARD1_5 175 return Type.GetType(UnityEngineApplicationClassName).GetTypeInfo().GetProperty("platform").GetValue(null).ToString(); 176 #else 177 return Type.GetType(UnityEngineApplicationClassName).GetProperty("platform").GetValue(null).ToString(); 178 #endif 179 } 180 181 [DllImport("libc")] uname(IntPtr buf)182 static extern int uname(IntPtr buf); 183 GetUname()184 static string GetUname() 185 { 186 var buffer = Marshal.AllocHGlobal(8192); 187 try 188 { 189 if (uname(buffer) == 0) 190 { 191 return Marshal.PtrToStringAnsi(buffer); 192 } 193 return string.Empty; 194 } 195 catch 196 { 197 return string.Empty; 198 } 199 finally 200 { 201 if (buffer != IntPtr.Zero) 202 { 203 Marshal.FreeHGlobal(buffer); 204 } 205 } 206 } 207 } 208 } 209