diff --git a/plugin-dev/Source/Sentry/Private/Android/AndroidSentrySubsystem.cpp b/plugin-dev/Source/Sentry/Private/Android/AndroidSentrySubsystem.cpp index b435a68b4..04cf99ece 100644 --- a/plugin-dev/Source/Sentry/Private/Android/AndroidSentrySubsystem.cpp +++ b/plugin-dev/Source/Sentry/Private/Android/AndroidSentrySubsystem.cpp @@ -28,6 +28,7 @@ #include "Dom/JsonObject.h" #include "HAL/FileManager.h" +#include "HAL/PlatformTLS.h" #include "Misc/CoreDelegates.h" #include "Misc/FileHelper.h" #include "Misc/OutputDeviceError.h" @@ -73,6 +74,10 @@ void FAndroidSentrySubsystem::InitWithSettings(const USentrySettings* settings, SettingsJson->SetBoolField(TEXT("sendDefaultPii"), settings->SendDefaultPii); SettingsJson->SetBoolField(TEXT("enableAnrTracking"), settings->EnableAppNotRespondingTracking); SettingsJson->SetNumberField(TEXT("anrTimeoutMillis"), settings->AppNotRespondingTimeout * 1000.0f); + if (settings->EnableAppNotRespondingTracking) + { + SettingsJson->SetNumberField(TEXT("anrThreadId"), static_cast(FPlatformTLS::GetCurrentThreadId())); + } SettingsJson->SetBoolField(TEXT("enableNdk"), settings->AndroidCrashBackend != ESentryAndroidCrashBackend::TombstoneOnly); SettingsJson->SetBoolField(TEXT("enableTombstone"), settings->AndroidCrashBackend == ESentryAndroidCrashBackend::TombstoneOnly || settings->AndroidCrashBackend == ESentryAndroidCrashBackend::TombstoneMergedWithNdk); @@ -123,6 +128,14 @@ void FAndroidSentrySubsystem::InitWithSettings(const USentrySettings* settings, TryCaptureScreenshot(); }); } + + if (IsEnabled() && settings->EnableAppNotRespondingTracking) + { + AnrHeartbeatDelegateHandle = FCoreDelegates::OnEndFrame.AddLambda([]() + { + FSentryJavaObjectWrapper::CallStaticMethod(SentryJavaClasses::SentryBridgeJava, "notifyAnrThreadAlive", "()V"); + }); + } } void FAndroidSentrySubsystem::Close() @@ -133,6 +146,12 @@ void FAndroidSentrySubsystem::Close() OnHandleSystemErrorDelegateHandle.Reset(); } + if (AnrHeartbeatDelegateHandle.IsValid()) + { + FCoreDelegates::OnEndFrame.Remove(AnrHeartbeatDelegateHandle); + AnrHeartbeatDelegateHandle.Reset(); + } + FSentryJavaObjectWrapper::CallStaticMethod(SentryJavaClasses::Sentry, "flush", "(J)V", (jlong)3000); FSentryJavaObjectWrapper::CallStaticMethod(SentryJavaClasses::Sentry, "close", "()V"); } diff --git a/plugin-dev/Source/Sentry/Private/Android/AndroidSentrySubsystem.h b/plugin-dev/Source/Sentry/Private/Android/AndroidSentrySubsystem.h index 1e85c51d0..d5767b774 100644 --- a/plugin-dev/Source/Sentry/Private/Android/AndroidSentrySubsystem.h +++ b/plugin-dev/Source/Sentry/Private/Android/AndroidSentrySubsystem.h @@ -64,6 +64,7 @@ class FAndroidSentrySubsystem : public ISentrySubsystem bool isScreenshotAttachmentEnabled = false; FDelegateHandle OnHandleSystemErrorDelegateHandle; + FDelegateHandle AnrHeartbeatDelegateHandle; }; typedef FAndroidSentrySubsystem FPlatformSentrySubsystem; diff --git a/plugin-dev/Source/Sentry/Private/Android/Java/SentryBridgeJava.java b/plugin-dev/Source/Sentry/Private/Android/Java/SentryBridgeJava.java index 375977a7c..0db4c808e 100644 --- a/plugin-dev/Source/Sentry/Private/Android/Java/SentryBridgeJava.java +++ b/plugin-dev/Source/Sentry/Private/Android/Java/SentryBridgeJava.java @@ -85,6 +85,9 @@ public void configure(SentryAndroidOptions options) { } options.setAnrEnabled(settingJson.getBoolean("enableAnrTracking")); options.setAnrTimeoutIntervalMillis(settingJson.getLong("anrTimeoutMillis")); + if (settingJson.has("anrThreadId")) { + options.setAnrThreadId(settingJson.getLong("anrThreadId")); + } options.setEnableNdk(settingJson.getBoolean("enableNdk")); options.setTombstoneEnabled(settingJson.getBoolean("enableTombstone")); options.getLogs().setEnabled(settingJson.getBoolean("enableStructuredLogging")); @@ -326,6 +329,10 @@ public static void clearAttachments() { Sentry.getGlobalScope().clearAttachments(); } + public static void notifyAnrThreadAlive() { + io.sentry.AnrHeartbeatRegistry.notifyAlive(); + } + public static void addLogFatal(final String message, final HashMap attributesMap) { addLog(SentryLogLevel.FATAL, message, attributesMap); }