-
-
Notifications
You must be signed in to change notification settings - Fork 50
/
SentryMonoBehaviour.cs
212 lines (194 loc) · 8.58 KB
/
SentryMonoBehaviour.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
using System;
using System.Collections;
using Sentry.Unity.Integrations;
using UnityEngine;
namespace Sentry.Unity
{
/// <summary>
/// Singleton and DontDestroyOnLoad setup.
/// </summary>
[AddComponentMenu("")] // Hides it from being added as a component in the inspector
internal partial class SentryMonoBehaviour : MonoBehaviour
{
private static SentryMonoBehaviour? _instance;
public static SentryMonoBehaviour Instance
{
get
{
// Unity overrides `==` operator in MonoBehaviours
if (_instance == null)
{
// HideAndDontSave excludes the gameObject from the scene meaning it does not get destroyed on loading/unloading
var sentryGameObject = new GameObject("SentryMonoBehaviour") { hideFlags = HideFlags.HideAndDontSave };
_instance = sentryGameObject.AddComponent<SentryMonoBehaviour>();
}
return _instance;
}
}
}
/// <summary>
/// A MonoBehavior used to forward application focus events to subscribers.
/// </summary>
internal partial class SentryMonoBehaviour
{
/// <summary>
/// Hook to receive an event when the application gains focus.
/// <remarks>
/// Listens to OnApplicationFocus for all platforms except Android, where we listen to OnApplicationPause.
/// </remarks>
/// </summary>
public event Action? ApplicationResuming;
/// <summary>
/// Hook to receive an event when the application loses focus.
/// <remarks>
/// Listens to OnApplicationFocus for all platforms except Android, where we listen to OnApplicationPause.
/// </remarks>
/// </summary>
public event Action? ApplicationPausing;
/// <summary>
/// Hook to receive an event when the application is quitting.
/// <remarks>
/// This is not guaranteed to be called on all platforms. See Unity docs for more details:
/// https://docs.unity3d.com/ScriptReference/MonoBehaviour.OnApplicationQuit.html
/// </remarks>
/// </summary>
public event Action? ApplicationQuitting;
// Keeping internal track of running state because OnApplicationPause and OnApplicationFocus get called during startup and would fire false resume events
private bool _isRunning = true;
private IApplication? _application;
internal IApplication Application
{
get
{
_application ??= ApplicationAdapter.Instance;
return _application;
}
set => _application = value;
}
/// <summary>
/// To receive Leaving/Resuming events on Android.
/// <remarks>
/// On Android, when the on-screen keyboard is enabled, it causes a OnApplicationFocus(false) event.
/// Additionally, if you press "Home" at the moment the keyboard is enabled, the OnApplicationFocus() event is
/// not called, but OnApplicationPause() is called instead.
/// </remarks>
/// <seealso href="https://docs.unity3d.com/2019.4/Documentation/ScriptReference/MonoBehaviour.OnApplicationPause.html"/>
/// </summary>
internal void OnApplicationPause(bool pauseStatus)
{
if (Application.Platform != RuntimePlatform.Android)
{
return;
}
if (pauseStatus && _isRunning)
{
_isRunning = false;
ApplicationPausing?.Invoke();
}
else if (!pauseStatus && !_isRunning)
{
_isRunning = true;
ApplicationResuming?.Invoke();
}
}
/// <summary>
/// To receive Leaving/Resuming events on all platforms except Android.
/// </summary>
/// <param name="hasFocus"></param>
internal void OnApplicationFocus(bool hasFocus)
{
// To avoid event duplication on Android since the pause event will be handled via OnApplicationPause
if (Application.Platform == RuntimePlatform.Android)
{
return;
}
if (hasFocus && !_isRunning)
{
_isRunning = true;
ApplicationResuming?.Invoke();
}
else if (!hasFocus && _isRunning)
{
_isRunning = false;
ApplicationPausing?.Invoke();
}
}
private void OnApplicationQuit()
{
try
{
ApplicationQuitting?.Invoke();
}
catch (Exception e)
{
Debug.LogWarningFormat("ApplicationQuitting.Invoke() threw an exception %s", e.ToString());
}
// The GameObject has to destroy itself since it was created with HideFlags.HideAndDontSave
Destroy(gameObject);
}
}
/// <summary>
/// Sentry-Unity SDK internal class for other Sentry.Unity.* assemblies.
/// You should not use this directly in your application.
/// </summary>
public class SentryMonoBehaviourInternal
{
/// This is `protected internal` to be semi-hidden from users.
protected internal static void AttachOnApplicationQuitting(Action action) =>
SentryMonoBehaviour.Instance.ApplicationQuitting += action;
}
/// <summary>
/// Main thread data collector.
/// </summary>
internal partial class SentryMonoBehaviour
{
internal readonly MainThreadData MainThreadData = new();
private ISentrySystemInfo? _sentrySystemInfo;
internal ISentrySystemInfo SentrySystemInfo
{
get
{
_sentrySystemInfo ??= SentrySystemInfoAdapter.Instance;
return _sentrySystemInfo;
}
set => _sentrySystemInfo = value;
}
private void Start()
=> StartCoroutine(CollectData());
internal IEnumerator CollectData()
{
MainThreadData.MainThreadId = SentrySystemInfo.MainThreadId;
yield return null;
MainThreadData.ProcessorCount = SentrySystemInfo.ProcessorCount;
MainThreadData.DeviceType = SentrySystemInfo.DeviceType;
MainThreadData.OperatingSystem = SentrySystemInfo.OperatingSystem;
MainThreadData.CpuDescription = SentrySystemInfo.CpuDescription;
MainThreadData.SupportsVibration = SentrySystemInfo.SupportsVibration;
MainThreadData.DeviceName = SentrySystemInfo.DeviceName;
MainThreadData.DeviceUniqueIdentifier = SentrySystemInfo.DeviceUniqueIdentifier;
MainThreadData.DeviceModel = SentrySystemInfo.DeviceModel;
MainThreadData.SystemMemorySize = SentrySystemInfo.SystemMemorySize;
yield return null;
MainThreadData.GraphicsDeviceId = SentrySystemInfo.GraphicsDeviceId;
MainThreadData.GraphicsDeviceName = SentrySystemInfo.GraphicsDeviceName;
MainThreadData.GraphicsDeviceVendorId = SentrySystemInfo.GraphicsDeviceVendorId;
MainThreadData.GraphicsDeviceVendor = SentrySystemInfo.GraphicsDeviceVendor;
MainThreadData.GraphicsMemorySize = SentrySystemInfo.GraphicsMemorySize;
MainThreadData.GraphicsMultiThreaded = SentrySystemInfo.GraphicsMultiThreaded;
MainThreadData.NpotSupport = SentrySystemInfo.NpotSupport;
MainThreadData.GraphicsDeviceVersion = SentrySystemInfo.GraphicsDeviceVersion;
MainThreadData.GraphicsDeviceType = SentrySystemInfo.GraphicsDeviceType;
MainThreadData.MaxTextureSize = SentrySystemInfo.MaxTextureSize;
MainThreadData.SupportsDrawCallInstancing = SentrySystemInfo.SupportsDrawCallInstancing;
MainThreadData.SupportsRayTracing = SentrySystemInfo.SupportsRayTracing;
MainThreadData.SupportsComputeShaders = SentrySystemInfo.SupportsComputeShaders;
MainThreadData.SupportsGeometryShaders = SentrySystemInfo.SupportsGeometryShaders;
MainThreadData.GraphicsShaderLevel = SentrySystemInfo.GraphicsShaderLevel;
MainThreadData.IsDebugBuild = SentrySystemInfo.IsDebugBuild;
MainThreadData.InstallMode = SentrySystemInfo.InstallMode;
MainThreadData.TargetFrameRate = SentrySystemInfo.TargetFrameRate;
MainThreadData.CopyTextureSupport = SentrySystemInfo.CopyTextureSupport;
MainThreadData.RenderingThreadingMode = SentrySystemInfo.RenderingThreadingMode;
}
}
}