├── .buildkite
├── block.step.yml
├── pipeline.full.yml
├── pipeline.yml
└── pipeline_trigger.sh
├── .clang-format
├── .github
├── ISSUE_TEMPLATE
│ ├── A.md
│ ├── bug_report.md
│ └── feature_request.md
├── PULL_REQUEST_TEMPLATE.md
├── SUPPORT.md
├── dependabot.yml
└── workflows
│ ├── codeql.yml
│ ├── downstream_updates.yml
│ ├── scorecard.yml
│ └── signing.yml
├── .gitignore
├── .gitmodules
├── CHANGELOG.md
├── CODEOWNERS
├── CONTRIBUTING.md
├── Gemfile
├── LICENSE
├── Makefile
├── README.md
├── SECURITY.md
├── UPGRADING.md
├── bugsnag-android-core
├── CMakeLists.txt
├── README.md
├── api
│ └── bugsnag-android-core.api
├── build.gradle.kts
├── detekt-baseline.xml
├── gradle.properties
├── lint-baseline.xml
├── proguard-rules.pro
└── src
│ ├── androidTest
│ ├── AndroidManifest.xml
│ └── java
│ │ ├── android
│ │ └── os
│ │ │ └── strictmode
│ │ │ └── FakeStrictModeViolation.kt
│ │ └── com
│ │ └── bugsnag
│ │ └── android
│ │ ├── AppDataCollectorForegroundTest.kt
│ │ ├── AppDataCollectorTest.kt
│ │ ├── BreadcrumbFilterTest.kt
│ │ ├── BreadcrumbStateTest.kt
│ │ ├── BugsnagKotlinTestUtils.kt
│ │ ├── BugsnagStoreMigratorTest.kt
│ │ ├── ClientConfigTest.java
│ │ ├── ClientContextInitTest.java
│ │ ├── ClientTest.java
│ │ ├── ClientUserTest.kt
│ │ ├── DeviceIdStoreTest.kt
│ │ ├── EventPayloadTest.java
│ │ ├── EventStoreConfinementTest.kt
│ │ ├── FileStoreTest.kt
│ │ ├── LastRunInfoStoreTest.kt
│ │ ├── ManifestConfigLoaderTest.kt
│ │ ├── MemoryTrimTest.java
│ │ ├── NativeInterfaceTest.java
│ │ ├── ObserverInterfaceTest.java
│ │ ├── OnBreadcrumbCallbackStateTest.java
│ │ ├── ProjectPackagesTest.kt
│ │ ├── SessionLegacyPayloadTest.java
│ │ ├── SessionPayloadTest.kt
│ │ ├── SessionTrackerConfinementTest.kt
│ │ ├── StrictModeTest.java
│ │ ├── StrictModeViolationTest.kt
│ │ ├── StrictModeWrapper.java
│ │ ├── SynchronizedStreamableStoreTest.kt
│ │ ├── ThreadStateTest.kt
│ │ ├── UniqueOnErrorCallbackTest.java
│ │ └── UserStoreTest.kt
│ ├── main
│ ├── AndroidManifest.xml
│ ├── CMakeLists.txt
│ ├── java
│ │ └── com
│ │ │ └── bugsnag
│ │ │ └── android
│ │ │ ├── ActivityBreadcrumbCollector.kt
│ │ │ ├── App.kt
│ │ │ ├── AppDataCollector.kt
│ │ │ ├── AppWithState.kt
│ │ │ ├── BaseObservable.kt
│ │ │ ├── Breadcrumb.java
│ │ │ ├── BreadcrumbInternal.kt
│ │ │ ├── BreadcrumbState.kt
│ │ │ ├── BreadcrumbType.kt
│ │ │ ├── Bugsnag.java
│ │ │ ├── BugsnagEventMapper.kt
│ │ │ ├── BugsnagStateModule.kt
│ │ │ ├── BugsnagThreadViolationListener.java
│ │ │ ├── BugsnagVmViolationListener.java
│ │ │ ├── CallbackAware.kt
│ │ │ ├── CallbackState.kt
│ │ │ ├── Client.java
│ │ │ ├── ClientComponentCallbacks.kt
│ │ │ ├── ClientObservable.kt
│ │ │ ├── CollectionUtils.java
│ │ │ ├── ConfigInternal.kt
│ │ │ ├── Configuration.java
│ │ │ ├── ConnectivityCompat.kt
│ │ │ ├── ContextExtensions.kt
│ │ │ ├── ContextState.kt
│ │ │ ├── DataCollectionModule.kt
│ │ │ ├── DebugLogger.kt
│ │ │ ├── DefaultDelivery.kt
│ │ │ ├── Deliverable.kt
│ │ │ ├── Delivery.kt
│ │ │ ├── DeliveryDelegate.java
│ │ │ ├── DeliveryHeaders.kt
│ │ │ ├── DeliveryParams.kt
│ │ │ ├── DeliveryStatus.kt
│ │ │ ├── Device.kt
│ │ │ ├── DeviceBuildInfo.kt
│ │ │ ├── DeviceDataCollector.kt
│ │ │ ├── DeviceIdFilePersistence.kt
│ │ │ ├── DeviceIdPersistence.kt
│ │ │ ├── DeviceIdStore.kt
│ │ │ ├── DeviceWithState.kt
│ │ │ ├── EndpointConfiguration.kt
│ │ │ ├── Error.java
│ │ │ ├── ErrorInternal.kt
│ │ │ ├── ErrorType.kt
│ │ │ ├── ErrorTypes.kt
│ │ │ ├── Event.java
│ │ │ ├── EventFilenameInfo.kt
│ │ │ ├── EventInternal.kt
│ │ │ ├── EventPayload.kt
│ │ │ ├── EventStorageModule.kt
│ │ │ ├── EventStore.kt
│ │ │ ├── ExceptionHandler.java
│ │ │ ├── FeatureFlag.java
│ │ │ ├── FeatureFlagAware.kt
│ │ │ ├── FeatureFlagState.kt
│ │ │ ├── FeatureFlags.kt
│ │ │ ├── FileStore.kt
│ │ │ ├── IOUtils.java
│ │ │ ├── InternalReportDelegate.java
│ │ │ ├── Intrinsics.java
│ │ │ ├── JsonReadable.kt
│ │ │ ├── JsonScope.java
│ │ │ ├── JsonStream.java
│ │ │ ├── JsonWriter.java
│ │ │ ├── LastRunInfo.kt
│ │ │ ├── LastRunInfoStore.kt
│ │ │ ├── LaunchCrashTracker.kt
│ │ │ ├── LibraryLoader.java
│ │ │ ├── Logger.kt
│ │ │ ├── ManifestConfigLoader.kt
│ │ │ ├── MarshalledEventSource.kt
│ │ │ ├── MemoryTrimState.kt
│ │ │ ├── Metadata.kt
│ │ │ ├── MetadataAware.kt
│ │ │ ├── MetadataState.kt
│ │ │ ├── NativeInterface.java
│ │ │ ├── NativeStackframe.kt
│ │ │ ├── NdkPluginCaller.kt
│ │ │ ├── NoopLogger.kt
│ │ │ ├── Notifier.kt
│ │ │ ├── ObjectJsonStreamer.kt
│ │ │ ├── OnBreadcrumbCallback.kt
│ │ │ ├── OnErrorCallback.kt
│ │ │ ├── OnSendCallback.kt
│ │ │ ├── OnSessionCallback.kt
│ │ │ ├── Plugin.kt
│ │ │ ├── PluginClient.kt
│ │ │ ├── RootDetector.kt
│ │ │ ├── Session.java
│ │ │ ├── SessionFilenameInfo.kt
│ │ │ ├── SessionStore.kt
│ │ │ ├── SessionTracker.java
│ │ │ ├── Severity.kt
│ │ │ ├── SeverityReason.java
│ │ │ ├── SharedPrefMigrator.kt
│ │ │ ├── Stackframe.kt
│ │ │ ├── Stacktrace.kt
│ │ │ ├── StateEvent.kt
│ │ │ ├── StorageModule.kt
│ │ │ ├── StrictModeHandler.java
│ │ │ ├── StrictModeOnErrorCallback.kt
│ │ │ ├── SynchronizedStreamableStore.kt
│ │ │ ├── SystemBroadcastReceiver.kt
│ │ │ ├── Telemetry.kt
│ │ │ ├── Thread.java
│ │ │ ├── ThreadInternal.kt
│ │ │ ├── ThreadSendPolicy.kt
│ │ │ ├── ThreadState.kt
│ │ │ ├── ThrowableExtensions.kt
│ │ │ ├── TraceCorrelation.kt
│ │ │ ├── TrackerModule.kt
│ │ │ ├── User.kt
│ │ │ ├── UserAware.kt
│ │ │ ├── UserState.kt
│ │ │ ├── UserStore.kt
│ │ │ └── internal
│ │ │ ├── AbstractStartupProvider.kt
│ │ │ ├── BackgroundTaskService.kt
│ │ │ ├── BugsnagContentProvider.kt
│ │ │ ├── BugsnagMapper.kt
│ │ │ ├── BugsnagStoreMigrator.kt
│ │ │ ├── ByteArrayExtensions.kt
│ │ │ ├── DateUtils.kt
│ │ │ ├── DexBuildIdGenerator.kt
│ │ │ ├── FallbackWriter.kt
│ │ │ ├── ForegroundDetector.kt
│ │ │ ├── ImmutableConfig.kt
│ │ │ ├── InternalMetrics.kt
│ │ │ ├── InternalMetricsImpl.kt
│ │ │ ├── InternalMetricsNoop.kt
│ │ │ ├── JsonHelper.kt
│ │ │ ├── StateObserver.kt
│ │ │ ├── StringUtils.kt
│ │ │ └── dag
│ │ │ ├── ConfigModule.kt
│ │ │ ├── ContextModule.kt
│ │ │ ├── DependencyModule.kt
│ │ │ ├── Provider.kt
│ │ │ └── SystemServiceModule.kt
│ └── jni
│ │ └── root_detection.c
│ ├── sharedTest
│ └── java
│ │ └── com
│ │ └── bugsnag
│ │ └── android
│ │ └── BugsnagTestUtils.java
│ └── test
│ ├── java
│ ├── android
│ │ └── os
│ │ │ └── strictmode
│ │ │ └── FakeStrictModeViolation.kt
│ └── com
│ │ └── bugsnag
│ │ └── android
│ │ ├── ActivityLifecycleBreadcrumbTest.kt
│ │ ├── ApiKeyConfigValidationTest.kt
│ │ ├── ApiKeyValidationTest.kt
│ │ ├── AppDataCollectorSerializationTest.kt
│ │ ├── AppMetadataSerializationTest.kt
│ │ ├── BreadcrumbFacadeTest.java
│ │ ├── BreadcrumbMutabilityTest.kt
│ │ ├── BreadcrumbNullabilityTest.java
│ │ ├── BreadcrumbSerializationTest.kt
│ │ ├── BreadcrumbStateSerializationTest.kt
│ │ ├── BreadcrumbStateTest.kt
│ │ ├── BugsnagApiTest.kt
│ │ ├── BugsnagClientMirrorInterfaceTest.kt
│ │ ├── CallbackStateTest.kt
│ │ ├── ClientComponentCallbacksMemoryCallbackTest.kt
│ │ ├── ClientFacadeTest.java
│ │ ├── ClientObservableTest.kt
│ │ ├── CollectionUtilsTest.java
│ │ ├── ConcurrentCallbackTest.java
│ │ ├── ConfigApiTest.kt
│ │ ├── ConfigChangeReceiverTest.kt
│ │ ├── ConfigurationFacadeTest.java
│ │ ├── ConfigurationTest.java
│ │ ├── ConnectivityApi24Test.kt
│ │ ├── ConnectivityCompatTest.kt
│ │ ├── ConnectivityLegacyTest.kt
│ │ ├── ContextExtensionsKtTest.kt
│ │ ├── ContextStateTest.kt
│ │ ├── DataCollectorTest.kt
│ │ ├── DeliveryDelegateTest.kt
│ │ ├── DeliveryHeadersTest.kt
│ │ ├── DeliveryStatusTest.kt
│ │ ├── DeviceDataCollectorSerializationTest.kt
│ │ ├── DeviceMetadataSerializationTest.kt
│ │ ├── DiscardTest.kt
│ │ ├── EmptyEventCallbackTest.kt
│ │ ├── EnabledErrorTypesTest.kt
│ │ ├── EndpointConfigValidationTest.kt
│ │ ├── ErrorFacadeTest.java
│ │ ├── ErrorSerializationTest.kt
│ │ ├── ErrorTest.kt
│ │ ├── EventApiTest.kt
│ │ ├── EventErrorTypeTest.kt
│ │ ├── EventFacadeTest.java
│ │ ├── EventFeatureFlagsCloneTest.kt
│ │ ├── EventFilenameTest.kt
│ │ ├── EventMetadataCloneTest.kt
│ │ ├── EventNameTest.kt
│ │ ├── EventPayloadSerializationTest.kt
│ │ ├── EventPayloadTest.kt
│ │ ├── EventPayloadTrimTest.kt
│ │ ├── EventRedactionTest.kt
│ │ ├── EventSerializationTest.kt
│ │ ├── EventStateTest.java
│ │ ├── EventStoreMaxLimitTest.kt
│ │ ├── EventTest.java
│ │ ├── ExceptionHandlerTest.kt
│ │ ├── FeatureFlagStateTest.kt
│ │ ├── FeatureFlagTest.java
│ │ ├── FeatureFlagsSerializationTest.kt
│ │ ├── FeatureFlagsTest.kt
│ │ ├── ImmutableConfigTest.kt
│ │ ├── InterceptingLogger.kt
│ │ ├── InternalEventPayloadDelegateTest.kt
│ │ ├── JsonParser.kt
│ │ ├── JsonStreamFileTest.java
│ │ ├── JsonStreamTest.kt
│ │ ├── JsonUtils.kt
│ │ ├── JsonWriterBugsnagTest.java
│ │ ├── JsonWriterTest.java
│ │ ├── LastRunInfoApiTest.java
│ │ ├── LaunchCrashDeliveryTest.kt
│ │ ├── LaunchCrashTrackerTest.kt
│ │ ├── LibraryLoaderTest.kt
│ │ ├── MemoryTrimStateTest.kt
│ │ ├── MetadataConcurrentModificationTest.kt
│ │ ├── MetadataMergeTest.kt
│ │ ├── MetadataRedactionTest.java
│ │ ├── MetadataSerializationTest.kt
│ │ ├── MetadataStateTest.kt
│ │ ├── NativeInterfaceApiTest.kt
│ │ ├── NativeStackframeSerializationTest.kt
│ │ ├── NotifierSerializationTest.kt
│ │ ├── NullMetadataTest.java
│ │ ├── OnErrorCallbackTest.kt
│ │ ├── PluginClientTest.kt
│ │ ├── RecursiveThrowableCauseTest.kt
│ │ ├── RootDetectorTest.kt
│ │ ├── SessionFacadeTest.java
│ │ ├── SessionFilenameTest.kt
│ │ ├── SessionSerializationTest.kt
│ │ ├── SessionStoreMaxLimitTest.kt
│ │ ├── SessionStoreTest.kt
│ │ ├── SessionTest.kt
│ │ ├── SessionTrackerPauseResumeTest.kt
│ │ ├── SessionTrackerTest.java
│ │ ├── SeverityReasonSerializationTest.kt
│ │ ├── SeverityReasonTest.kt
│ │ ├── SeveritySerializationTest.kt
│ │ ├── SharedPrefMigratorTest.kt
│ │ ├── StackframeSerializationTest.kt
│ │ ├── StacktraceSerializationTest.kt
│ │ ├── StacktraceTest.kt
│ │ ├── StrictModeChainedListenerTest.kt
│ │ ├── StrictModeFacadeTest.java
│ │ ├── SystemBroadcastReceiverTest.kt
│ │ ├── ThreadDeserializationTest.kt
│ │ ├── ThreadFacadeTest.java
│ │ ├── ThreadSendPolicyTest.kt
│ │ ├── ThreadSerializationTest.kt
│ │ ├── UnrollThrowableCausesTest.kt
│ │ ├── UpdateMemoryTrimLevelTest.kt
│ │ ├── UserSerializationTest.kt
│ │ ├── UserStateTest.kt
│ │ ├── UserTest.java
│ │ └── internal
│ │ ├── BackgroundRunnableProviderServiceTest.kt
│ │ ├── BugsnagMapperTest.kt
│ │ ├── DexBuildIdGeneratorTest.kt
│ │ ├── ForegroundDetectorTest.kt
│ │ ├── JsonHelperTest.kt
│ │ └── StringUtilsTest.kt
│ └── resources
│ ├── app_data_serialization_0.json
│ ├── app_data_serialization_1.json
│ ├── app_meta_data_serialization_0.json
│ ├── breadcrumb_serialization_0.json
│ ├── breadcrumb_serialization_1.json
│ ├── breadcrumb_state_serialization_0.json
│ ├── com
│ └── bugsnag
│ │ └── android
│ │ └── internal
│ │ ├── classes.dex
│ │ └── empty-app-debug.apk
│ ├── device_data_serialization_0.json
│ ├── device_data_serialization_1.json
│ ├── device_metadata_serialization_0.json
│ ├── error_serialization_0.json
│ ├── error_serialization_1.json
│ ├── error_serialization_2.json
│ ├── event_default_redaction.json
│ ├── event_redaction.json
│ ├── event_serialization_0.json
│ ├── event_serialization_1.json
│ ├── event_serialization_2.json
│ ├── event_serialization_3.json
│ ├── event_serialization_4.json
│ ├── event_serialization_5.json
│ ├── event_serialization_6.json
│ ├── event_serialization_7.json
│ ├── event_serialization_8.json
│ ├── feature_flags_serialization_0.json
│ ├── feature_flags_serialization_1.json
│ ├── feature_flags_serialization_2.json
│ ├── json_stream.json
│ ├── meta_data_serialization_0.json
│ ├── meta_data_serialization_1.json
│ ├── meta_data_serialization_2.json
│ ├── meta_data_serialization_3.json
│ ├── meta_data_serialization_4.json
│ ├── metadata_redaction_0.json
│ ├── metadata_redaction_1.json
│ ├── metadata_redaction_2.json
│ ├── metadata_redaction_3.json
│ ├── metadata_redaction_4.json
│ ├── mockito-extensions
│ └── org.mockito.plugins.MockMaker
│ ├── native_stackframe_serialization_0.json
│ ├── native_stackframe_serialization_1.json
│ ├── native_stackframe_serialization_2.json
│ ├── notifier_serialization_0.json
│ ├── notifier_serialization_1.json
│ ├── null_json_stream.json
│ ├── report_serialization_0.json
│ ├── session_serialization_0.json
│ ├── severity_reason_serialization_0.json
│ ├── severity_reason_serialization_1.json
│ ├── severity_reason_serialization_2.json
│ ├── severity_reason_serialization_3.json
│ ├── severity_reason_serialization_4.json
│ ├── severity_reason_serialization_5.json
│ ├── severity_reason_serialization_6.json
│ ├── severity_reason_serialization_7.json
│ ├── severity_reason_serialization_8.json
│ ├── severity_reason_serialization_9.json
│ ├── severity_serialization_0.json
│ ├── severity_serialization_1.json
│ ├── severity_serialization_2.json
│ ├── stackframe_serialization_0.json
│ ├── stackframe_serialization_1.json
│ ├── stackframe_serialization_2.json
│ ├── stackframe_serialization_3.json
│ ├── stackframe_serialization_4.json
│ ├── stacktrace_serialization_0.json
│ ├── stacktrace_serialization_1.json
│ ├── stacktrace_serialization_2.json
│ ├── stacktrace_serialization_3.json
│ ├── stacktrace_serialization_4.json
│ ├── stacktrace_serialization_5.json
│ ├── thread_deserialization_0.json
│ ├── thread_deserialization_1.json
│ ├── thread_deserialization_2.json
│ ├── thread_serialization_0.json
│ ├── thread_serialization_1.json
│ ├── thread_serialization_2.json
│ ├── thread_serialization_3.json
│ └── user_serialization_0.json
├── bugsnag-android
├── README.md
├── build.gradle.kts
├── gradle.properties
├── lint-baseline.xml
└── src
│ └── main
│ └── AndroidManifest.xml
├── bugsnag-benchmarks
├── benchmark-proguard-rules.pro
├── build.gradle
└── src
│ ├── androidTest
│ ├── AndroidManifest.xml
│ └── java
│ │ └── com
│ │ └── bugsnag
│ │ └── android
│ │ ├── ClientHooks.kt
│ │ ├── EventHooks.java
│ │ └── benchmark
│ │ ├── ClientDataBenchmarkTest.kt
│ │ ├── CriticalPathBenchmarkTest.kt
│ │ ├── EventBenchmarkTest.kt
│ │ ├── JsonSerializationBenchmarkTest.kt
│ │ └── SessionBenchmarkTest.kt
│ └── main
│ └── AndroidManifest.xml
├── bugsnag-plugin-android-anr
├── CMakeLists.txt
├── README.md
├── api
│ └── bugsnag-plugin-android-anr.api
├── build.gradle.kts
├── detekt-baseline.xml
├── gradle.properties
├── lint-baseline.xml
├── proguard-rules.pro
└── src
│ ├── main
│ ├── AndroidManifest.xml
│ ├── CMakeLists.txt
│ ├── java
│ │ └── com
│ │ │ └── bugsnag
│ │ │ └── android
│ │ │ ├── AnrDetailsCollector.kt
│ │ │ └── AnrPlugin.kt
│ └── jni
│ │ ├── anr_google.c
│ │ ├── anr_google.h
│ │ ├── anr_handler.c
│ │ ├── anr_handler.h
│ │ ├── bsg_unwind.h
│ │ ├── bugsnag_anr.c
│ │ ├── include
│ │ └── event.h
│ │ ├── unwind_func.h
│ │ └── utils
│ │ ├── string.c
│ │ └── string.h
│ └── test
│ └── java
│ └── com
│ └── bugsnag
│ └── android
│ └── AnrDetailsCollectorTest.kt
├── bugsnag-plugin-android-exitinfo
├── README.md
├── api
│ └── bugsnag-plugin-android-exitinfo.api
├── build.gradle.kts
├── detekt-baseline.xml
├── gradle.properties
├── lint-baseline.xml
├── proguard-rules.pro
└── src
│ ├── androidTest
│ └── java
│ │ └── com
│ │ └── bugsnag
│ │ └── android
│ │ ├── BugsnagExitInfoPluginStoreTest.kt
│ │ └── TestHooks.java
│ ├── main
│ ├── AndroidManifest.xml
│ ├── java
│ │ └── com
│ │ │ └── bugsnag
│ │ │ └── android
│ │ │ ├── ApplicationExitInfoMatcher.kt
│ │ │ ├── BugsnagExitInfoPlugin.kt
│ │ │ ├── CodeStrings.kt
│ │ │ ├── EventSynthesizer.kt
│ │ │ ├── ExitInfoCallback.kt
│ │ │ ├── ExitInfoKey.kt
│ │ │ ├── ExitInfoPluginConfiguration.kt
│ │ │ ├── ExitInfoPluginStore.kt
│ │ │ ├── InternalHooks.java
│ │ │ ├── TombstoneEventEnhancer.kt
│ │ │ ├── TombstoneParser.kt
│ │ │ ├── TraceEventEnhancer.kt
│ │ │ └── TraceParser.kt
│ └── proto
│ │ └── tombstone.proto
│ └── test
│ ├── java
│ └── com
│ │ └── bugsnag
│ │ └── android
│ │ ├── ExitInfoCallbackTest.kt
│ │ ├── TombstoneEventEnhancerTest.kt
│ │ ├── TombstoneParserTest.kt
│ │ ├── TraceEventEnhancerTest.kt
│ │ ├── TraceParserInvalidStackframesTest.kt
│ │ ├── TraceParserJavaStackframeTest.kt
│ │ ├── TraceParserNativeStackframeTest.kt
│ │ └── TraceParserTest.kt
│ └── resources
│ ├── emulator-exit-anr-trace
│ └── tombstone_01.pb
├── bugsnag-plugin-android-ndk
├── CMakeLists.txt
├── README.md
├── api
│ └── bugsnag-plugin-android-ndk.api
├── build.gradle.kts
├── detekt-baseline.xml
├── gradle.properties
├── lint-baseline.xml
├── package.json
├── proguard-rules.pro
└── src
│ ├── androidTest
│ ├── java
│ │ └── com
│ │ │ └── bugsnag
│ │ │ └── android
│ │ │ └── ndk
│ │ │ ├── NativeBreadcrumbTest.kt
│ │ │ ├── NativeEventAppMutatorsTest.kt
│ │ │ ├── NativeEventDeviceMutatorsTest.kt
│ │ │ ├── NativeEventMutatorsTest.kt
│ │ │ ├── NativeFeatureFlagsTest.kt
│ │ │ ├── NativeJsonSerializeTest.kt
│ │ │ ├── NativeStringTest.kt
│ │ │ ├── OpaqueValueTest.kt
│ │ │ ├── ReportDiscardScannerTest.kt
│ │ │ ├── ResourceUtils.kt
│ │ │ ├── StartBugsnagTest.kt
│ │ │ ├── UnwindTest.kt
│ │ │ └── VerifyUtils.kt
│ └── resources
│ │ └── event_serialization.json
│ ├── main
│ ├── AndroidManifest.xml
│ ├── CMakeLists.txt
│ ├── exported_native_symbols-Debug.txt
│ ├── exported_native_symbols-RelWithDebInfo.txt
│ ├── java
│ │ └── com
│ │ │ └── bugsnag
│ │ │ └── android
│ │ │ ├── NdkPlugin.kt
│ │ │ └── ndk
│ │ │ ├── BugsnagNDK.kt
│ │ │ ├── NativeBridge.kt
│ │ │ ├── OpaqueValue.kt
│ │ │ └── ReportDiscardScanner.kt
│ └── jni
│ │ ├── bsg_unwind.h
│ │ ├── bugsnag.c
│ │ ├── bugsnag_ndk.c
│ │ ├── bugsnag_ndk.h
│ │ ├── event.c
│ │ ├── event.h
│ │ ├── featureflags.c
│ │ ├── featureflags.h
│ │ ├── handlers
│ │ ├── cpp_handler.cpp
│ │ ├── cpp_handler.h
│ │ ├── signal_handler.c
│ │ └── signal_handler.h
│ │ ├── include
│ │ ├── bugsnag.h
│ │ └── event.h
│ │ ├── internal_metrics.c
│ │ ├── internal_metrics.h
│ │ ├── jni_cache.c
│ │ ├── jni_cache.h
│ │ ├── metadata.c
│ │ ├── metadata.h
│ │ ├── safejni.c
│ │ ├── safejni.h
│ │ └── utils
│ │ ├── build.h
│ │ ├── crash_info.c
│ │ ├── crash_info.h
│ │ ├── logger.h
│ │ ├── memory.c
│ │ ├── memory.h
│ │ ├── seqlock.c
│ │ ├── seqlock.h
│ │ ├── serializer.c
│ │ ├── serializer.h
│ │ ├── serializer
│ │ ├── BSG_KSCrashStringConversion.c
│ │ ├── BSG_KSCrashStringConversion.h
│ │ ├── BSG_KSJSONCodec.c
│ │ ├── BSG_KSJSONCodec.h
│ │ ├── buffered_writer.c
│ │ ├── buffered_writer.h
│ │ ├── event_writer.c
│ │ └── event_writer.h
│ │ ├── stack_unwinder.cpp
│ │ ├── stack_unwinder.h
│ │ ├── string.c
│ │ ├── string.h
│ │ ├── threads.c
│ │ └── threads.h
│ └── test
│ ├── CMakeLists.txt
│ └── cpp
│ ├── UnwindTest.cpp
│ ├── deps
│ └── greatest
│ │ ├── greatest.h
│ │ └── package.json
│ ├── main.c
│ ├── parson
│ ├── package.json
│ ├── parson.c
│ └── parson.h
│ ├── test_breadcrumbs.c
│ ├── test_bsg_event.c
│ ├── test_bsg_event.h
│ ├── test_featureflags.c
│ ├── test_serializer.c
│ ├── test_serializer.h
│ ├── test_utils_serialize.c
│ └── test_utils_string.c
├── bugsnag-plugin-android-okhttp
├── README.md
├── api
│ └── bugsnag-plugin-android-okhttp.api
├── build.gradle.kts
├── detekt-baseline.xml
├── gradle.properties
├── lint-baseline.xml
├── proguard-rules.pro
└── src
│ ├── main
│ ├── AndroidManifest.xml
│ └── java
│ │ └── com
│ │ └── bugsnag
│ │ └── android
│ │ ├── BreadcrumbHooks.kt
│ │ └── okhttp
│ │ ├── BugsnagOkHttpPlugin.kt
│ │ └── OkHttpDelivery.kt
│ └── test
│ └── java
│ └── com
│ └── bugsnag
│ └── android
│ ├── BugsnagOkHttpPluginTest.kt
│ ├── CachedRequestIntegrationTest.kt
│ ├── ClonedRequestTest.kt
│ ├── ComplexRequestIntegrationTest.kt
│ ├── GetRequestIntegrationTest.kt
│ ├── NetworkBreadcrumbRequest.kt
│ ├── PostRequestIntegrationTest.kt
│ └── RedirectedRequestIntegrationTest.kt
├── bugsnag-plugin-react-native
├── README.md
├── api
│ └── bugsnag-plugin-react-native.api
├── build.gradle.kts
├── detekt-baseline.xml
├── gradle.properties
├── lint-baseline.xml
├── proguard-rules.pro
└── src
│ ├── main
│ ├── AndroidManifest.xml
│ └── java
│ │ └── com
│ │ └── bugsnag
│ │ └── android
│ │ ├── AppDeserializer.java
│ │ ├── AppSerializer.kt
│ │ ├── BreadcrumbDeserializer.java
│ │ ├── BreadcrumbSerializer.kt
│ │ ├── BugsnagReactNativeBridge.kt
│ │ ├── BugsnagReactNativePlugin.kt
│ │ ├── ConfigSerializer.java
│ │ ├── DeviceDeserializer.java
│ │ ├── DeviceSerializer.kt
│ │ ├── ErrorDeserializer.java
│ │ ├── EventDeserializer.kt
│ │ ├── InternalHooks.java
│ │ ├── MapDeserializer.java
│ │ ├── MapSerializer.java
│ │ ├── MapUtils.java
│ │ ├── MessageEvent.kt
│ │ ├── MetadataDeserializer.java
│ │ ├── NativeStackDeserializer.java
│ │ ├── StackframeDeserializer.java
│ │ ├── ThreadDeserializer.java
│ │ ├── ThreadSerializer.kt
│ │ └── UserDeserializer.java
│ └── test
│ ├── java
│ └── com
│ │ └── bugsnag
│ │ └── android
│ │ ├── AppDeserializerTest.kt
│ │ ├── AppSerializerTest.java
│ │ ├── BreadcrumbDeserializerTest.kt
│ │ ├── BreadcrumbSerializerTest.java
│ │ ├── BugsnagReactNativeBridgeTest.java
│ │ ├── BugsnagReactNativePluginTest.kt
│ │ ├── ConfigSerializerTest.java
│ │ ├── DeviceDeserializerTest.kt
│ │ ├── DeviceSerializerTest.java
│ │ ├── ErrorDeserializerTest.kt
│ │ ├── EventDeserializerTest.kt
│ │ ├── LeaveBreadcrumbTest.kt
│ │ ├── MetadataDeserializerTest.java
│ │ ├── NativeStackDeserializerTest.kt
│ │ ├── StackframeDeserializerTest.kt
│ │ ├── TestData.java
│ │ ├── TestHooks.java
│ │ ├── ThreadDeserializerTest.kt
│ │ ├── ThreadSerializerTest.java
│ │ ├── UpdateMetadataTest.kt
│ │ └── UserDeserializerTest.kt
│ └── resources
│ └── mockito-extensions
│ └── org.mockito.plugins.MockMaker
├── build.gradle.kts
├── buildSrc
├── build.gradle.kts
├── settings.gradle.kts
└── src
│ └── main
│ └── kotlin
│ ├── Checkstyle.kt
│ ├── ProjectDefaults.kt
│ └── Versions.kt
├── config
├── checkstyle
│ └── checkstyle.xml
└── detekt
│ └── detekt.yml
├── docker-compose.yml
├── dockerfiles
├── Dockerfile.android-common
├── Dockerfile.android-license-audit
└── Dockerfile.android-publisher
├── docs
├── BENCHMARKS.md
├── DEVELOPMENT.md
├── ENVIRONMENT_SETUP.md
├── MAZERUNNER.md
├── NEW_MODULE_CHECKLIST.md
├── PROJECT_STRUCTURE.md
├── README.md
├── RELEASING.md
└── TESTING.md
├── examples
└── sdk-app-example
│ ├── .gitignore
│ ├── README.md
│ ├── app
│ ├── .gitignore
│ ├── CMakeLists.txt
│ ├── build.gradle.kts
│ ├── proguard-rules.pro
│ └── src
│ │ └── main
│ │ ├── AndroidManifest.xml
│ │ ├── cpp
│ │ └── entrypoint.cpp
│ │ ├── ic_launcher-web.png
│ │ ├── java
│ │ └── com
│ │ │ └── example
│ │ │ ├── bugsnag
│ │ │ └── android
│ │ │ │ ├── BaseCrashyActivity.kt
│ │ │ │ ├── ExampleActivity.kt
│ │ │ │ ├── ExampleApplication.kt
│ │ │ │ ├── MultiProcessActivity.kt
│ │ │ │ └── ProcessCompat.kt
│ │ │ └── foo
│ │ │ └── CrashyClass.java
│ │ └── res
│ │ ├── drawable
│ │ └── ic_bugsnag_svg.xml
│ │ ├── layout
│ │ └── main.xml
│ │ ├── mipmap-anydpi-v26
│ │ ├── ic_launcher.xml
│ │ └── ic_launcher_round.xml
│ │ ├── mipmap-hdpi
│ │ ├── ic_launcher.png
│ │ ├── ic_launcher_foreground.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-mdpi
│ │ ├── ic_launcher.png
│ │ ├── ic_launcher_foreground.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-xhdpi
│ │ ├── ic_launcher.png
│ │ ├── ic_launcher_foreground.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-xxhdpi
│ │ ├── ic_launcher.png
│ │ ├── ic_launcher_foreground.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-xxxhdpi
│ │ ├── ic_launcher.png
│ │ ├── ic_launcher_foreground.png
│ │ └── ic_launcher_round.png
│ │ └── values
│ │ ├── colors.xml
│ │ ├── ic_launcher_background.xml
│ │ ├── strings.xml
│ │ └── styles.xml
│ ├── build.gradle.kts
│ ├── fakekeys.jks
│ ├── gradle.properties
│ ├── gradle
│ ├── libs.versions.toml
│ └── wrapper
│ │ ├── gradle-wrapper.jar
│ │ └── gradle-wrapper.properties
│ ├── gradlew
│ ├── gradlew.bat
│ ├── lint-baseline.xml
│ └── settings.gradle.kts
├── features
├── fixtures
│ ├── fakekeys.jks
│ ├── mazerunner
│ │ ├── README.md
│ │ ├── app
│ │ │ ├── .gitignore
│ │ │ ├── build.gradle
│ │ │ ├── detekt-baseline.xml
│ │ │ ├── proguard-rules.pro
│ │ │ └── src
│ │ │ │ └── main
│ │ │ │ ├── AndroidManifest.xml
│ │ │ │ ├── java
│ │ │ │ └── com
│ │ │ │ │ └── bugsnag
│ │ │ │ │ └── android
│ │ │ │ │ ├── BugsnagInternals.java
│ │ │ │ │ └── mazerunner
│ │ │ │ │ ├── MainActivity.kt
│ │ │ │ │ ├── MazerunnerApp.kt
│ │ │ │ │ ├── NetworkStatus.kt
│ │ │ │ │ ├── SecondActivity.kt
│ │ │ │ │ ├── StartSessionBehaviour.kt
│ │ │ │ │ └── StartupANRBehaviour.kt
│ │ │ │ └── res
│ │ │ │ ├── layout
│ │ │ │ └── activity_main.xml
│ │ │ │ └── xml
│ │ │ │ └── network_security_config.xml
│ │ ├── bugsnag-dependency.gradle
│ │ ├── build.gradle
│ │ ├── config
│ │ │ ├── checkstyle
│ │ │ │ └── checkstyle.xml
│ │ │ └── detekt
│ │ │ │ └── detekt.yml
│ │ ├── cxx-scenarios-bugsnag
│ │ │ ├── .gitignore
│ │ │ ├── CMakeLists.txt
│ │ │ ├── build.gradle
│ │ │ ├── detekt-baseline.xml
│ │ │ └── src
│ │ │ │ └── main
│ │ │ │ ├── AndroidManifest.xml
│ │ │ │ ├── cpp
│ │ │ │ ├── CXXExceptionSmokeScenario.cpp
│ │ │ │ ├── CXXExternalStackElementScenario.cpp
│ │ │ │ └── cxx-scenarios-bugsnag.cpp
│ │ │ │ ├── java
│ │ │ │ └── com
│ │ │ │ │ └── bugsnag
│ │ │ │ │ └── android
│ │ │ │ │ └── mazerunner
│ │ │ │ │ └── scenarios
│ │ │ │ │ ├── CXXAutoContextScenario.java
│ │ │ │ │ ├── CXXBackgroundNotifyScenario.kt
│ │ │ │ │ ├── CXXBreadcrumbScenario.java
│ │ │ │ │ ├── CXXCaptureThreadsNotifyScenario.kt
│ │ │ │ │ ├── CXXCaptureThreadsScenario.kt
│ │ │ │ │ ├── CXXCrashLoopScenario.kt
│ │ │ │ │ ├── CXXDelayedNotifyScenario.java
│ │ │ │ │ ├── CXXExceptionOnErrorFalseScenario.kt
│ │ │ │ │ ├── CXXExceptionOnErrorTrueScenario.kt
│ │ │ │ │ ├── CXXExceptionSmokeScenario.kt
│ │ │ │ │ ├── CXXExceptionWithUsageScenario.kt
│ │ │ │ │ ├── CXXExternalStackElementScenario.java
│ │ │ │ │ ├── CXXGetJavaDataScenario.java
│ │ │ │ │ ├── CXXHandledOverrideScenario.kt
│ │ │ │ │ ├── CXXJavaBreadcrumbNativeBreadcrumbScenario.java
│ │ │ │ │ ├── CXXNativeBreadcrumbJavaCrashScenario.java
│ │ │ │ │ ├── CXXNativeBreadcrumbJavaNotifyScenario.java
│ │ │ │ │ ├── CXXNativeBreadcrumbNativeCrashScenario.java
│ │ │ │ │ ├── CXXNativeUserInfoJavaCrashScenario.java
│ │ │ │ │ ├── CXXNaughtyStringsScenario.kt
│ │ │ │ │ ├── CXXNotifySmokeScenario.java
│ │ │ │ │ ├── CXXRefreshSymbolTableDuringCrashScenario.kt
│ │ │ │ │ ├── CXXRemoveDataScenario.java
│ │ │ │ │ ├── CXXRemoveOnErrorScenario.kt
│ │ │ │ │ ├── CXXSignalOnErrorFalseScenario.kt
│ │ │ │ │ ├── CXXSignalSmokeScenario.java
│ │ │ │ │ ├── CXXSigsegvWithUsageScenario.kt
│ │ │ │ │ ├── CXXStartScenario.java
│ │ │ │ │ ├── EventTooBigScenario.kt
│ │ │ │ │ ├── ExitInfoScenario.kt
│ │ │ │ │ ├── HandledExceptionWithUsageScenario.kt
│ │ │ │ │ ├── MetadataStringsTooLargeScenario.kt
│ │ │ │ │ ├── MultiProcessHandledCXXErrorScenario.kt
│ │ │ │ │ ├── MultiProcessUnhandledCXXErrorScenario.kt
│ │ │ │ │ └── UnhandledExceptionWithUsageScenario.kt
│ │ │ │ └── jniLibs
│ │ │ │ ├── arm64-v8a
│ │ │ │ └── libmonochrome.so
│ │ │ │ ├── armeabi-v7a
│ │ │ │ └── libmonochrome.so
│ │ │ │ ├── x86
│ │ │ │ └── libmonochrome.so
│ │ │ │ └── x86_64
│ │ │ │ └── libmonochrome.so
│ │ ├── cxx-scenarios
│ │ │ ├── .gitignore
│ │ │ ├── CMakeLists.txt
│ │ │ ├── build.gradle
│ │ │ ├── detekt-baseline.xml
│ │ │ └── src
│ │ │ │ └── main
│ │ │ │ ├── AndroidManifest.xml
│ │ │ │ ├── cpp
│ │ │ │ ├── CXXAbortScenario.cpp
│ │ │ │ ├── CXXCallNullFunctionPointerScenario.cpp
│ │ │ │ ├── CXXDereferenceNullScenario.cpp
│ │ │ │ ├── CXXImproperTypecastScenario.cpp
│ │ │ │ ├── CXXInvalidRethrow.cpp
│ │ │ │ ├── CXXStackoverflowScenario.cpp
│ │ │ │ ├── CXXThrowFromNoexcept.cpp
│ │ │ │ ├── CXXTrapScenario.cpp
│ │ │ │ ├── CXXWriteReadOnlyMemoryScenario.cpp
│ │ │ │ ├── bugsnag-java-scenarios.cpp
│ │ │ │ └── cxx-scenarios.cpp
│ │ │ │ └── java
│ │ │ │ └── com
│ │ │ │ └── bugsnag
│ │ │ │ └── android
│ │ │ │ └── mazerunner
│ │ │ │ └── scenarios
│ │ │ │ ├── AutoDetectNdkDisabledScenario.java
│ │ │ │ ├── CXXAbortScenario.java
│ │ │ │ ├── CXXAnrNdkDisabledScenario.kt
│ │ │ │ ├── CXXAnrScenario.java
│ │ │ │ ├── CXXCallNullFunctionPointerScenario.kt
│ │ │ │ ├── CXXConfigurationMetadataNativeCrashScenario.java
│ │ │ │ ├── CXXDelayedCrashScenario.kt
│ │ │ │ ├── CXXDelayedErrorScenario.kt
│ │ │ │ ├── CXXDereferenceNullScenario.java
│ │ │ │ ├── CXXExceptionScenario.java
│ │ │ │ ├── CXXExtraordinaryLongStringScenario.java
│ │ │ │ ├── CXXFeatureFlagNativeCrashScenario.java
│ │ │ │ ├── CXXIgnoredSigabrtScenario.kt
│ │ │ │ ├── CXXImproperTypecastScenario.java
│ │ │ │ ├── CXXInvalidRethrow.kt
│ │ │ │ ├── CXXJavaBreadcrumbNativeCrashScenario.java
│ │ │ │ ├── CXXJavaUserInfoNativeCrashScenario.java
│ │ │ │ ├── CXXMarkLaunchCompletedScenario.kt
│ │ │ │ ├── CXXMaxBreadcrumbCrashScenario.kt
│ │ │ │ ├── CXXPausedSessionScenario.kt
│ │ │ │ ├── CXXSessionInfoCrashScenario.kt
│ │ │ │ ├── CXXSigabrtScenario.java
│ │ │ │ ├── CXXSigbusScenario.java
│ │ │ │ ├── CXXSigfpeScenario.java
│ │ │ │ ├── CXXSigillScenario.java
│ │ │ │ ├── CXXSigsegvScenario.java
│ │ │ │ ├── CXXSigtrapScenario.java
│ │ │ │ ├── CXXStackoverflowScenario.java
│ │ │ │ ├── CXXStartSessionScenario.kt
│ │ │ │ ├── CXXThrowFromNoexcept.kt
│ │ │ │ ├── CXXThrowSomethingOutsideReleaseStagesScenario.kt
│ │ │ │ ├── CXXThrowSomethingScenario.java
│ │ │ │ ├── CXXTrapOutsideReleaseStagesScenario.kt
│ │ │ │ ├── CXXTrapScenario.java
│ │ │ │ ├── CXXUpdateContextCrashScenario.java
│ │ │ │ ├── CXXWriteReadOnlyMemoryScenario.java
│ │ │ │ ├── UnhandledNdkAutoNotifyFalseScenario.kt
│ │ │ │ └── UnhandledNdkAutoNotifyTrueScenario.kt
│ │ ├── gradle.properties
│ │ ├── gradle
│ │ │ ├── checkstyle.gradle
│ │ │ └── wrapper
│ │ │ │ ├── gradle-wrapper.jar
│ │ │ │ └── gradle-wrapper.properties
│ │ ├── gradlew
│ │ ├── gradlew.bat
│ │ ├── jvm-scenarios
│ │ │ ├── .gitignore
│ │ │ ├── build.gradle
│ │ │ ├── consumer-rules.pro
│ │ │ ├── detekt-baseline.xml
│ │ │ └── src
│ │ │ │ └── main
│ │ │ │ ├── AndroidManifest.xml
│ │ │ │ ├── java
│ │ │ │ └── com
│ │ │ │ │ └── bugsnag
│ │ │ │ │ └── android
│ │ │ │ │ ├── JavaHooks.java
│ │ │ │ │ ├── TestHarnessHooks.kt
│ │ │ │ │ ├── mazerunner
│ │ │ │ │ ├── AnrHelper.kt
│ │ │ │ │ ├── BugsnagConfig.kt
│ │ │ │ │ ├── BugsnagIntentParams.kt
│ │ │ │ │ ├── CustomSerializedException.java
│ │ │ │ │ ├── InterceptingDelivery.kt
│ │ │ │ │ ├── Log.kt
│ │ │ │ │ ├── MazerunnerHttpClient.kt
│ │ │ │ │ ├── NaughtyStrings.kt
│ │ │ │ │ ├── SomeException.kt
│ │ │ │ │ └── scenarios
│ │ │ │ │ │ ├── ArrayEnabledReleaseStageScenario.kt
│ │ │ │ │ │ ├── AsyncErrorConnectivityScenario.kt
│ │ │ │ │ │ ├── AsyncErrorDoubleFlushScenario.kt
│ │ │ │ │ │ ├── AsyncErrorLaunchScenario.kt
│ │ │ │ │ │ ├── AutoDetectAnrsFalseScenario.kt
│ │ │ │ │ │ ├── AutoDetectAnrsTrueScenario.kt
│ │ │ │ │ │ ├── AutoRedactKeysScenario.kt
│ │ │ │ │ │ ├── AutoSessionSmokeScenario.kt
│ │ │ │ │ │ ├── BreadcrumbAutoScenario.kt
│ │ │ │ │ │ ├── BreadcrumbDisabledScenario.kt
│ │ │ │ │ │ ├── BreadcrumbScenario.kt
│ │ │ │ │ │ ├── BugsnagInitScenario.kt
│ │ │ │ │ │ ├── ConfigureStartupAnrScenario.kt
│ │ │ │ │ │ ├── CrashHandlerScenario.kt
│ │ │ │ │ │ ├── CustomHttpClientFlushScenario.kt
│ │ │ │ │ │ ├── CustomHttpClientScenario.kt
│ │ │ │ │ │ ├── CustomPluginExample.kt
│ │ │ │ │ │ ├── CustomPluginNotifierDescriptionScenario.kt
│ │ │ │ │ │ ├── DeliverOnCrashScenario.kt
│ │ │ │ │ │ ├── DisableAutoDetectErrorsScenario.kt
│ │ │ │ │ │ ├── DiscardBigEventsScenario.kt
│ │ │ │ │ │ ├── DiscardOldEventsScenario.kt
│ │ │ │ │ │ ├── DiscardOldSessionScenario.kt
│ │ │ │ │ │ ├── DiscardOldSessionScenarioPart2.kt
│ │ │ │ │ │ ├── DiscardOldSessionScenarioPart3.kt
│ │ │ │ │ │ ├── EmptyEnabledReleaseStageScenario.kt
│ │ │ │ │ │ ├── EmptyStacktraceScenario.kt
│ │ │ │ │ │ ├── ErrorBreadcrumbsScenario.kt
│ │ │ │ │ │ ├── FeatureFlagScenario.kt
│ │ │ │ │ │ ├── HandledExceptionApiKeyChangeScenario.kt
│ │ │ │ │ │ ├── HandledExceptionMaxThreadsScenario.kt
│ │ │ │ │ │ ├── HandledExceptionScenario.kt
│ │ │ │ │ │ ├── HandledExceptionWithoutMessageScenario.kt
│ │ │ │ │ │ ├── HandledJavaSmokeScenario.java
│ │ │ │ │ │ ├── HandledJvmAutoNotifyFalseScenario.kt
│ │ │ │ │ │ ├── HandledKotlinSmokeScenario.kt
│ │ │ │ │ │ ├── HandledOnSendCallbackScenario.kt
│ │ │ │ │ │ ├── IgnoredExceptionScenario.kt
│ │ │ │ │ │ ├── InForegroundScenario.kt
│ │ │ │ │ │ ├── InternalErrorDisabledScenario.kt
│ │ │ │ │ │ ├── InternalErrorScenario.kt
│ │ │ │ │ │ ├── JvmAnrDisabledScenario.kt
│ │ │ │ │ │ ├── JvmAnrLoopScenario.kt
│ │ │ │ │ │ ├── JvmAnrMinimalFixtureScenario.kt
│ │ │ │ │ │ ├── JvmAnrOutsideReleaseStagesScenario.java
│ │ │ │ │ │ ├── JvmAnrSleepScenario.kt
│ │ │ │ │ │ ├── JvmCrashLoopScenario.kt
│ │ │ │ │ │ ├── JvmDelayedErrorScenario.kt
│ │ │ │ │ │ ├── JvmMarkLaunchCompletedScenario.kt
│ │ │ │ │ │ ├── LoadConfigurationFromManifestScenario.kt
│ │ │ │ │ │ ├── LoadConfigurationKotlinScenario.kt
│ │ │ │ │ │ ├── LoadConfigurationNullsScenario.java
│ │ │ │ │ │ ├── ManualRedactKeysScenario.kt
│ │ │ │ │ │ ├── ManualSessionSmokeScenario.kt
│ │ │ │ │ │ ├── MetadataNestedNullScenario.kt
│ │ │ │ │ │ ├── MetadataScenario.kt
│ │ │ │ │ │ ├── MultiProcessHandledExceptionScenario.kt
│ │ │ │ │ │ ├── MultiProcessUnhandledExceptionScenario.kt
│ │ │ │ │ │ ├── NaughtyStringScenario.kt
│ │ │ │ │ │ ├── NetworkBreadcrumbScenario.kt
│ │ │ │ │ │ ├── NullReleaseStageScenario.kt
│ │ │ │ │ │ ├── NullStackTraceScenario.kt
│ │ │ │ │ │ ├── OkHttpDeliveryScenario.kt
│ │ │ │ │ │ ├── OnSendCallbackScenario.kt
│ │ │ │ │ │ ├── OomScenario.kt
│ │ │ │ │ │ ├── OutsideReleaseStageScenario.kt
│ │ │ │ │ │ ├── OverrideToHandledExceptionScenario.kt
│ │ │ │ │ │ ├── OverrideToUnhandledExceptionScenario.kt
│ │ │ │ │ │ ├── ReportCacheScenario.kt
│ │ │ │ │ │ ├── Scenario.kt
│ │ │ │ │ │ ├── SessionApiKeyResetScenario.kt
│ │ │ │ │ │ ├── SessionCacheScenario.kt
│ │ │ │ │ │ ├── SessionPersistUserDisabledScenario.kt
│ │ │ │ │ │ ├── SessionPersistUserScenario.kt
│ │ │ │ │ │ ├── SessionStoppingScenario.kt
│ │ │ │ │ │ ├── SharedPrefMigrationScenario.kt
│ │ │ │ │ │ ├── StackOverflowScenario.kt
│ │ │ │ │ │ ├── StartSessionAutoModeScenario.kt
│ │ │ │ │ │ ├── StartupCrashFlushScenario.kt
│ │ │ │ │ │ ├── StrictModeDiscScenario.kt
│ │ │ │ │ │ ├── StrictModeFileUriExposeScenario.kt
│ │ │ │ │ │ ├── StrictModeNetworkScenario.kt
│ │ │ │ │ │ ├── TrimmedStacktraceScenario.kt
│ │ │ │ │ │ ├── UnhandledExceptionApiKeyChangeScenario.kt
│ │ │ │ │ │ ├── UnhandledExceptionEventDetailChangeScenario.kt
│ │ │ │ │ │ ├── UnhandledExceptionMaxThreadsScenario.kt
│ │ │ │ │ │ ├── UnhandledExceptionScenario.kt
│ │ │ │ │ │ ├── UnhandledJavaLoadedConfigScenario.java
│ │ │ │ │ │ ├── UnhandledJvmAutoNotifyFalseScenario.kt
│ │ │ │ │ │ ├── UnhandledJvmAutoNotifyTrueScenario.kt
│ │ │ │ │ │ ├── UnsatisfiedLinkErrorScenario.java
│ │ │ │ │ │ ├── UserCallbackScenario.kt
│ │ │ │ │ │ ├── UserDisabledScenario.kt
│ │ │ │ │ │ └── UserIdScenario.kt
│ │ │ │ │ └── multiprocess
│ │ │ │ │ ├── MultiProcessService.kt
│ │ │ │ │ └── ProcessCompat.kt
│ │ │ │ └── resources
│ │ │ │ └── naughty_strings.txt
│ │ └── settings.gradle
│ └── minimalapp
│ │ ├── .gitignore
│ │ ├── Dangerfile
│ │ ├── Gemfile
│ │ ├── app
│ │ ├── build.gradle
│ │ ├── fakekeys.jks
│ │ └── src
│ │ │ └── main
│ │ │ ├── AndroidManifest.xml
│ │ │ └── java
│ │ │ └── com
│ │ │ └── bugsnag
│ │ │ └── android
│ │ │ └── minimalapp
│ │ │ └── CustomApp.java
│ │ ├── build.gradle
│ │ ├── gradle.properties
│ │ ├── gradle
│ │ └── wrapper
│ │ │ ├── gradle-wrapper.jar
│ │ │ └── gradle-wrapper.properties
│ │ ├── gradlew
│ │ ├── gradlew.bat
│ │ └── settings.gradle
├── full_tests
│ ├── anr.feature
│ ├── async_error_flush.feature
│ ├── auto_notify.feature
│ ├── breadcrumb.feature
│ ├── bugsnag_init.feature
│ ├── crash_handler.feature
│ ├── custom_http_client.feature
│ ├── detect_ndk_crashes.feature
│ ├── discarded_events.feature
│ ├── discarded_session.feature
│ ├── empty_stacktrace.feature
│ ├── error_callback_alters_fields.feature
│ ├── event_callback_alters_api_key.feature
│ ├── exit_information.feature
│ ├── feature_flags.feature
│ ├── filtering_metadata.feature
│ ├── handled_exception.feature
│ ├── identify_crashes_on_launch.feature
│ ├── ignored_reports.feature
│ ├── in_foreground.feature
│ ├── internal_error_reports.feature
│ ├── load_configuration.feature
│ ├── max_reported_threads.feature
│ ├── meta_data_scenario.feature
│ ├── multi_process.feature
│ ├── native_api.feature
│ ├── native_breadcrumbs.feature
│ ├── native_context.feature
│ ├── native_crash_handling.feature
│ ├── native_event_tracking.feature
│ ├── native_feature_flags.feature
│ ├── native_metadata.feature
│ ├── native_on_error.feature
│ ├── native_session_tracking.feature
│ ├── native_signal_raise.feature
│ ├── native_threads.feature
│ ├── native_throw_crash.feature
│ ├── native_user.feature
│ ├── naughty_strings.feature
│ ├── network_breadcrumbs.feature
│ ├── null_stacktrace.feature
│ ├── onsend_callback.feature
│ ├── oom.feature
│ ├── override_unhandled.feature
│ ├── plugin_interface.feature
│ ├── release_stage.feature
│ ├── session_stopping.feature
│ ├── session_tracking.feature
│ ├── stackoverflow.feature
│ ├── startup_anr.feature
│ ├── strict_mode_legacy.feature
│ ├── strict_mode_violations.feature
│ ├── trimmed_stacktrace.feature
│ ├── trimming.feature
│ ├── usage.feature
│ └── user.feature
├── minimal
│ └── detect_anr_minimal.feature
├── scripts
│ ├── close-anr-dialog.sh
│ ├── generate_gpg_key
│ └── tap-screen.sh
├── smoke_tests
│ ├── 01_anr.feature
│ ├── 02_handled.feature
│ ├── 03_sessions.feature
│ └── 04_unhandled.feature
├── steps
│ ├── android_steps.rb
│ ├── breadcrumb_metadata_steps.rb
│ └── symbol_steps.rb
└── support
│ ├── env.rb
│ ├── maze.all.cfg
│ └── maze.buildkite.cfg
├── gradle.properties
├── gradle
├── detekt.gradle
├── license-check.gradle
├── release.gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── maze_output
└── .gitignore
├── scripts
├── audit-dependency-licenses.sh
├── bump-version.sh
├── copy-build-files.rb
├── docker-publish.sh
├── run-clang-format-ci-check.sh
├── run-clang-format.sh
├── run-connected-checks.rb
├── run-cpp-check.sh
└── run-sizer.sh
└── settings.gradle.kts
/.buildkite/block.step.yml:
--------------------------------------------------------------------------------
1 | agents:
2 | queue: 'macos'
3 |
4 | steps:
5 | - label:
6 | block: 'Trigger full build'
7 | key: 'trigger-full-build'
8 |
9 | - label: 'Upload the full test pipeline'
10 | depends_on: 'trigger-full-build'
11 | command: buildkite-agent pipeline upload .buildkite/pipeline.full.yml
12 | timeout_in_minutes: 5
13 |
--------------------------------------------------------------------------------
/.buildkite/pipeline_trigger.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | if [[ "$BUILDKITE_MESSAGE" == *"[full ci]"* ||
4 | "$BUILDKITE_BRANCH" == "main" ||
5 | "$BUILDKITE_PULL_REQUEST_BASE_BRANCH" == "main" ||
6 | ! -z "$FULL_SCHEDULED_BUILD" ]]; then
7 | # Full build
8 | buildkite-agent pipeline upload .buildkite/pipeline.full.yml
9 |
10 | else
11 | # Basic build, but allow a full build to be triggered
12 | buildkite-agent pipeline upload .buildkite/block.step.yml
13 | fi
14 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/A.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Having trouble getting started?
3 | about: Please contact us at support@bugsnag.com for assistance with integrating BugSnag
4 | into your application.
5 | title: ''
6 | labels: ''
7 | assignees: ''
8 |
9 | ---
10 | Please check out our [documentation](https://docs.bugsnag.com/platforms/android/) for guides, references and tutorials.
11 |
12 | If you have questions about your integration, please contact us at [support@bugsnag.com](mailto:support@bugsnag.com).
13 |
14 | Alternatively, view additional options at [SUPPORT.md](../SUPPORT.md).
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature request
3 | about: Suggest an idea for this project
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 |
11 |
12 | ### Description
13 |
16 |
17 | **Describe the solution you'd like**
18 |
19 |
20 | **Describe alternatives you've considered**
21 |
22 |
23 | **Additional context**
24 |
--------------------------------------------------------------------------------
/.github/PULL_REQUEST_TEMPLATE.md:
--------------------------------------------------------------------------------
1 | ## Goal
2 |
3 |
4 |
5 | ## Design
6 |
7 |
8 |
9 | ## Changeset
10 |
11 |
12 |
13 | ## Testing
14 |
15 |
--------------------------------------------------------------------------------
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | # To get started with Dependabot version updates, you'll need to specify which
2 | # package ecosystems to update and where the package manifests are located.
3 | # Please see the documentation for all configuration options:
4 | # https://docs.github.com/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file
5 | version: 2
6 | updates:
7 | - package-ecosystem: "bundler"
8 | directory: "/"
9 | schedule:
10 | interval: "weekly"
11 | - package-ecosystem: "github-actions"
12 | directory: "/"
13 | schedule:
14 | interval: "weekly"
15 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Gradle files
2 | .gradle/
3 | build/
4 |
5 | # Local configuration file (sdk path, etc)
6 | local.properties
7 |
8 | # Android Studio generated folders
9 | captures/
10 | .externalNativeBuild
11 |
12 | # IntelliJ project files
13 | *.iml
14 | .idea/
15 |
16 | # Misc
17 | .DS_Store
18 | infer-out/
19 | *.log
20 | CMakeFiles
21 | CMakeCache.txt
22 | Testing
23 | bugsnag_test
24 | *.crash
25 | .cxx/
26 | .project
27 | decisions.yml
28 | Gemfile.lock
29 |
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "bugsnag-plugin-android-ndk/src/main/jni/external/libunwindstack-ndk"]
2 | path = bugsnag-plugin-android-ndk/src/main/jni/external/libunwindstack-ndk
3 | url = https://github.com/bugsnag/libunwindstack-ndk
4 | [submodule "bugsnag-android-core/dsl-json"]
5 | path = bugsnag-android-core/dsl-json
6 | url = https://github.com/bugsnag/dsl-json
7 |
--------------------------------------------------------------------------------
/CODEOWNERS:
--------------------------------------------------------------------------------
1 | bugsnag-android/ @lemnik @YYChen01988
2 | bugsnag-android-core/ @lemnik @YYChen01988
3 | bugsnag-plugin-android-anr/ @lemnik @YYChen01988
4 | bugsnag-plugin-android-exitinfo/ @lemnik @YYChen01988
5 | bugsnag-plugin-android-ndk/ @lemnik @YYChen01988
6 | bugsnag-plugin-android-okhttp/ @lemnik @YYChen01988
7 | bugsnag-plugin-react-native/ @lemnik @YYChen01988
8 |
--------------------------------------------------------------------------------
/Gemfile:
--------------------------------------------------------------------------------
1 | source "https://rubygems.org"
2 |
3 | # You can run against local Maze Runner branches and uncommitted changes:
4 | #gem 'bugsnag-maze-runner', path: '../maze-runner'
5 |
6 | # Or a specific release:
7 | gem 'bugsnag-maze-runner', '~>9.0'
8 |
9 | # Or follow master:
10 | #gem 'bugsnag-maze-runner', git: 'https://github.com/bugsnag/maze-runner'
11 |
12 | gem "license_finder", "~> 7.0"
13 |
--------------------------------------------------------------------------------
/SECURITY.md:
--------------------------------------------------------------------------------
1 | # Security Policy
2 |
3 | ## Supported Versions
4 |
5 | | Version | Supported |
6 | | ------- | --------------------- |
7 | | 5.x | Critical patches only |
8 | | 6.x | Yes |
9 |
10 | ## Reporting a Vulnerability
11 |
12 | If you find a vulnerability in this SDK, please report it to our [Support Team](mailto:support@bugsnag.com) for review.
13 |
--------------------------------------------------------------------------------
/bugsnag-android-core/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 3.19)
2 | project(bugsnag-android-core)
3 | add_subdirectory(src/main)
4 |
--------------------------------------------------------------------------------
/bugsnag-android-core/README.md:
--------------------------------------------------------------------------------
1 | # bugsnag-android-core
2 |
3 | This module detects JVM exceptions and reports them to bugsnag.
4 |
5 | ## High-level Overview
6 |
7 | An `UncaughtExceptionHandler` is installed which generates an error report whenever an uncaught
8 | `Throwable` propagates. This module is also responsible for the delivery of JSON payloads to the
9 | Error Reporting API, and also provides the main public API for bugsnag-android.
10 |
--------------------------------------------------------------------------------
/bugsnag-android-core/gradle.properties:
--------------------------------------------------------------------------------
1 | pomName=Bugsnag Android Core
2 | artefactId=bugsnag-android-core
3 |
--------------------------------------------------------------------------------
/bugsnag-android-core/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | -keepattributes LineNumberTable,SourceFile
2 | -keep class com.bugsnag.android.NativeInterface { *; }
3 | -keep class com.bugsnag.android.NativeStackframe { *; }
4 | -keep class com.bugsnag.android.Breadcrumb { *; }
5 | -keep class com.bugsnag.android.BreadcrumbState { *; }
6 | -keep class com.bugsnag.android.BreadcrumbType { *; }
7 | -keep class com.bugsnag.android.Severity { *; }
8 | -keepclassmembers enum com.bugsnag.android.Telemetry {
9 | public static com.bugsnag.android.Telemetry[] values();
10 | }
11 | -keepclassmembers enum com.bugsnag.android.ErrorType {
12 | public static com.bugsnag.android.Telemetry[] values();
13 | }
--------------------------------------------------------------------------------
/bugsnag-android-core/src/androidTest/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/bugsnag-android-core/src/androidTest/java/android/os/strictmode/FakeStrictModeViolation.kt:
--------------------------------------------------------------------------------
1 | package android.os.strictmode
2 |
3 | internal class FakeStrictModeViolation : Violation()
4 |
--------------------------------------------------------------------------------
/bugsnag-android-core/src/androidTest/java/com/bugsnag/android/BugsnagKotlinTestUtils.kt:
--------------------------------------------------------------------------------
1 | package com.bugsnag.android
2 |
3 | import android.os.Build
4 |
5 | inline fun withBuildSdkInt(sdk: Int, block: () -> R): R {
6 | val build = Build.VERSION::class.java
7 | val sdkInt = build.getDeclaredField("SDK_INT")
8 | .apply { isAccessible = true }
9 |
10 | val oldSdkInt = sdkInt.get(null)
11 | sdkInt.set(null, sdk)
12 | try {
13 | return block()
14 | } finally {
15 | sdkInt.set(null, oldSdkInt)
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/bugsnag-android-core/src/androidTest/java/com/bugsnag/android/StrictModeWrapper.java:
--------------------------------------------------------------------------------
1 | package com.bugsnag.android;
2 |
3 | import android.os.StrictMode;
4 |
5 | class StrictModeWrapper {
6 |
7 | static void setUp() {
8 | StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
9 | .detectDiskReads()
10 | .penaltyDeath()
11 | .build());
12 | }
13 |
14 | static void tearDown() {
15 | StrictMode.setThreadPolicy(StrictMode.ThreadPolicy.LAX);
16 | }
17 |
18 | }
19 |
--------------------------------------------------------------------------------
/bugsnag-android-core/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/bugsnag-android-core/src/main/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | set(BUGSNAG_VERSION 1.0.1)
2 | add_library( # Specifies the name of the library.
3 | bugsnag-root-detection
4 | # Sets the library as a shared library.
5 | SHARED
6 | # Provides a relative path to your source file(s).
7 | jni/root_detection.c
8 | )
9 |
10 | include_directories(jni)
11 |
12 | set(EXTRA_LINK_FLAGS "-Wl,-z,max-page-size=16384")
13 |
14 | set_target_properties(
15 | bugsnag-root-detection
16 | PROPERTIES
17 | COMPILE_OPTIONS -Werror -Wall -pedantic
18 | LINK_FLAGS "${EXTRA_LINK_FLAGS}"
19 | )
20 |
--------------------------------------------------------------------------------
/bugsnag-android-core/src/main/java/com/bugsnag/android/CallbackAware.kt:
--------------------------------------------------------------------------------
1 | package com.bugsnag.android
2 |
3 | internal interface CallbackAware {
4 | fun addOnError(onError: OnErrorCallback)
5 | fun removeOnError(onError: OnErrorCallback)
6 | fun addOnBreadcrumb(onBreadcrumb: OnBreadcrumbCallback)
7 | fun removeOnBreadcrumb(onBreadcrumb: OnBreadcrumbCallback)
8 | fun addOnSession(onSession: OnSessionCallback)
9 | fun removeOnSession(onSession: OnSessionCallback)
10 | }
11 |
--------------------------------------------------------------------------------
/bugsnag-android-core/src/main/java/com/bugsnag/android/CollectionUtils.java:
--------------------------------------------------------------------------------
1 | package com.bugsnag.android;
2 |
3 | import androidx.annotation.Nullable;
4 |
5 | import java.util.Collection;
6 |
7 | class CollectionUtils {
8 | static boolean containsNullElements(@Nullable Collection data) {
9 | if (data == null) {
10 | return true;
11 | }
12 | for (T datum : data) {
13 | if (datum == null) {
14 | return true;
15 | }
16 | }
17 | return false;
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/bugsnag-android-core/src/main/java/com/bugsnag/android/DeliveryParams.kt:
--------------------------------------------------------------------------------
1 | package com.bugsnag.android
2 |
3 | /**
4 | * The parameters which should be used to deliver an Event/Session.
5 | */
6 | class DeliveryParams(
7 |
8 | /**
9 | * The endpoint to which the payload should be sent
10 | */
11 | val endpoint: String,
12 |
13 | /**
14 | * The HTTP headers which must be attached to the request
15 | */
16 | val headers: Map
17 | )
18 |
--------------------------------------------------------------------------------
/bugsnag-android-core/src/main/java/com/bugsnag/android/DeviceIdPersistence.kt:
--------------------------------------------------------------------------------
1 | package com.bugsnag.android
2 |
3 | interface DeviceIdPersistence {
4 | /**
5 | * Loads the device ID from storage.
6 | *
7 | * Device IDs are UUIDs which are persisted on a per-install basis.
8 | *
9 | * This method must be thread-safe and multi-process safe.
10 | *
11 | * Note: requestCreateIfDoesNotExist is only a request; an implementation may still refuse to create a new ID.
12 | */
13 | fun loadDeviceId(requestCreateIfDoesNotExist: Boolean): String?
14 | }
15 |
--------------------------------------------------------------------------------
/bugsnag-android-core/src/main/java/com/bugsnag/android/Intrinsics.java:
--------------------------------------------------------------------------------
1 | package com.bugsnag.android;
2 |
3 | class Intrinsics {
4 |
5 | static boolean isEmpty(CharSequence str) {
6 | return str == null || str.length() == 0;
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/bugsnag-android-core/src/main/java/com/bugsnag/android/JsonReadable.kt:
--------------------------------------------------------------------------------
1 | package com.bugsnag.android
2 |
3 | import android.util.JsonReader
4 |
5 | /**
6 | * Classes which implement this interface are capable of deserializing a JSON input.
7 | */
8 | internal interface JsonReadable {
9 |
10 | /**
11 | * Constructs an object from a JSON input.
12 | */
13 | fun fromReader(reader: JsonReader): T
14 | }
15 |
--------------------------------------------------------------------------------
/bugsnag-android-core/src/main/java/com/bugsnag/android/LastRunInfo.kt:
--------------------------------------------------------------------------------
1 | package com.bugsnag.android
2 |
3 | /**
4 | * Provides information about the last launch of the application, if there was one.
5 | */
6 | class LastRunInfo(
7 |
8 | /**
9 | * The number times the app has consecutively crashed during its launch period.
10 | */
11 | val consecutiveLaunchCrashes: Int,
12 |
13 | /**
14 | * Whether the last app run ended with a crash, or was abnormally terminated by the system.
15 | */
16 | val crashed: Boolean,
17 |
18 | /**
19 | * True if the previous app run ended with a crash during its launch period.
20 | */
21 | val crashedDuringLaunch: Boolean
22 | ) {
23 | override fun toString(): String {
24 | return "LastRunInfo(consecutiveLaunchCrashes=$consecutiveLaunchCrashes, crashed=$crashed, crashedDuringLaunch=$crashedDuringLaunch)"
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/bugsnag-android-core/src/main/java/com/bugsnag/android/MetadataAware.kt:
--------------------------------------------------------------------------------
1 | package com.bugsnag.android
2 |
3 | internal interface MetadataAware {
4 | fun addMetadata(section: String, value: Map)
5 | fun addMetadata(section: String, key: String, value: Any?)
6 |
7 | fun clearMetadata(section: String)
8 | fun clearMetadata(section: String, key: String)
9 |
10 | fun getMetadata(section: String): Map?
11 | fun getMetadata(section: String, key: String): Any?
12 | }
13 |
--------------------------------------------------------------------------------
/bugsnag-android-core/src/main/java/com/bugsnag/android/NoopLogger.kt:
--------------------------------------------------------------------------------
1 | package com.bugsnag.android
2 |
3 | internal object NoopLogger : Logger
4 |
--------------------------------------------------------------------------------
/bugsnag-android-core/src/main/java/com/bugsnag/android/OnErrorCallback.kt:
--------------------------------------------------------------------------------
1 | package com.bugsnag.android
2 |
3 | /**
4 | * A callback to be run before error reports are sent to Bugsnag.
5 | *
6 | * You can use this to add or modify information attached to an error
7 | * before it is sent to your dashboard. You can also return
8 | * `false` from any callback to halt execution.
9 | *
10 | * "on error" callbacks added via the JVM API do not run when a fatal C/C++ crash occurs.
11 | */
12 | fun interface OnErrorCallback {
13 | /**
14 | * Runs the "on error" callback. If the callback returns
15 | * `false` any further OnErrorCallback callbacks will not be called
16 | * and the event will not be sent to Bugsnag.
17 | *
18 | * @param event the event to be sent to Bugsnag
19 | * @see Event
20 | */
21 | fun onError(event: Event): Boolean
22 | }
23 |
--------------------------------------------------------------------------------
/bugsnag-android-core/src/main/java/com/bugsnag/android/OnSendCallback.kt:
--------------------------------------------------------------------------------
1 | package com.bugsnag.android
2 |
3 | /**
4 | * A callback to be invoked before an [Event] is uploaded to a server. Similar to
5 | * [OnErrorCallback], an `OnSendCallback` may modify the `Event`
6 | * contents or even reject the entire payload by returning `false`.
7 | */
8 | fun interface OnSendCallback {
9 | fun onSend(event: Event): Boolean
10 | }
11 |
--------------------------------------------------------------------------------
/bugsnag-android-core/src/main/java/com/bugsnag/android/OnSessionCallback.kt:
--------------------------------------------------------------------------------
1 | package com.bugsnag.android
2 |
3 | /**
4 | * A callback to be run before sessions are sent to Bugsnag.
5 | *
6 | * You can use this to add or modify information attached to a session
7 | * before it is sent to your dashboard. You can also return
8 | * `false` from any callback to halt execution.
9 | */
10 | fun interface OnSessionCallback {
11 | /**
12 | * Runs the "on session" callback. If the callback returns
13 | * `false` any further OnSessionCallback callbacks will not be called
14 | * and the session will not be sent to Bugsnag.
15 | *
16 | * @param session the session to be sent to Bugsnag
17 | * @see Session
18 | */
19 | fun onSession(session: Session): Boolean
20 | }
21 |
--------------------------------------------------------------------------------
/bugsnag-android-core/src/main/java/com/bugsnag/android/Plugin.kt:
--------------------------------------------------------------------------------
1 | package com.bugsnag.android
2 |
3 | /**
4 | * A plugin allows for additional functionality to be added to the Bugsnag SDK.
5 | */
6 | interface Plugin {
7 |
8 | /**
9 | * Loads a plugin with the given Client. When this method is invoked the plugin should
10 | * activate its behaviour - for example, by capturing an additional source of errors.
11 | */
12 | fun load(client: Client)
13 |
14 | /**
15 | * Unloads a plugin. When this is invoked the plugin should cease all custom behaviour and
16 | * restore the application to its unloaded state.
17 | */
18 | fun unload()
19 | }
20 |
--------------------------------------------------------------------------------
/bugsnag-android-core/src/main/java/com/bugsnag/android/Severity.kt:
--------------------------------------------------------------------------------
1 | package com.bugsnag.android
2 |
3 | import java.io.IOException
4 |
5 | /**
6 | * The severity of an Event, one of "error", "warning" or "info".
7 | *
8 | * By default, unhandled exceptions will be Severity.ERROR and handled
9 | * exceptions sent with bugsnag.notify will be Severity.WARNING.
10 | */
11 | enum class Severity(private val str: String) : JsonStream.Streamable {
12 | ERROR("error"),
13 | WARNING("warning"),
14 | INFO("info");
15 |
16 | @Throws(IOException::class)
17 | override fun toStream(writer: JsonStream) {
18 | writer.value(str)
19 | }
20 |
21 | internal companion object {
22 | internal fun fromDescriptor(desc: String) = values().find { it.str == desc }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/bugsnag-android-core/src/main/java/com/bugsnag/android/StrictModeOnErrorCallback.kt:
--------------------------------------------------------------------------------
1 | package com.bugsnag.android
2 |
3 | internal class StrictModeOnErrorCallback(private val errMsg: String) : OnErrorCallback {
4 | override fun onError(event: Event): Boolean {
5 | event.updateSeverityInternal(Severity.INFO)
6 | event.updateSeverityReason(SeverityReason.REASON_STRICT_MODE)
7 | val error = event.errors.firstOrNull()
8 | error?.errorMessage = errMsg
9 | return true
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/bugsnag-android-core/src/main/java/com/bugsnag/android/Telemetry.kt:
--------------------------------------------------------------------------------
1 | package com.bugsnag.android
2 |
3 | /**
4 | * Types of telemetry that may be sent to Bugsnag for product improvement purposes.
5 | */
6 | enum class Telemetry {
7 |
8 | /**
9 | * Errors within the Bugsnag SDK.
10 | */
11 | INTERNAL_ERRORS,
12 |
13 | /**
14 | * Differences from the default configuration.
15 | */
16 | USAGE;
17 |
18 | internal companion object {
19 | fun fromString(str: String) = values().find { it.name == str } ?: INTERNAL_ERRORS
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/bugsnag-android-core/src/main/java/com/bugsnag/android/ThreadSendPolicy.kt:
--------------------------------------------------------------------------------
1 | package com.bugsnag.android
2 |
3 | /**
4 | * Controls whether we should capture and serialize the state of all threads at the time
5 | * of an error.
6 | */
7 | enum class ThreadSendPolicy {
8 |
9 | /**
10 | * Threads should be captured for all events.
11 | */
12 | ALWAYS,
13 |
14 | /**
15 | * Threads should be captured for unhandled events only.
16 | */
17 | UNHANDLED_ONLY,
18 |
19 | /**
20 | * Threads should never be captured.
21 | */
22 | NEVER;
23 |
24 | internal companion object {
25 | fun fromString(str: String) = values().find { it.name == str } ?: ALWAYS
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/bugsnag-android-core/src/main/java/com/bugsnag/android/ThrowableExtensions.kt:
--------------------------------------------------------------------------------
1 | @file:JvmName("ThrowableUtils")
2 | package com.bugsnag.android
3 |
4 | /**
5 | * Unroll the list of causes for this Throwable, handling any recursion that may appear within
6 | * the chain. The first element returned will be this Throwable, and the last will be the root
7 | * cause or last non-recursive Throwable.
8 | */
9 | internal fun Throwable.safeUnrollCauses(): List {
10 | val causes = LinkedHashSet()
11 | var currentEx: Throwable? = this
12 |
13 | // Set.add will return false if we have already "seen" currentEx
14 | while (currentEx != null && causes.add(currentEx)) {
15 | currentEx = currentEx.cause
16 | }
17 |
18 | return causes.toList()
19 | }
20 |
--------------------------------------------------------------------------------
/bugsnag-android-core/src/main/java/com/bugsnag/android/TraceCorrelation.kt:
--------------------------------------------------------------------------------
1 | package com.bugsnag.android
2 |
3 | import java.util.UUID
4 |
5 | internal data class TraceCorrelation(val traceId: UUID, val spanId: Long) : JsonStream.Streamable {
6 | override fun toStream(writer: JsonStream) {
7 | writer.beginObject()
8 | .name("traceId").value(traceId.toHexString())
9 | .name("spanId").value(spanId.toHexString())
10 | writer.endObject()
11 | }
12 |
13 | private fun UUID.toHexString(): String {
14 | return "%016x%016x".format(mostSignificantBits, leastSignificantBits)
15 | }
16 |
17 | private fun Long.toHexString(): String {
18 | return "%016x".format(this)
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/bugsnag-android-core/src/main/java/com/bugsnag/android/UserAware.kt:
--------------------------------------------------------------------------------
1 | package com.bugsnag.android
2 |
3 | internal interface UserAware {
4 | fun getUser(): User
5 | fun setUser(id: String?, email: String?, name: String?)
6 | }
7 |
--------------------------------------------------------------------------------
/bugsnag-android-core/src/main/java/com/bugsnag/android/UserState.kt:
--------------------------------------------------------------------------------
1 | package com.bugsnag.android
2 |
3 | internal class UserState(user: User) : BaseObservable() {
4 | var user = user
5 | set(value) {
6 | field = value
7 | emitObservableEvent()
8 | }
9 |
10 | fun emitObservableEvent() = updateState { StateEvent.UpdateUser(user) }
11 | }
12 |
--------------------------------------------------------------------------------
/bugsnag-android-core/src/main/java/com/bugsnag/android/internal/BugsnagContentProvider.kt:
--------------------------------------------------------------------------------
1 | package com.bugsnag.android.internal
2 |
3 | import android.app.Application
4 |
5 | class BugsnagContentProvider : AbstractStartupProvider() {
6 | override fun onCreate(): Boolean {
7 | (context?.applicationContext as? Application)?.let { app ->
8 | ForegroundDetector.registerOn(app)
9 | }
10 |
11 | return true
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/bugsnag-android-core/src/main/java/com/bugsnag/android/internal/ByteArrayExtensions.kt:
--------------------------------------------------------------------------------
1 | package com.bugsnag.android.internal
2 |
3 | private const val HEX_RADIX = 16
4 |
5 | /**
6 | * Encode this `ByteArray` as a string of lowercase hex-pairs.
7 | */
8 | internal fun ByteArray.toHexString(): String = buildString(size * 2) {
9 | for (byte in this@toHexString) {
10 | @Suppress("MagicNumber")
11 | val value = byte.toInt() and 0xff
12 | if (value < HEX_RADIX) append('0')
13 | append(value.toString(HEX_RADIX))
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/bugsnag-android-core/src/main/java/com/bugsnag/android/internal/InternalMetricsNoop.kt:
--------------------------------------------------------------------------------
1 | package com.bugsnag.android.internal
2 |
3 | class InternalMetricsNoop : InternalMetrics {
4 | override fun toJsonableMap(): Map = emptyMap()
5 | override fun setConfigDifferences(differences: Map) = Unit
6 | override fun setCallbackCounts(newCallbackCounts: Map) = Unit
7 | override fun notifyAddCallback(callback: String) = Unit
8 | override fun notifyRemoveCallback(callback: String) = Unit
9 | override fun setMetadataTrimMetrics(stringsTrimmed: Int, charsRemoved: Int) = Unit
10 | override fun setBreadcrumbTrimMetrics(breadcrumbsRemoved: Int, bytesRemoved: Int) = Unit
11 | }
12 |
--------------------------------------------------------------------------------
/bugsnag-android-core/src/main/java/com/bugsnag/android/internal/StateObserver.kt:
--------------------------------------------------------------------------------
1 | package com.bugsnag.android.internal
2 |
3 | import com.bugsnag.android.StateEvent
4 |
5 | fun interface StateObserver {
6 | /**
7 | * This is called whenever the notifier's state is altered, so that observers can react
8 | * appropriately. This is intended for internal use only.
9 | */
10 | fun onStateChange(event: StateEvent)
11 | }
12 |
--------------------------------------------------------------------------------
/bugsnag-android-core/src/main/java/com/bugsnag/android/internal/dag/ConfigModule.kt:
--------------------------------------------------------------------------------
1 | package com.bugsnag.android.internal.dag
2 |
3 | import com.bugsnag.android.Configuration
4 | import com.bugsnag.android.Connectivity
5 | import com.bugsnag.android.internal.BackgroundTaskService
6 | import com.bugsnag.android.internal.sanitiseConfiguration
7 |
8 | /**
9 | * A dependency module which constructs the configuration object that is used to alter
10 | * Bugsnag's default behaviour.
11 | */
12 | internal class ConfigModule(
13 | contextModule: ContextModule,
14 | configuration: Configuration,
15 | connectivity: Connectivity,
16 | bgTaskExecutor: BackgroundTaskService
17 | ) : BackgroundDependencyModule(bgTaskExecutor) {
18 | val config = sanitiseConfiguration(contextModule.ctx, configuration, connectivity, bgTaskExecutor)
19 | }
20 |
--------------------------------------------------------------------------------
/bugsnag-android-core/src/main/java/com/bugsnag/android/internal/dag/ContextModule.kt:
--------------------------------------------------------------------------------
1 | package com.bugsnag.android.internal.dag
2 |
3 | import android.content.Context
4 | import com.bugsnag.android.internal.BackgroundTaskService
5 |
6 | /**
7 | * A dependency module which accesses the application context object, falling back to the supplied
8 | * context if it is the base context.
9 | */
10 | internal class ContextModule(
11 | appContext: Context,
12 | bgTaskService: BackgroundTaskService
13 | ) : BackgroundDependencyModule(bgTaskService) {
14 |
15 | val ctx: Context = when (appContext.applicationContext) {
16 | null -> appContext
17 | else -> appContext.applicationContext
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/bugsnag-android-core/src/main/java/com/bugsnag/android/internal/dag/SystemServiceModule.kt:
--------------------------------------------------------------------------------
1 | package com.bugsnag.android.internal.dag
2 |
3 | import com.bugsnag.android.getActivityManager
4 | import com.bugsnag.android.getStorageManager
5 | import com.bugsnag.android.internal.BackgroundTaskService
6 |
7 | /**
8 | * A dependency module which provides a reference to Android system services.
9 | */
10 | internal class SystemServiceModule(
11 | contextModule: ContextModule,
12 | bgTaskService: BackgroundTaskService
13 | ) : BackgroundDependencyModule(bgTaskService) {
14 |
15 | val storageManager = contextModule.ctx.getStorageManager()
16 | val activityManager = contextModule.ctx.getActivityManager()
17 | }
18 |
--------------------------------------------------------------------------------
/bugsnag-android-core/src/test/java/android/os/strictmode/FakeStrictModeViolation.kt:
--------------------------------------------------------------------------------
1 | package android.os.strictmode
2 |
3 | internal class FakeStrictModeViolation : Violation()
4 |
--------------------------------------------------------------------------------
/bugsnag-android-core/src/test/java/com/bugsnag/android/BreadcrumbMutabilityTest.kt:
--------------------------------------------------------------------------------
1 | package com.bugsnag.android
2 |
3 | import org.junit.Assert.assertFalse
4 | import org.junit.Test
5 | import java.util.Date
6 |
7 | class BreadcrumbMutabilityTest {
8 | @Test
9 | fun breadcrumbProtectsMetadata() {
10 | val data = mutableMapOf()
11 | val breadcrumb = Breadcrumb("foo", BreadcrumbType.MANUAL, data, Date(0), NoopLogger)
12 | breadcrumb.metadata!!["a"] = "bar"
13 | assertFalse(breadcrumb.metadata!!.isEmpty())
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/bugsnag-android-core/src/test/java/com/bugsnag/android/BreadcrumbNullabilityTest.java:
--------------------------------------------------------------------------------
1 | package com.bugsnag.android;
2 |
3 | import static org.junit.Assert.assertEquals;
4 | import static org.junit.Assert.assertNull;
5 |
6 | import org.junit.Test;
7 |
8 | import java.util.Date;
9 |
10 | public class BreadcrumbNullabilityTest {
11 |
12 | @Test
13 | public void testCreateFullBreadcrumbWithoutMetadata() {
14 | Date now = new Date();
15 | Breadcrumb crumb = new Breadcrumb("badger spotted", BreadcrumbType.USER,
16 | null, now, NoopLogger.INSTANCE);
17 | assertEquals("badger spotted", crumb.getMessage());
18 | assertEquals(BreadcrumbType.USER, crumb.getType());
19 | assertEquals(now, crumb.getTimestamp());
20 | assertNull(crumb.getMetadata());
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/bugsnag-android-core/src/test/java/com/bugsnag/android/CollectionUtilsTest.java:
--------------------------------------------------------------------------------
1 | package com.bugsnag.android;
2 |
3 | import static org.junit.Assert.assertFalse;
4 | import static org.junit.Assert.assertTrue;
5 |
6 | import org.junit.Test;
7 |
8 | import java.util.HashSet;
9 | import java.util.Set;
10 |
11 | @SuppressWarnings("ConstantConditions")
12 | public class CollectionUtilsTest {
13 |
14 | @Test
15 | public void nullInput() {
16 | assertTrue(CollectionUtils.containsNullElements(null));
17 | }
18 |
19 | @Test
20 | public void sanitiseSet() {
21 | Set input = new HashSet<>();
22 | input.add("foo");
23 | assertFalse(CollectionUtils.containsNullElements(input));
24 | input.add(null);
25 | assertTrue(CollectionUtils.containsNullElements(input));
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/bugsnag-android-core/src/test/java/com/bugsnag/android/EventPayloadTest.kt:
--------------------------------------------------------------------------------
1 | package com.bugsnag.android
2 |
3 | import org.junit.Assert.assertEquals
4 | import org.junit.Assert.assertNotSame
5 | import org.junit.Test
6 |
7 | class EventPayloadTest {
8 |
9 | @Test
10 | fun testCloneNotifier() {
11 | val original = Notifier()
12 | val config = BugsnagTestUtils.generateImmutableConfig()
13 | val payload = EventPayload("api-key", null, null, original, config)
14 | val copy = payload.notifier
15 | assertNotSame(original, copy)
16 | assertNotSame(original.dependencies, copy.dependencies)
17 | assertEquals(original.dependencies, copy.dependencies)
18 | assertEquals(original.name, copy.name)
19 | assertEquals(original.url, copy.url)
20 | assertEquals(original.version, copy.version)
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/bugsnag-android-core/src/test/java/com/bugsnag/android/InterceptingLogger.kt:
--------------------------------------------------------------------------------
1 | package com.bugsnag.android
2 |
3 | class InterceptingLogger : Logger {
4 |
5 | var msg: String? = null
6 |
7 | override fun w(msg: String) {
8 | this.msg = msg
9 | }
10 |
11 | override fun w(msg: String, throwable: Throwable) {
12 | this.msg = msg
13 | }
14 |
15 | override fun e(msg: String) {
16 | this.msg = msg
17 | }
18 |
19 | override fun e(msg: String, throwable: Throwable) {
20 | this.msg = msg
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/bugsnag-android-core/src/test/java/com/bugsnag/android/JsonParser.kt:
--------------------------------------------------------------------------------
1 | package com.bugsnag.android
2 |
3 | import java.io.StringWriter
4 |
5 | internal class JsonParser {
6 |
7 | fun read(resourceName: String): String {
8 | return JsonParser::class.java.classLoader!!.getResource(resourceName).readText()
9 | }
10 |
11 | fun toJsonString(streamable: JsonStream.Streamable): String {
12 | val writer = StringWriter()
13 | val jsonStream = JsonStream(writer)
14 | streamable.toStream(jsonStream)
15 | return writer.toString()
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/bugsnag-android-core/src/test/java/com/bugsnag/android/LastRunInfoApiTest.java:
--------------------------------------------------------------------------------
1 | package com.bugsnag.android;
2 |
3 | import static org.junit.Assert.assertEquals;
4 | import static org.junit.Assert.assertFalse;
5 | import static org.junit.Assert.assertTrue;
6 |
7 | import org.junit.Test;
8 |
9 | public class LastRunInfoApiTest {
10 |
11 | /**
12 | * Verifies the LastRunInfo class contains the expected methods and hasn't broken
13 | * its API contract.
14 | */
15 | @Test
16 | public void testLastRunInfo() {
17 | LastRunInfo lastRunInfo = new LastRunInfo(5, true, false);
18 | assertEquals(5, lastRunInfo.getConsecutiveLaunchCrashes());
19 | assertTrue(lastRunInfo.getCrashed());
20 | assertFalse(lastRunInfo.getCrashedDuringLaunch());
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/bugsnag-android-core/src/test/java/com/bugsnag/android/OnErrorCallbackTest.kt:
--------------------------------------------------------------------------------
1 | package com.bugsnag.android
2 |
3 | import com.bugsnag.android.BugsnagTestUtils.generateImmutableConfig
4 | import org.junit.Assert.assertEquals
5 | import org.junit.Test
6 |
7 | class OnErrorCallbackTest {
8 |
9 | private val config = generateImmutableConfig()
10 |
11 | @Test
12 | fun testRunModifiesError() {
13 | val context = "new-context"
14 |
15 | val onError = OnErrorCallback {
16 | it.context = context
17 | false
18 | }
19 |
20 | val handledState = SeverityReason.newInstance(
21 | SeverityReason.REASON_HANDLED_EXCEPTION
22 | )
23 | val error = Event(RuntimeException("Test"), config, handledState, NoopLogger)
24 | onError.onError(error)
25 | assertEquals(context, error.context)
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/bugsnag-android-core/src/test/java/com/bugsnag/android/SeveritySerializationTest.kt:
--------------------------------------------------------------------------------
1 | package com.bugsnag.android
2 |
3 | import org.junit.Test
4 | import org.junit.runner.RunWith
5 | import org.junit.runners.Parameterized
6 | import org.junit.runners.Parameterized.Parameter
7 | import org.junit.runners.Parameterized.Parameters
8 |
9 | @RunWith(Parameterized::class)
10 | internal class SeveritySerializationTest {
11 |
12 | companion object {
13 | @JvmStatic
14 | @Parameters
15 | fun testCases() = generateSerializationTestCases(
16 | "severity",
17 | Severity.ERROR,
18 | Severity.WARNING,
19 | Severity.INFO
20 | )
21 | }
22 |
23 | @Parameter
24 | lateinit var testCase: Pair
25 |
26 | @Test
27 | fun testJsonSerialisation() = verifyJsonMatches(testCase.first, testCase.second)
28 | }
29 |
--------------------------------------------------------------------------------
/bugsnag-android-core/src/test/java/com/bugsnag/android/StrictModeFacadeTest.java:
--------------------------------------------------------------------------------
1 | package com.bugsnag.android;
2 |
3 | import static org.junit.Assert.assertNotNull;
4 |
5 | import org.junit.Test;
6 |
7 | /**
8 | * Ensures that Bugsnag's API surface is able to deal with any unexpected null input that might
9 | * cause the SDK to crash.
10 | */
11 | public class StrictModeFacadeTest {
12 |
13 | @Test
14 | public void testInvalidThreadListener() {
15 | BugsnagThreadViolationListener listener = new BugsnagThreadViolationListener(null);
16 | listener.onThreadViolation(null);
17 | assertNotNull(listener);
18 | }
19 |
20 | @Test
21 | public void testInvalidVmListener() {
22 | BugsnagVmViolationListener listener = new BugsnagVmViolationListener(null);
23 | listener.onVmViolation(null);
24 | assertNotNull(listener);
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/bugsnag-android-core/src/test/java/com/bugsnag/android/ThreadSendPolicyTest.kt:
--------------------------------------------------------------------------------
1 | package com.bugsnag.android
2 |
3 | import com.bugsnag.android.ThreadSendPolicy.ALWAYS
4 | import com.bugsnag.android.ThreadSendPolicy.NEVER
5 | import com.bugsnag.android.ThreadSendPolicy.UNHANDLED_ONLY
6 | import org.junit.Assert.assertEquals
7 | import org.junit.Test
8 |
9 | class ThreadSendPolicyTest {
10 |
11 | @Test
12 | fun invalidFromString() {
13 | assertEquals(ALWAYS, ThreadSendPolicy.fromString(""))
14 | assertEquals(ALWAYS, ThreadSendPolicy.fromString("foo"))
15 | }
16 |
17 | @Test
18 | fun validFromString() {
19 | assertEquals(ALWAYS, ThreadSendPolicy.fromString("ALWAYS"))
20 | assertEquals(NEVER, ThreadSendPolicy.fromString("NEVER"))
21 | assertEquals(UNHANDLED_ONLY, ThreadSendPolicy.fromString("UNHANDLED_ONLY"))
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/bugsnag-android-core/src/test/java/com/bugsnag/android/UserSerializationTest.kt:
--------------------------------------------------------------------------------
1 | package com.bugsnag.android
2 |
3 | import org.junit.Test
4 | import org.junit.runner.RunWith
5 | import org.junit.runners.Parameterized
6 | import org.junit.runners.Parameterized.Parameter
7 | import org.junit.runners.Parameterized.Parameters
8 |
9 | @RunWith(Parameterized::class)
10 | internal class UserSerializationTest {
11 |
12 | companion object {
13 | @JvmStatic
14 | @Parameters
15 | fun testCases() = generateSerializationTestCases(
16 | "user",
17 | User("123", "bob@example.com", "bob smith")
18 | )
19 | }
20 |
21 | @Parameter
22 | lateinit var testCase: Pair
23 |
24 | @Test
25 | fun testJsonSerialisation() = verifyJsonMatches(testCase.first, testCase.second)
26 | }
27 |
--------------------------------------------------------------------------------
/bugsnag-android-core/src/test/java/com/bugsnag/android/UserTest.java:
--------------------------------------------------------------------------------
1 | package com.bugsnag.android;
2 |
3 | import static org.junit.Assert.assertEquals;
4 |
5 | import org.junit.Before;
6 | import org.junit.Test;
7 |
8 | public class UserTest {
9 |
10 | private User user;
11 |
12 | @Before
13 | public void setUp() {
14 | user = new User("123", "bob@example.com", "bob smith");
15 | }
16 |
17 | @Test
18 | public void testUserDefaults() {
19 | assertEquals("123", user.getId());
20 | assertEquals("bob smith", user.getName());
21 | assertEquals("bob@example.com", user.getEmail());
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/bugsnag-android-core/src/test/resources/app_data_serialization_0.json:
--------------------------------------------------------------------------------
1 | {
2 | "binaryArch": "x86",
3 | "codeBundleId": "foo-99",
4 | "id": "com.example.foo",
5 | "releaseStage": "test-stage",
6 | "type": "React Native",
7 | "version": "1.2.3",
8 | "versionCode": 55
9 | }
--------------------------------------------------------------------------------
/bugsnag-android-core/src/test/resources/app_data_serialization_1.json:
--------------------------------------------------------------------------------
1 | {
2 | "binaryArch": "x86",
3 | "codeBundleId": "foo-99",
4 | "id": "com.example.foo",
5 | "releaseStage": "test-stage",
6 | "type": "React Native",
7 | "version": "1.2.3",
8 | "versionCode": 55,
9 | "duration": 0,
10 | "durationInForeground": 0,
11 | "inForeground": false,
12 | "isLaunching": false
13 | }
14 |
--------------------------------------------------------------------------------
/bugsnag-android-core/src/test/resources/app_meta_data_serialization_0.json:
--------------------------------------------------------------------------------
1 | {
2 | "memoryTrimLevel": "None",
3 | "activeScreen": "MyActivity",
4 | "name": "MyApp",
5 | "lowMemory": false
6 | }
7 |
--------------------------------------------------------------------------------
/bugsnag-android-core/src/test/resources/breadcrumb_serialization_0.json:
--------------------------------------------------------------------------------
1 | {
2 | "timestamp": "1970-01-01T00:00:00.000Z",
3 | "name": "hello world",
4 | "type": "manual",
5 | "metaData": {}
6 | }
--------------------------------------------------------------------------------
/bugsnag-android-core/src/test/resources/breadcrumb_serialization_1.json:
--------------------------------------------------------------------------------
1 | {
2 | "timestamp": "1970-01-01T00:00:00.000Z",
3 | "name": "metadata",
4 | "type": "process",
5 | "metaData": {
6 | "foo": true,
7 | "password": "[REDACTED]"
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/bugsnag-android-core/src/test/resources/breadcrumb_state_serialization_0.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "timestamp": "1970-01-01T00:00:00.000Z",
4 | "name": "hello world",
5 | "type": "manual",
6 | "metaData": {
7 | "direction": "left"
8 | }
9 | }
10 | ]
--------------------------------------------------------------------------------
/bugsnag-android-core/src/test/resources/com/bugsnag/android/internal/classes.dex:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bugsnag/bugsnag-android/984a528aae7101b3711d63932cd372568bcb1c1a/bugsnag-android-core/src/test/resources/com/bugsnag/android/internal/classes.dex
--------------------------------------------------------------------------------
/bugsnag-android-core/src/test/resources/com/bugsnag/android/internal/empty-app-debug.apk:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bugsnag/bugsnag-android/984a528aae7101b3711d63932cd372568bcb1c1a/bugsnag-android-core/src/test/resources/com/bugsnag/android/internal/empty-app-debug.apk
--------------------------------------------------------------------------------
/bugsnag-android-core/src/test/resources/device_data_serialization_0.json:
--------------------------------------------------------------------------------
1 | {
2 | "cpuAbi": [
3 | "armeabi-v7a"
4 | ],
5 | "jailbroken": false,
6 | "id": "123",
7 | "locale": "en_GB",
8 | "manufacturer": "samsung",
9 | "model": "s7",
10 | "osName": "android",
11 | "osVersion": "7.1",
12 | "runtimeVersions": {
13 | "androidApiLevel": "24",
14 | "osBuild": "bulldog"
15 | },
16 | "totalMemory": 502934020442
17 | }
--------------------------------------------------------------------------------
/bugsnag-android-core/src/test/resources/device_data_serialization_1.json:
--------------------------------------------------------------------------------
1 | {
2 | "cpuAbi": [
3 | "armeabi-v7a"
4 | ],
5 | "jailbroken": false,
6 | "id": "123",
7 | "locale": "en_GB",
8 | "manufacturer": "samsung",
9 | "model": "s7",
10 | "osName": "android",
11 | "osVersion": "7.1",
12 | "runtimeVersions": {
13 | "androidApiLevel": "24",
14 | "osBuild": "bulldog"
15 | },
16 | "totalMemory": 502934020442,
17 | "freeDisk": 120935100007,
18 | "freeMemory": 2234092234234,
19 | "orientation": "landscape",
20 | "time": "1970-01-01T00:00:00.000Z"
21 | }
--------------------------------------------------------------------------------
/bugsnag-android-core/src/test/resources/device_metadata_serialization_0.json:
--------------------------------------------------------------------------------
1 | {
2 | "locationStatus": "disallowed",
3 | "emulator": false,
4 | "networkAccess": "unknown",
5 | "screenDensity": 200.0,
6 | "dpi": 120,
7 | "screenResolution": "0x0",
8 | "brand": "google"
9 | }
10 |
--------------------------------------------------------------------------------
/bugsnag-android-core/src/test/resources/error_serialization_0.json:
--------------------------------------------------------------------------------
1 | {
2 | "errorClass": "foo",
3 | "message": "bar",
4 | "type": "android",
5 | "stacktrace": []
6 | }
7 |
--------------------------------------------------------------------------------
/bugsnag-android-core/src/test/resources/error_serialization_1.json:
--------------------------------------------------------------------------------
1 | {
2 | "errorClass": "foo",
3 | "message": "bar",
4 | "type": "android",
5 | "stacktrace": [
6 | {
7 | "method": "foo()",
8 | "file": "Bar.kt",
9 | "lineNumber": 55,
10 | "inProject": true,
11 | "columnNumber": 99,
12 | "code": {
13 | "54": "invoke()"
14 | }
15 | }
16 | ]
17 | }
18 |
--------------------------------------------------------------------------------
/bugsnag-android-core/src/test/resources/error_serialization_2.json:
--------------------------------------------------------------------------------
1 | {
2 | "errorClass": "com.bugsnag.android.StacktraceSerializationTest",
3 | "message": "bar",
4 | "type": "android",
5 | "stacktrace": [
6 | {
7 | "method": "com.bugsnag.android.StacktraceSerializationTest$Companion.inProject",
8 | "file": "StacktraceSerializationTest.kt",
9 | "lineNumber": 47,
10 | "inProject": true
11 | },
12 | {
13 | "method": "com.bugsnag.android.StacktraceSerializationTest$Companion.testCases",
14 | "file": "StacktraceSerializationTest.kt",
15 | "lineNumber": 31,
16 | "inProject": true
17 | }
18 | ]
19 | }
20 |
--------------------------------------------------------------------------------
/bugsnag-android-core/src/test/resources/feature_flags_serialization_0.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "featureFlag": "sample_group",
4 | "variant": "a"
5 | },
6 | {
7 | "featureFlag": "demo_mode"
8 | },
9 | {
10 | "featureFlag": "view_mode",
11 | "variant": "modern"
12 | }
13 | ]
14 |
--------------------------------------------------------------------------------
/bugsnag-android-core/src/test/resources/feature_flags_serialization_1.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "featureFlag": "sample_group",
4 | "variant": "b"
5 | },
6 | {
7 | "featureFlag": "demo_mode"
8 | }
9 | ]
10 |
--------------------------------------------------------------------------------
/bugsnag-android-core/src/test/resources/feature_flags_serialization_2.json:
--------------------------------------------------------------------------------
1 | []
--------------------------------------------------------------------------------
/bugsnag-android-core/src/test/resources/json_stream.json:
--------------------------------------------------------------------------------
1 | {
2 | "bool": true,
3 | "string": "string",
4 | "int": 123,
5 | "long": 123,
6 | "float": 123.45,
7 | "streamable": {
8 | "timestamp": "1970-01-01T00:00:00.000Z",
9 | "name": "whoops",
10 | "type": "log",
11 | "metaData": {}
12 | },
13 | "map": {
14 | "Baz": "What"
15 | },
16 | "collection": [
17 | "bar"
18 | ],
19 | "array": [
20 | "foo"
21 | ],
22 | "object": "[OBJECT]"
23 | }
24 |
--------------------------------------------------------------------------------
/bugsnag-android-core/src/test/resources/meta_data_serialization_0.json:
--------------------------------------------------------------------------------
1 | {}
--------------------------------------------------------------------------------
/bugsnag-android-core/src/test/resources/meta_data_serialization_1.json:
--------------------------------------------------------------------------------
1 | {
2 | "example": {
3 | "boolean": true,
4 | "string": "value",
5 | "array": [
6 | "a",
7 | "b"
8 | ],
9 | "double": 123.45,
10 | "integer": 123,
11 | "collection": [
12 | "Hello",
13 | "World"
14 | ],
15 | "map": {
16 | "key": "value"
17 | }
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/bugsnag-android-core/src/test/resources/meta_data_serialization_2.json:
--------------------------------------------------------------------------------
1 | {
2 | "example": {
3 | "map": {
4 | "key": {
5 | "key": "value"
6 | }
7 | }
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/bugsnag-android-core/src/test/resources/meta_data_serialization_3.json:
--------------------------------------------------------------------------------
1 | {
2 | "example": {
3 | "list": [
4 | [
5 | "james",
6 | "test"
7 | ]
8 | ]
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/bugsnag-android-core/src/test/resources/meta_data_serialization_4.json:
--------------------------------------------------------------------------------
1 | {}
--------------------------------------------------------------------------------
/bugsnag-android-core/src/test/resources/metadata_redaction_0.json:
--------------------------------------------------------------------------------
1 | {
2 | "example": {
3 | "normal": "safe",
4 | "password": "[REDACTED]",
5 | "confirm_password": "[REDACTED]"
6 | }
7 | }
--------------------------------------------------------------------------------
/bugsnag-android-core/src/test/resources/metadata_redaction_1.json:
--------------------------------------------------------------------------------
1 | {
2 | "example": {
3 | "sensitiveMap": {
4 | "normal": "safe",
5 | "password": "[REDACTED]",
6 | "confirm_password": "[REDACTED]"
7 | }
8 | }
9 | }
--------------------------------------------------------------------------------
/bugsnag-android-core/src/test/resources/metadata_redaction_2.json:
--------------------------------------------------------------------------------
1 | {
2 | "foo": {
3 | "password": "[REDACTED]"
4 | }
5 | }
--------------------------------------------------------------------------------
/bugsnag-android-core/src/test/resources/metadata_redaction_3.json:
--------------------------------------------------------------------------------
1 | {}
--------------------------------------------------------------------------------
/bugsnag-android-core/src/test/resources/metadata_redaction_4.json:
--------------------------------------------------------------------------------
1 | {
2 | "foo": {
3 | "bar": "[REDACTED]",
4 | "password": "abc123"
5 | }
6 | }
--------------------------------------------------------------------------------
/bugsnag-android-core/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker:
--------------------------------------------------------------------------------
1 | mock-maker-inline
--------------------------------------------------------------------------------
/bugsnag-android-core/src/test/resources/native_stackframe_serialization_0.json:
--------------------------------------------------------------------------------
1 | {
2 | "method": "aMethod",
3 | "file": "aFile",
4 | "lineNumber": 1,
5 | "frameAddress": "0x2",
6 | "symbolAddress": "0x3",
7 | "loadAddress": "0x4",
8 | "isPC": true,
9 | "type": "c"
10 | }
11 |
--------------------------------------------------------------------------------
/bugsnag-android-core/src/test/resources/native_stackframe_serialization_1.json:
--------------------------------------------------------------------------------
1 | {
2 | "method": "aMethod",
3 | "file": "aFile",
4 | "lineNumber": 1
5 | }
6 |
--------------------------------------------------------------------------------
/bugsnag-android-core/src/test/resources/native_stackframe_serialization_2.json:
--------------------------------------------------------------------------------
1 | {
2 | "type": "android"
3 | }
4 |
--------------------------------------------------------------------------------
/bugsnag-android-core/src/test/resources/notifier_serialization_0.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "AndroidBugsnagNotifier",
3 | "version": "9.9.9",
4 | "url": "https://bugsnag.com"
5 | }
6 |
--------------------------------------------------------------------------------
/bugsnag-android-core/src/test/resources/notifier_serialization_1.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "CustomNotifier",
3 | "version": "4.5.6",
4 | "url": "https://example.com",
5 | "dependencies": [
6 | {
7 | "name": "AndroidBugsnagNotifier",
8 | "version": "9.9.9",
9 | "url": "https://bugsnag.com"
10 | }
11 | ]
12 | }
13 |
--------------------------------------------------------------------------------
/bugsnag-android-core/src/test/resources/null_json_stream.json:
--------------------------------------------------------------------------------
1 | {}
2 |
--------------------------------------------------------------------------------
/bugsnag-android-core/src/test/resources/report_serialization_0.json:
--------------------------------------------------------------------------------
1 | {
2 | "apiKey": "api-key",
3 | "payloadVersion": "4.0",
4 | "notifier": {
5 | "name": "AndroidBugsnagNotifier",
6 | "version": "9.9.9",
7 | "url": "https://bugsnag.com"
8 | },
9 | "events": []
10 | }
11 |
--------------------------------------------------------------------------------
/bugsnag-android-core/src/test/resources/session_serialization_0.json:
--------------------------------------------------------------------------------
1 | {
2 | "notifier": {
3 | "name": "AndroidBugsnagNotifier",
4 | "version": "9.9.9",
5 | "url": "https://bugsnag.com"
6 | },
7 | "app": {
8 | "type": "android",
9 | "versionCode": 0
10 | },
11 | "device": {
12 | "cpuAbi": [],
13 | "manufacturer": "samsung",
14 | "model": "s7",
15 | "osName": "android",
16 | "osVersion": "7.1",
17 | "runtimeVersions": {
18 | "osBuild": "bulldog",
19 | "androidApiLevel": "24"
20 | },
21 | "totalMemory": 10923250000
22 | },
23 | "sessions": [
24 | {
25 | "id": "123",
26 | "startedAt": "1970-01-01T00:00:00.000Z",
27 | "user": {}
28 | }
29 | ]
30 | }
--------------------------------------------------------------------------------
/bugsnag-android-core/src/test/resources/severity_reason_serialization_0.json:
--------------------------------------------------------------------------------
1 | {
2 | "type": "unhandledException",
3 | "unhandledOverridden": false
4 | }
5 |
--------------------------------------------------------------------------------
/bugsnag-android-core/src/test/resources/severity_reason_serialization_1.json:
--------------------------------------------------------------------------------
1 | {
2 | "type": "strictMode",
3 | "unhandledOverridden": false,
4 | "attributes": {
5 | "violationType": "diskRead"
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/bugsnag-android-core/src/test/resources/severity_reason_serialization_2.json:
--------------------------------------------------------------------------------
1 | {
2 | "type": "handledException",
3 | "unhandledOverridden": false
4 | }
--------------------------------------------------------------------------------
/bugsnag-android-core/src/test/resources/severity_reason_serialization_3.json:
--------------------------------------------------------------------------------
1 | {
2 | "type": "userSpecifiedSeverity",
3 | "unhandledOverridden": false
4 | }
5 |
--------------------------------------------------------------------------------
/bugsnag-android-core/src/test/resources/severity_reason_serialization_4.json:
--------------------------------------------------------------------------------
1 | {
2 | "type": "userCallbackSetSeverity",
3 | "unhandledOverridden": false
4 | }
5 |
--------------------------------------------------------------------------------
/bugsnag-android-core/src/test/resources/severity_reason_serialization_5.json:
--------------------------------------------------------------------------------
1 | {
2 | "type": "unhandledPromiseRejection",
3 | "unhandledOverridden": false
4 | }
5 |
--------------------------------------------------------------------------------
/bugsnag-android-core/src/test/resources/severity_reason_serialization_6.json:
--------------------------------------------------------------------------------
1 | {
2 | "type": "log",
3 | "unhandledOverridden": false,
4 | "attributes": {
5 | "level": "warning"
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/bugsnag-android-core/src/test/resources/severity_reason_serialization_7.json:
--------------------------------------------------------------------------------
1 | {
2 | "type": "anrError",
3 | "unhandledOverridden": false
4 | }
5 |
--------------------------------------------------------------------------------
/bugsnag-android-core/src/test/resources/severity_reason_serialization_8.json:
--------------------------------------------------------------------------------
1 | {
2 | "type": "handledException",
3 | "unhandledOverridden": true
4 | }
5 |
--------------------------------------------------------------------------------
/bugsnag-android-core/src/test/resources/severity_reason_serialization_9.json:
--------------------------------------------------------------------------------
1 | {
2 | "type": "handledError",
3 | "unhandledOverridden": false
4 | }
5 |
--------------------------------------------------------------------------------
/bugsnag-android-core/src/test/resources/severity_serialization_0.json:
--------------------------------------------------------------------------------
1 | "error"
--------------------------------------------------------------------------------
/bugsnag-android-core/src/test/resources/severity_serialization_1.json:
--------------------------------------------------------------------------------
1 | "warning"
--------------------------------------------------------------------------------
/bugsnag-android-core/src/test/resources/severity_serialization_2.json:
--------------------------------------------------------------------------------
1 | "info"
--------------------------------------------------------------------------------
/bugsnag-android-core/src/test/resources/stackframe_serialization_0.json:
--------------------------------------------------------------------------------
1 | {
2 | "method": "foo",
3 | "file": "Bar",
4 | "lineNumber": 55,
5 | "inProject": true,
6 | "type": "android"
7 | }
8 |
--------------------------------------------------------------------------------
/bugsnag-android-core/src/test/resources/stackframe_serialization_1.json:
--------------------------------------------------------------------------------
1 | {
2 | "method": "aMethod",
3 | "file": "aFile",
4 | "lineNumber": 1,
5 | "frameAddress": "0x2",
6 | "symbolAddress": "0x3",
7 | "loadAddress": "0x4",
8 | "type": "c"
9 | }
10 |
--------------------------------------------------------------------------------
/bugsnag-android-core/src/test/resources/stackframe_serialization_2.json:
--------------------------------------------------------------------------------
1 | {
2 | "method": "aMethod",
3 | "file": "aFile",
4 | "lineNumber": 1
5 | }
6 |
--------------------------------------------------------------------------------
/bugsnag-android-core/src/test/resources/stackframe_serialization_3.json:
--------------------------------------------------------------------------------
1 | {}
2 |
--------------------------------------------------------------------------------
/bugsnag-android-core/src/test/resources/stackframe_serialization_4.json:
--------------------------------------------------------------------------------
1 | {
2 | "method": "_kDartIsolateSnapshotInstructions",
3 | "codeIdentifier": "b6951c7f8ae5ea368e83b65d81ff5c91",
4 | "type": "dart"
5 | }
6 |
--------------------------------------------------------------------------------
/bugsnag-android-core/src/test/resources/stacktrace_serialization_0.json:
--------------------------------------------------------------------------------
1 | []
--------------------------------------------------------------------------------
/bugsnag-android-core/src/test/resources/stacktrace_serialization_1.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "method": "foo()",
4 | "file": "Bar.kt",
5 | "lineNumber": 55,
6 | "inProject": true,
7 | "columnNumber": 99,
8 | "code": {
9 | "54": "invoke()"
10 | }
11 | }
12 | ]
13 |
--------------------------------------------------------------------------------
/bugsnag-android-core/src/test/resources/stacktrace_serialization_2.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "method": "com.bugsnag.android.StacktraceSerializationTest$Companion.basic",
4 | "file": "StacktraceSerializationTest.kt",
5 | "lineNumber": 41
6 | },
7 | {
8 | "method": "com.bugsnag.android.StacktraceSerializationTest$Companion.testCases",
9 | "file": "StacktraceSerializationTest.kt",
10 | "lineNumber": 28
11 | }
12 | ]
--------------------------------------------------------------------------------
/bugsnag-android-core/src/test/resources/stacktrace_serialization_3.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "method": "com.bugsnag.android.StacktraceSerializationTest$Companion.inProject",
4 | "file": "StacktraceSerializationTest.kt",
5 | "lineNumber": 47,
6 | "inProject": true
7 | },
8 | {
9 | "method": "com.bugsnag.android.StacktraceSerializationTest$Companion.testCases",
10 | "file": "StacktraceSerializationTest.kt",
11 | "lineNumber": 31,
12 | "inProject": true
13 | }
14 | ]
--------------------------------------------------------------------------------
/bugsnag-android-core/src/test/resources/thread_deserialization_0.json:
--------------------------------------------------------------------------------
1 | {
2 | "id": "riker",
3 | "name": "will.riker",
4 | "type": "c"
5 | }
--------------------------------------------------------------------------------
/bugsnag-android-core/src/test/resources/thread_deserialization_1.json:
--------------------------------------------------------------------------------
1 | {
2 | "id": 321,
3 | "name": "mayne",
4 | "type": "android"
5 | }
--------------------------------------------------------------------------------
/bugsnag-android-core/src/test/resources/thread_deserialization_2.json:
--------------------------------------------------------------------------------
1 | {
2 | "id": "1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679821480865132823066470938446095505822317253594081284811174502841027019385211055596446229489549303819644288109756659334461284756482337867831652712019091456485669234603486104543266482",
3 | "name": "smoke signal handler",
4 | "type": "android",
5 | "state": "happy"
6 | }
--------------------------------------------------------------------------------
/bugsnag-android-core/src/test/resources/thread_serialization_0.json:
--------------------------------------------------------------------------------
1 | {
2 | "id": "24",
3 | "name": "main-one",
4 | "type": "android",
5 | "state": "RUNNABLE",
6 | "stacktrace": [
7 | {
8 | "method": "run_func",
9 | "file": "librunner.so",
10 | "lineNumber": 5038
11 | },
12 | {
13 | "method": "Runner.runFunc",
14 | "file": "Runner.java",
15 | "lineNumber": 14
16 | },
17 | {
18 | "method": "App.launch",
19 | "file": "App.java",
20 | "lineNumber": 70
21 | }
22 | ],
23 | "errorReportingThread": true
24 | }
25 |
--------------------------------------------------------------------------------
/bugsnag-android-core/src/test/resources/thread_serialization_1.json:
--------------------------------------------------------------------------------
1 | {
2 | "id": "24",
3 | "name": "main-one",
4 | "type": "android",
5 | "state": "RUNNABLE",
6 | "stacktrace": [
7 | {
8 | "method": "run_func",
9 | "file": "librunner.so",
10 | "lineNumber": 5038
11 | },
12 | {
13 | "method": "Runner.runFunc",
14 | "file": "Runner.java",
15 | "lineNumber": 14
16 | },
17 | {
18 | "method": "App.launch",
19 | "file": "App.java",
20 | "lineNumber": 70
21 | }
22 | ]
23 | }
24 |
--------------------------------------------------------------------------------
/bugsnag-android-core/src/test/resources/thread_serialization_2.json:
--------------------------------------------------------------------------------
1 | {
2 | "id": "24",
3 | "name": "main-one",
4 | "type": "android",
5 | "state": "RUNNABLE",
6 | "stacktrace": [
7 | {
8 | "method": "run_func",
9 | "file": "librunner.so",
10 | "lineNumber": 5038
11 | },
12 | {
13 | "method": "Runner.runFunc",
14 | "file": "Runner.java",
15 | "lineNumber": 14
16 | },
17 | {
18 | "method": "App.launch",
19 | "file": "App.java",
20 | "lineNumber": 70
21 | }
22 | ],
23 | "errorReportingThread": true
24 | }
25 |
--------------------------------------------------------------------------------
/bugsnag-android-core/src/test/resources/thread_serialization_3.json:
--------------------------------------------------------------------------------
1 | {
2 | "id": "24",
3 | "name": "main-one",
4 | "type": "android",
5 | "state": "RUNNABLE",
6 | "stacktrace": [
7 | {
8 | "method": "run_func",
9 | "file": "librunner.so",
10 | "lineNumber": 5038
11 | },
12 | {
13 | "method": "Runner.runFunc",
14 | "file": "Runner.java",
15 | "lineNumber": 14
16 | },
17 | {
18 | "method": "App.launch",
19 | "file": "App.java",
20 | "lineNumber": 70
21 | }
22 | ]
23 | }
24 |
--------------------------------------------------------------------------------
/bugsnag-android-core/src/test/resources/user_serialization_0.json:
--------------------------------------------------------------------------------
1 | {
2 | "id": "123",
3 | "email": "bob@example.com",
4 | "name": "bob smith"
5 | }
6 |
--------------------------------------------------------------------------------
/bugsnag-android/README.md:
--------------------------------------------------------------------------------
1 | # bugsnag-android
2 |
3 | This module is a meta package which contains no code itself. Its primary purpose is to
4 | publish an AAR + POM that adds a dependency on _all_ the bugsnag-android-* artefacts. This allows
5 | users to include bugsnag-android in their applications using the following syntax:
6 |
7 | ```
8 | implementation "com.bugsnag:bugsnag-android:$version"
9 | ```
10 |
11 | Which is simpler than manually specifying every single dependency:
12 |
13 | ```
14 | implementation "com.bugsnag:bugsnag-android-core:$version"
15 | implementation "com.bugsnag:bugsnag-plugin-android-ndk:$version"
16 | implementation "com.bugsnag:bugsnag-plugin-android-anr:$version"
17 | ```
18 |
--------------------------------------------------------------------------------
/bugsnag-android/build.gradle.kts:
--------------------------------------------------------------------------------
1 | plugins {
2 | load(Versions.Plugins.AGP)
3 | load(Versions.Plugins.licenseCheck)
4 | }
5 |
6 | android {
7 | compileSdk = Versions.Android.Build.compileSdkVersion
8 | namespace = "com.bugsnag.android"
9 |
10 | defaultConfig {
11 | minSdk = Versions.Android.Build.minSdkVersion
12 | ndkVersion = Versions.Android.Build.ndk
13 | }
14 | }
15 |
16 | dependencies {
17 | add("api", project(":bugsnag-android-core"))
18 | add("api", project(":bugsnag-plugin-android-anr"))
19 | add("api", project(":bugsnag-plugin-android-ndk"))
20 | }
21 |
22 | apply(from = rootProject.file("gradle/license-check.gradle"))
23 | apply(from = rootProject.file("gradle/release.gradle"))
24 |
--------------------------------------------------------------------------------
/bugsnag-android/gradle.properties:
--------------------------------------------------------------------------------
1 | pomName=Bugsnag Android
2 | artefactId=bugsnag-android
3 |
--------------------------------------------------------------------------------
/bugsnag-android/lint-baseline.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/bugsnag-android/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/bugsnag-benchmarks/src/androidTest/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
12 |
16 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/bugsnag-benchmarks/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/bugsnag-plugin-android-anr/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 3.19)
2 | project(bugsnag-plugin-android-anr)
3 | add_subdirectory(src/main)
4 |
--------------------------------------------------------------------------------
/bugsnag-plugin-android-anr/README.md:
--------------------------------------------------------------------------------
1 | # bugsnag-plugin-android-anr
2 |
3 | This module detects ANRs and reports them to bugsnag.
4 |
5 | ## High-level Overview
6 |
7 | When an ANR dialog is shown SIGQUIT is raised. This module installs a SIGQUIT handler and sets a
8 | ByteBuffer that is continuously monitored from the JVM. When the JVM code detects a ByteBuffer has
9 | been modified, it generates a report of the ANR.
10 |
--------------------------------------------------------------------------------
/bugsnag-plugin-android-anr/api/bugsnag-plugin-android-anr.api:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bugsnag/bugsnag-android/984a528aae7101b3711d63932cd372568bcb1c1a/bugsnag-plugin-android-anr/api/bugsnag-plugin-android-anr.api
--------------------------------------------------------------------------------
/bugsnag-plugin-android-anr/detekt-baseline.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SwallowedException:AnrDetailsCollector.kt$AnrDetailsCollector$exc: RuntimeException
6 | SwallowedException:AnrPlugin.kt$AnrPlugin$exc: Throwable
7 | ThrowingExceptionsWithoutMessageOrCause:AnrPlugin.kt$AnrPlugin$RuntimeException()
8 | UnusedPrivateMember:AnrPlugin.kt$AnrPlugin$private fun notifyAnrDetected(nativeTrace: List<NativeStackframe>)
9 |
10 |
11 |
--------------------------------------------------------------------------------
/bugsnag-plugin-android-anr/gradle.properties:
--------------------------------------------------------------------------------
1 | pomName=Bugsnag Android ANR
2 | artefactId=bugsnag-plugin-android-anr
3 |
--------------------------------------------------------------------------------
/bugsnag-plugin-android-anr/lint-baseline.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/bugsnag-plugin-android-anr/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | -keepattributes LineNumberTable,SourceFile
2 | -keep class com.bugsnag.android.AnrPlugin { *; }
3 | -keep class com.bugsnag.android.ErrorType { *; }
4 |
--------------------------------------------------------------------------------
/bugsnag-plugin-android-anr/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/bugsnag-plugin-android-anr/src/main/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | set(BUGSNAG_VERSION 1.0.1)
2 | add_library( # Specifies the name of the library.
3 | bugsnag-plugin-android-anr
4 | # Sets the library as a shared library.
5 | SHARED
6 | # Provides a relative path to your source file(s).
7 | jni/anr_google.c
8 | jni/anr_handler.c
9 | jni/bugsnag_anr.c
10 | jni/utils/string.c
11 | )
12 |
13 | include_directories(jni)
14 |
15 | set(EXTRA_LINK_FLAGS "-Wl,-z,max-page-size=16384")
16 |
17 | target_link_libraries( # Specifies the target library.
18 | bugsnag-plugin-android-anr
19 | # Links the log library to the target library.
20 | log)
21 |
22 | set_target_properties(
23 | bugsnag-plugin-android-anr
24 | PROPERTIES
25 | COMPILE_OPTIONS -Werror -Wall -pedantic
26 | LINK_FLAGS "${EXTRA_LINK_FLAGS}"
27 | )
28 |
--------------------------------------------------------------------------------
/bugsnag-plugin-android-anr/src/main/jni/bsg_unwind.h:
--------------------------------------------------------------------------------
1 | #ifndef BSG_UNWIND_H
2 | #define BSG_UNWIND_H
3 |
4 | #include "include/event.h"
5 |
6 | // These are isolated because the ANR plugin symlinks to this file and to
7 | // ../assets/include/event.h
8 |
9 | #ifndef BUGSNAG_FRAMES_MAX
10 | /**
11 | * Number of frames in a stacktrace. Configures a default if not defined.
12 | */
13 | #define BUGSNAG_FRAMES_MAX 192
14 | #endif
15 |
16 | #endif
17 |
--------------------------------------------------------------------------------
/bugsnag-plugin-android-anr/src/main/jni/bugsnag_anr.c:
--------------------------------------------------------------------------------
1 | #include "anr_handler.h"
2 | #include "unwind_func.h"
3 | #include
4 | #include
5 |
6 | #ifdef __cplusplus
7 | extern "C" {
8 | #endif
9 |
10 | JNIEXPORT void JNICALL Java_com_bugsnag_android_AnrPlugin_enableAnrReporting(
11 | JNIEnv *env, jobject _this) {
12 | bsg_handler_install_anr(env, _this);
13 | }
14 |
15 | JNIEXPORT void JNICALL Java_com_bugsnag_android_AnrPlugin_disableAnrReporting(
16 | JNIEnv *env, jobject _this) {
17 | bsg_handler_uninstall_anr();
18 | }
19 |
20 | JNIEXPORT void JNICALL Java_com_bugsnag_android_AnrPlugin_setUnwindFunction(
21 | JNIEnv *env, jobject thiz, jlong unwind_function) {
22 | bsg_set_unwind_function((unwind_func)unwind_function);
23 | }
24 |
25 | #ifdef __cplusplus
26 | }
27 | #endif
28 |
--------------------------------------------------------------------------------
/bugsnag-plugin-android-anr/src/main/jni/include/event.h:
--------------------------------------------------------------------------------
1 | ../../../../../bugsnag-plugin-android-ndk/src/main/jni/include/event.h
--------------------------------------------------------------------------------
/bugsnag-plugin-android-anr/src/main/jni/unwind_func.h:
--------------------------------------------------------------------------------
1 | #ifndef UNWIND_FUNC_H
2 | #define UNWIND_FUNC_H
3 |
4 | #include "bsg_unwind.h"
5 | #include
6 | #include
7 |
8 | #ifdef __cplusplus
9 | extern "C" {
10 | #endif
11 |
12 | typedef ssize_t (*unwind_func)(
13 | bugsnag_stackframe stacktrace[BUGSNAG_FRAMES_MAX], siginfo_t *info,
14 | void *user_context);
15 |
16 | #ifdef __cplusplus
17 | }
18 | #endif
19 | #endif
20 |
--------------------------------------------------------------------------------
/bugsnag-plugin-android-anr/src/main/jni/utils/string.c:
--------------------------------------------------------------------------------
1 | #include "string.h"
2 |
3 | void bsg_strncpy(char *dst, char *src, size_t len) {
4 | int i = 0;
5 | while (i <= len) {
6 | char current = src[i];
7 | dst[i] = current;
8 | if (current == '\0') {
9 | break;
10 | }
11 | i++;
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/bugsnag-plugin-android-anr/src/main/jni/utils/string.h:
--------------------------------------------------------------------------------
1 | #ifndef BUGSNAG_UTILS_STRING_H
2 | #define BUGSNAG_UTILS_STRING_H
3 |
4 | #ifdef __cplusplus
5 | extern "C" {
6 | #endif
7 |
8 | #include
9 |
10 | /**
11 | * Copy the contents of src to dst where src is null-terminated
12 | */
13 | void bsg_strncpy(char *dst, char *src, size_t len);
14 |
15 | #ifdef __cplusplus
16 | }
17 | #endif
18 | #endif
19 |
--------------------------------------------------------------------------------
/bugsnag-plugin-android-exitinfo/README.md:
--------------------------------------------------------------------------------
1 | # bugsnag-plugin-android-exitinfo
2 |
3 | This module enhances your crash reports on Android 11+ devices by merging data captured in
4 | the [ApplicationExitInfo](https://developer.android.com/reference/android/app/ApplicationExitInfo).
5 |
6 | ## High-level Overview
7 |
8 | This module correlates `ApplicationExitInfo` traces and tombstones with reports being sent by
9 | bugsnag-android-core, and augments the existing error reports with information extracted from
10 | these files (such as the full stack-traces from all threads in native crashes).
--------------------------------------------------------------------------------
/bugsnag-plugin-android-exitinfo/gradle.properties:
--------------------------------------------------------------------------------
1 | pomName=Bugsnag Android ExitInfo
2 | artefactId=bugsnag-plugin-android-exitinfo
3 |
--------------------------------------------------------------------------------
/bugsnag-plugin-android-exitinfo/lint-baseline.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/bugsnag-plugin-android-exitinfo/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | -keep class com.bugsnag.android.repackaged.server.os.* extends com.google.protobuf.GeneratedMessageLite { *; }
--------------------------------------------------------------------------------
/bugsnag-plugin-android-exitinfo/src/androidTest/java/com/bugsnag/android/TestHooks.java:
--------------------------------------------------------------------------------
1 | package com.bugsnag.android;
2 |
3 | import com.bugsnag.android.internal.ImmutableConfig;
4 | import com.bugsnag.android.internal.ImmutableConfigKt;
5 |
6 | import androidx.annotation.NonNull;
7 |
8 | public class TestHooks {
9 | private TestHooks() {
10 | }
11 |
12 | public static ImmutableConfig convertToImmutableConfig(
13 | @NonNull Configuration configuration
14 | ) {
15 | return ImmutableConfigKt.convertToImmutableConfig(configuration);
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/bugsnag-plugin-android-exitinfo/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/bugsnag-plugin-android-exitinfo/src/main/java/com/bugsnag/android/ExitInfoKey.kt:
--------------------------------------------------------------------------------
1 | package com.bugsnag.android
2 |
3 | import android.app.ApplicationExitInfo
4 | import android.os.Build
5 | import androidx.annotation.RequiresApi
6 |
7 | internal data class ExitInfoKey(val pid: Int, val timestamp: Long) : JsonStream.Streamable {
8 | @RequiresApi(Build.VERSION_CODES.R)
9 | constructor(exitInfo: ApplicationExitInfo) :
10 | this(exitInfo.pid, exitInfo.timestamp)
11 |
12 | override fun toStream(stream: JsonStream) {
13 | stream.beginObject()
14 | .name("pid").value(pid)
15 | .name("timestamp").value(timestamp.toString())
16 | .endObject()
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/bugsnag-plugin-android-exitinfo/src/test/resources/tombstone_01.pb:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bugsnag/bugsnag-android/984a528aae7101b3711d63932cd372568bcb1c1a/bugsnag-plugin-android-exitinfo/src/test/resources/tombstone_01.pb
--------------------------------------------------------------------------------
/bugsnag-plugin-android-ndk/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 3.19)
2 | project(bugsnag-plugin-android-ndk)
3 | project(TEST)
4 | add_subdirectory(src/main)
5 |
6 | if(${CMAKE_BUILD_TYPE} STREQUAL Debug)
7 | enable_testing()
8 | add_subdirectory(src/test)
9 | endif()
10 |
--------------------------------------------------------------------------------
/bugsnag-plugin-android-ndk/detekt-baseline.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CyclomaticComplexMethod:NativeBridge.kt$NativeBridge$override fun onStateChange(event: StateEvent)
6 | LongParameterList:NativeBridge.kt$NativeBridge$( apiKey: String, reportingDirectory: String, lastRunInfoPath: String, eventUUID: String, consecutiveLaunchCrashes: Int, autoDetectNdkCrashes: Boolean, apiLevel: Int, is32bit: Boolean, threadSendPolicy: Int, maxBreadcrumbs: Int, )
7 | SwallowedException:ReportDiscardScanner.kt$ReportDiscardScanner$ex: Exception
8 | TooManyFunctions:NativeBridge.kt$NativeBridge : StateObserver
9 | UseCheckOrError:ResourceUtils.kt$throw IllegalStateException("Failed to read JSON from $resourceName")
10 |
11 |
12 |
--------------------------------------------------------------------------------
/bugsnag-plugin-android-ndk/gradle.properties:
--------------------------------------------------------------------------------
1 | pomName=Bugsnag Android NDK
2 | artefactId=bugsnag-plugin-android-ndk
3 |
--------------------------------------------------------------------------------
/bugsnag-plugin-android-ndk/lint-baseline.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/bugsnag-plugin-android-ndk/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "development": {
3 | "silentbicycle/greatest": "v1.2.1"
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/bugsnag-plugin-android-ndk/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | -keepattributes LineNumberTable,SourceFile
2 | -keep class com.bugsnag.android.ndk.OpaqueValue {
3 | java.lang.String getJson();
4 | static java.lang.Object makeSafe(java.lang.Object);
5 | }
6 | -keep class com.bugsnag.android.ndk.NativeBridge { *; }
7 | -keep class com.bugsnag.android.NdkPlugin { *; }
8 |
--------------------------------------------------------------------------------
/bugsnag-plugin-android-ndk/src/androidTest/java/com/bugsnag/android/ndk/NativeBreadcrumbTest.kt:
--------------------------------------------------------------------------------
1 | package com.bugsnag.android.ndk
2 |
3 | import org.junit.Test
4 |
5 | class NativeBreadcrumbTest {
6 |
7 | companion object {
8 | init {
9 | System.loadLibrary("bugsnag-ndk")
10 | System.loadLibrary("bugsnag-ndk-test")
11 | }
12 | }
13 |
14 | external fun run(): Int
15 |
16 | @Test
17 | fun testPassesNativeSuite() {
18 | verifyNativeRun(run())
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/bugsnag-plugin-android-ndk/src/androidTest/java/com/bugsnag/android/ndk/NativeEventAppMutatorsTest.kt:
--------------------------------------------------------------------------------
1 | package com.bugsnag.android.ndk
2 |
3 | import org.junit.Test
4 |
5 | class NativeEventAppMutatorsTest {
6 |
7 | companion object {
8 | init {
9 | System.loadLibrary("bugsnag-ndk")
10 | System.loadLibrary("bugsnag-ndk-test")
11 | }
12 | }
13 |
14 | external fun run(): Int
15 |
16 | @Test
17 | fun testPassesNativeSuite() {
18 | verifyNativeRun(run())
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/bugsnag-plugin-android-ndk/src/androidTest/java/com/bugsnag/android/ndk/NativeEventDeviceMutatorsTest.kt:
--------------------------------------------------------------------------------
1 | package com.bugsnag.android.ndk
2 |
3 | import org.junit.Test
4 |
5 | class NativeEventDeviceMutatorsTest {
6 |
7 | companion object {
8 | init {
9 | System.loadLibrary("bugsnag-ndk")
10 | System.loadLibrary("bugsnag-ndk-test")
11 | }
12 | }
13 |
14 | external fun run(): Int
15 |
16 | @Test
17 | fun testPassesNativeSuite() {
18 | verifyNativeRun(run())
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/bugsnag-plugin-android-ndk/src/androidTest/java/com/bugsnag/android/ndk/NativeEventMutatorsTest.kt:
--------------------------------------------------------------------------------
1 | package com.bugsnag.android.ndk
2 |
3 | import org.junit.Test
4 |
5 | class NativeEventMutatorsTest {
6 |
7 | companion object {
8 | init {
9 | System.loadLibrary("bugsnag-ndk")
10 | System.loadLibrary("bugsnag-ndk-test")
11 | }
12 | }
13 |
14 | external fun run(): Int
15 |
16 | @Test
17 | fun testPassesNativeSuite() {
18 | verifyNativeRun(run())
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/bugsnag-plugin-android-ndk/src/androidTest/java/com/bugsnag/android/ndk/NativeFeatureFlagsTest.kt:
--------------------------------------------------------------------------------
1 | package com.bugsnag.android.ndk
2 |
3 | import org.junit.Test
4 |
5 | class NativeFeatureFlagsTest {
6 | companion object {
7 | init {
8 | System.loadLibrary("bugsnag-ndk")
9 | System.loadLibrary("bugsnag-ndk-test")
10 | }
11 | }
12 |
13 | external fun run(): Int
14 |
15 | @Test
16 | fun testPassesNativeSuite() {
17 | verifyNativeRun(run())
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/bugsnag-plugin-android-ndk/src/androidTest/java/com/bugsnag/android/ndk/NativeStringTest.kt:
--------------------------------------------------------------------------------
1 | package com.bugsnag.android.ndk
2 |
3 | import org.junit.Test
4 |
5 | class NativeStringTest {
6 |
7 | companion object {
8 | init {
9 | System.loadLibrary("bugsnag-ndk")
10 | System.loadLibrary("bugsnag-ndk-test")
11 | }
12 | }
13 |
14 | external fun run(): Int
15 |
16 | @Test
17 | fun testPassesNativeSuite() {
18 | verifyNativeRun(run())
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/bugsnag-plugin-android-ndk/src/androidTest/java/com/bugsnag/android/ndk/ResourceUtils.kt:
--------------------------------------------------------------------------------
1 | package com.bugsnag.android.ndk
2 |
3 | internal fun loadJson(resourceName: String): String {
4 | val classLoader = requireNotNull(NativeJsonSerializeTest::class.java.classLoader)
5 | val resource = classLoader.getResource(resourceName)
6 | ?: throw IllegalArgumentException("Could not find $resourceName")
7 | val json = resource.readText()
8 | if (json.isEmpty()) {
9 | throw IllegalStateException("Failed to read JSON from $resourceName")
10 | }
11 | return json
12 | }
13 |
--------------------------------------------------------------------------------
/bugsnag-plugin-android-ndk/src/androidTest/java/com/bugsnag/android/ndk/VerifyUtils.kt:
--------------------------------------------------------------------------------
1 | package com.bugsnag.android.ndk
2 |
3 | import java.lang.IllegalStateException
4 |
5 | internal fun verifyNativeRun(code: Int): Boolean {
6 | if (code != 0) {
7 | throw IllegalStateException(
8 | "Native test suite failed." +
9 | " Filter the device logs by 'BugsnagNDKTest' to get the results."
10 | )
11 | } else {
12 | return true
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/bugsnag-plugin-android-ndk/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/bugsnag-plugin-android-ndk/src/main/exported_native_symbols-Debug.txt:
--------------------------------------------------------------------------------
1 | LIBBUGSNAG_NDK {
2 | global:
3 | bugsnag_*;
4 | Java_*;
5 | bsg_*;
6 | json_*;
7 | BSG_MIGRATOR_CURRENT_VERSION;
8 | migrate_app_v2;
9 | __gxx_*;
10 | __cxa_*;
11 | local:
12 | *;
13 | };
14 |
--------------------------------------------------------------------------------
/bugsnag-plugin-android-ndk/src/main/exported_native_symbols-RelWithDebInfo.txt:
--------------------------------------------------------------------------------
1 | LIBBUGSNAG_NDK {
2 | global:
3 | bugsnag_*;
4 | __cxa_*;
5 | __dynamic_cast;
6 | __emutls_get_address;
7 | __gxx_personality_v0;
8 | Java_*;
9 | extern "C++" {
10 | "std::get_terminate()";
11 | "std::set_terminate(void (*)())";
12 | "std::set_unexpected(void (*)())";
13 | "std::get_new_handler()";
14 | "std::set_new_handler(void (*)())";
15 | "std::rethrow_exception(std::exception_ptr)";
16 | "std::__throw_bad_alloc()";
17 | "std::uncaught_exception()";
18 | "std::uncaught_exceptions()";
19 | "std::nothrow";
20 | "std::terminate()";
21 | };
22 |
23 | local:
24 | *;
25 | };
26 |
--------------------------------------------------------------------------------
/bugsnag-plugin-android-ndk/src/main/java/com/bugsnag/android/ndk/BugsnagNDK.kt:
--------------------------------------------------------------------------------
1 | package com.bugsnag.android.ndk
2 |
3 | import com.bugsnag.android.Bugsnag
4 | import com.bugsnag.android.ndkPlugin
5 |
6 | object BugsnagNDK {
7 | @JvmStatic
8 | fun refreshSymbolTable() {
9 | if (Bugsnag.isStarted()) {
10 | val client = Bugsnag.getClient()
11 | client.ndkPlugin?.nativeBridge?.refreshSymbolTable()
12 | }
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/bugsnag-plugin-android-ndk/src/main/jni/bsg_unwind.h:
--------------------------------------------------------------------------------
1 | #ifndef BSG_UNWIND_H
2 | #define BSG_UNWIND_H
3 |
4 | #include "include/event.h"
5 |
6 | // These are isolated because the ANR plugin symlinks to this file and to
7 | // ../assets/include/event.h
8 |
9 | #ifndef BUGSNAG_FRAMES_MAX
10 | /**
11 | * Number of frames in a stacktrace. Configures a default if not defined.
12 | */
13 | #define BUGSNAG_FRAMES_MAX 192
14 | #endif
15 |
16 | #endif
17 |
--------------------------------------------------------------------------------
/bugsnag-plugin-android-ndk/src/main/jni/utils/build.h:
--------------------------------------------------------------------------------
1 | #ifndef BUGSNAG_ANDROID_BUILD_H
2 | #define BUGSNAG_ANDROID_BUILD_H
3 | #ifdef CLANG_ANALYZE_ASYNCSAFE
4 | #define __asyncsafe __attribute__((asyncsafe));
5 | #else
6 | #define __asyncsafe
7 | #endif
8 | #endif // BUGSNAG_ANDROID_BUILD_H
9 |
--------------------------------------------------------------------------------
/bugsnag-plugin-android-ndk/src/main/jni/utils/crash_info.h:
--------------------------------------------------------------------------------
1 | /**
2 | * Async-safe utilities for manipulating crash reports
3 | */
4 | #ifndef BUGSNAG_CRASH_INFO_H
5 | #define BUGSNAG_CRASH_INFO_H
6 |
7 | #include "../bugsnag_ndk.h"
8 | #include "build.h"
9 | #ifdef __cplusplus
10 | extern "C" {
11 | #endif
12 | /**
13 | * Add crash-time information to an event, respecting signal safety
14 | */
15 | void bsg_populate_event_as(bsg_environment *env) __asyncsafe;
16 |
17 | /**
18 | * Increment the handled/unhandled count on the bugsnag event.
19 | */
20 | void bsg_increment_unhandled_count(bugsnag_event *ptr);
21 |
22 | #ifdef __cplusplus
23 | }
24 | #endif
25 | #endif
26 |
--------------------------------------------------------------------------------
/bugsnag-plugin-android-ndk/src/main/jni/utils/logger.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include
3 |
4 | #ifndef BUGSNAG_LOG
5 | #define BUGSNAG_LOG(fmt, ...) \
6 | __android_log_print(ANDROID_LOG_WARN, "BugsnagNDK", fmt, ##__VA_ARGS__)
7 | #endif
8 |
--------------------------------------------------------------------------------
/bugsnag-plugin-android-ndk/src/main/jni/utils/memory.c:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | #include "memory.h"
4 |
5 | #ifdef __cplusplus
6 | extern "C" {
7 | #endif
8 |
9 | /**
10 | * Global shared context for Bugsnag reports
11 | */
12 | static bsg_environment *bsg_global_env;
13 |
14 | void bsg_init_memory(bsg_environment *env) { bsg_global_env = env; }
15 |
16 | void bsg_free(void *ptr) {
17 | /*
18 | * free is only "active" when there are no signal handlers active, if there is
19 | * a crash in progress the memory cannot be safely released within the process
20 | * (free is not async safe), and the heap will be released along with the rest
21 | * of the process when the crash is over.
22 | */
23 | if (bsg_global_env->handling_crash) {
24 | return;
25 | }
26 |
27 | free(ptr);
28 | }
29 |
30 | #ifdef __cplusplus
31 | }
32 | #endif
33 |
--------------------------------------------------------------------------------
/bugsnag-plugin-android-ndk/src/main/jni/utils/memory.h:
--------------------------------------------------------------------------------
1 | #ifndef BUGSNAG_ANDROID_MEMORY_H
2 | #define BUGSNAG_ANDROID_MEMORY_H
3 |
4 | #include "bugsnag_ndk.h"
5 |
6 | #ifdef __cplusplus
7 | extern "C" {
8 | #endif
9 |
10 | /**
11 | * Crash-safe 'free' that won't cause deadlocks if a signal handler is active.
12 | * @param ptr
13 | */
14 | void bsg_free(void *ptr);
15 |
16 | void bsg_init_memory(bsg_environment *env);
17 |
18 | #ifdef __cplusplus
19 | }
20 | #endif
21 |
22 | #endif // BUGSNAG_ANDROID_MEMORY_H
23 |
--------------------------------------------------------------------------------
/bugsnag-plugin-android-ndk/src/main/jni/utils/seqlock.h:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Jason Morris on 02/02/2023.
3 | //
4 |
5 | #ifndef BUGSNAG_ANDROID_SEQLOCK_H
6 | #define BUGSNAG_ANDROID_SEQLOCK_H
7 |
8 | #include
9 | #include
10 |
11 | #ifdef __cplusplus
12 | extern "C" {
13 | #endif
14 |
15 | typedef atomic_uint_fast64_t bsg_seqlock_t;
16 | typedef uint_fast64_t bsg_seqlock_status_t;
17 |
18 | void bsg_seqlock_init(bsg_seqlock_t *lock);
19 |
20 | void bsg_seqlock_acquire_write(bsg_seqlock_t *lock);
21 |
22 | void bsg_seqlock_release_write(bsg_seqlock_t *lock);
23 |
24 | bsg_seqlock_status_t bsg_seqlock_optimistic_read(bsg_seqlock_t *lock);
25 |
26 | bool bsg_seqlock_validate(bsg_seqlock_t *lock, bsg_seqlock_status_t expected);
27 |
28 | #define bsg_seqlock_is_write_locked(c) (((c) & 1uLL) != 0)
29 |
30 | #ifdef __cplusplus
31 | }
32 | #endif
33 |
34 | #endif // BUGSNAG_ANDROID_SEQLOCK_H
35 |
--------------------------------------------------------------------------------
/bugsnag-plugin-android-ndk/src/main/jni/utils/serializer.c:
--------------------------------------------------------------------------------
1 | #include "serializer.h"
2 | #include "serializer/event_writer.h"
3 |
4 | bool bsg_serialize_last_run_info_to_file(bsg_environment *env) {
5 | return bsg_lastrun_write(env);
6 | }
7 |
8 | bool bsg_serialize_event_to_file(bsg_environment *env) {
9 | return bsg_event_write(env);
10 | }
11 |
--------------------------------------------------------------------------------
/bugsnag-plugin-android-ndk/src/main/jni/utils/serializer.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include "../bugsnag_ndk.h"
3 | #include "build.h"
4 |
5 | #ifdef __cplusplus
6 | extern "C" {
7 | #endif
8 |
9 | char *bsg_serialize_event_to_json_string(bugsnag_event *event);
10 |
11 | bool bsg_serialize_event_to_file(bsg_environment *env) __asyncsafe;
12 |
13 | /**
14 | * Serializes the LastRunInfo to the file. This persists information about
15 | * why the current launch crashed, for use on future launch.
16 | */
17 | bool bsg_serialize_last_run_info_to_file(bsg_environment *env) __asyncsafe;
18 |
19 | #ifdef __cplusplus
20 | }
21 | #endif
22 |
--------------------------------------------------------------------------------
/bugsnag-plugin-android-ndk/src/main/jni/utils/serializer/event_writer.h:
--------------------------------------------------------------------------------
1 | /**
2 | * async-safe functions for writing an event to disk
3 | */
4 | #pragma once
5 | #include "../../bugsnag_ndk.h"
6 |
7 | bool bsg_event_write(bsg_environment *env) __asyncsafe;
8 |
9 | bool bsg_write_event_file(bsg_environment *env,
10 | const char *filename) __asyncsafe;
11 |
12 | bool bsg_lastrun_write(bsg_environment *env) __asyncsafe;
13 |
--------------------------------------------------------------------------------
/bugsnag-plugin-android-ndk/src/main/jni/utils/threads.h:
--------------------------------------------------------------------------------
1 | #ifndef BUGSNAG_THREADS_H
2 | #define BUGSNAG_THREADS_H
3 |
4 | #include "../event.h"
5 | #include "build.h"
6 |
7 | #ifdef __cplusplus
8 | extern "C" {
9 | #endif
10 |
11 | #define MAX_STAT_PATH_LENGTH 64
12 |
13 | size_t bsg_capture_thread_states(pid_t reporting_tid, bsg_thread *threads,
14 | size_t max_threads) __asyncsafe;
15 |
16 | #ifdef __cplusplus
17 | }
18 | #endif
19 | #endif // BUGSNAG_THREADS_H
20 |
--------------------------------------------------------------------------------
/bugsnag-plugin-android-ndk/src/test/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | include_directories(
2 | ../main/jni
3 | ../main/jni/deps
4 | cpp
5 | cpp/deps
6 | )
7 | add_library(bugsnag-ndk-test SHARED
8 | cpp/main.c
9 | cpp/test_utils_string.c
10 | cpp/test_utils_serialize.c
11 | cpp/test_serializer.c
12 | cpp/test_breadcrumbs.c
13 | cpp/test_bsg_event.c
14 | cpp/test_featureflags.c
15 | cpp/test_bsg_event.c
16 | cpp/UnwindTest.cpp
17 | cpp/parson/parson.h
18 | )
19 | target_link_libraries(bugsnag-ndk-test bugsnag-ndk)
20 |
--------------------------------------------------------------------------------
/bugsnag-plugin-android-ndk/src/test/cpp/deps/greatest/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "greatest",
3 | "version": "v1.2.1",
4 | "repo": "silentbicycle/greatest",
5 | "src": ["greatest.h"],
6 | "description": "A C testing library in 1 file. No dependencies, no dynamic allocation.",
7 | "license": "ISC",
8 | "keywords": ["test", "unit", "testing"]
9 | }
10 |
--------------------------------------------------------------------------------
/bugsnag-plugin-android-ndk/src/test/cpp/parson/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "parson",
3 | "version": "0.0.0",
4 | "repo": "kgabis/parson",
5 | "description": "Small json parser and reader",
6 | "keywords": [ "json", "parser" ],
7 | "license": "MIT",
8 | "src": [
9 | "parson.c",
10 | "parson.h"
11 | ]
12 | }
13 |
--------------------------------------------------------------------------------
/bugsnag-plugin-android-ndk/src/test/cpp/test_bsg_event.h:
--------------------------------------------------------------------------------
1 | #ifndef BUGSNAG_ANDROID_TEST_BSG_EVENT_H
2 | #define BUGSNAG_ANDROID_TEST_BSG_EVENT_H
3 |
4 | #include
5 |
6 | bugsnag_event *init_event();
7 |
8 | #endif // BUGSNAG_ANDROID_TEST_BSG_EVENT_H
9 |
--------------------------------------------------------------------------------
/bugsnag-plugin-android-okhttp/README.md:
--------------------------------------------------------------------------------
1 | # bugsnag-plugin-android-okhttp
2 |
3 | This module captures a breadcrumb for each network request made by OkHttp.
4 |
5 | ## High-level Overview
6 |
7 | The module has a `compileOnly` dependency on OkHttp 4 and implements the `Plugin` and `EventListener`
8 | interfaces. The user should install the plugin while initializing Bugsnag and creating an
9 | `OkHttpClient`, and OkHttp's callbacks will then be used to automatically capture breadcrumbs
10 | for each request.
11 |
--------------------------------------------------------------------------------
/bugsnag-plugin-android-okhttp/detekt-baseline.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | MagicNumber:BugsnagOkHttpPlugin.kt$100
6 | MagicNumber:BugsnagOkHttpPlugin.kt$399
7 | MagicNumber:BugsnagOkHttpPlugin.kt$400
8 | MagicNumber:BugsnagOkHttpPlugin.kt$599
9 |
10 |
11 |
--------------------------------------------------------------------------------
/bugsnag-plugin-android-okhttp/gradle.properties:
--------------------------------------------------------------------------------
1 | pomName=Bugsnag Android OkHttp
2 | artefactId=bugsnag-plugin-android-okhttp
3 |
--------------------------------------------------------------------------------
/bugsnag-plugin-android-okhttp/lint-baseline.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/bugsnag-plugin-android-okhttp/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | -keepattributes LineNumberTable,SourceFile
2 |
--------------------------------------------------------------------------------
/bugsnag-plugin-android-okhttp/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/bugsnag-plugin-android-okhttp/src/main/java/com/bugsnag/android/BreadcrumbHooks.kt:
--------------------------------------------------------------------------------
1 | package com.bugsnag.android
2 |
3 | internal fun Client.shouldDiscardNetworkBreadcrumb() = config.shouldDiscardBreadcrumb(BreadcrumbType.REQUEST)
4 |
--------------------------------------------------------------------------------
/bugsnag-plugin-react-native/README.md:
--------------------------------------------------------------------------------
1 | # bugsnag-plugin-react-native
2 |
3 | This module detects errors in React Native apps and reports them to bugsnag.
4 |
5 | ## High-level Overview
6 |
7 | This module depends on bugsnag-android-core, and implements a `BugsnagReactNativePlugin` which is
8 | added in the native layer using the `Plugin` interface. This class is intended to be the sole
9 | internal API which `BugsnagReactNative` in the `bugsnag-js` repository invokes.
10 |
11 | The responsibility of this module is to serialize information into a format that can be understood
12 | by the React Bridge, and to forward method calls onto the appropriate site from `bugsnag-js`.
13 |
14 | The responsibility of Android code in the `bugsnag-js` package is to implement any functionality
15 | that requires the React Native Android dependency. A minimal number of classes require this and
16 | by default code should be implemented in this module.
17 |
--------------------------------------------------------------------------------
/bugsnag-plugin-react-native/detekt-baseline.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/bugsnag-plugin-react-native/gradle.properties:
--------------------------------------------------------------------------------
1 | pomName=Bugsnag Android React Native
2 | artefactId=bugsnag-plugin-react-native
3 |
--------------------------------------------------------------------------------
/bugsnag-plugin-react-native/lint-baseline.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/bugsnag-plugin-react-native/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | -keepattributes LineNumberTable,SourceFile
2 | -keepnames class com.facebook.react.common.JavascriptException { *; }
3 | -keep class com.bugsnag.android.BugsnagReactNativePlugin { *; }
4 |
--------------------------------------------------------------------------------
/bugsnag-plugin-react-native/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/bugsnag-plugin-react-native/src/main/java/com/bugsnag/android/AppSerializer.kt:
--------------------------------------------------------------------------------
1 | package com.bugsnag.android
2 |
3 | internal class AppSerializer : MapSerializer {
4 | override fun serialize(map: MutableMap, app: AppWithState) {
5 | map["type"] = app.type
6 | map["binaryArch"] = app.binaryArch
7 | map["buildUuid"] = app.buildUuid
8 | map["codeBundleId"] = app.codeBundleId
9 | map["duration"] = app.duration
10 | map["durationInForeground"] = app.durationInForeground
11 | map["id"] = app.id
12 | map["inForeground"] = app.inForeground
13 | map["isLaunching"] = app.isLaunching
14 | map["releaseStage"] = app.releaseStage
15 | map["version"] = app.version
16 | map["versionCode"] = app.versionCode
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/bugsnag-plugin-react-native/src/main/java/com/bugsnag/android/BreadcrumbSerializer.kt:
--------------------------------------------------------------------------------
1 | package com.bugsnag.android
2 |
3 | import com.bugsnag.android.internal.DateUtils
4 |
5 | internal class BreadcrumbSerializer : MapSerializer {
6 | override fun serialize(map: MutableMap, crumb: Breadcrumb) {
7 | map["timestamp"] = DateUtils.toIso8601(crumb.timestamp)
8 | map["message"] = crumb.message
9 | map["type"] = crumb.type.toString().lowercase()
10 | map["metadata"] = crumb.metadata
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/bugsnag-plugin-react-native/src/main/java/com/bugsnag/android/MapDeserializer.java:
--------------------------------------------------------------------------------
1 | package com.bugsnag.android;
2 |
3 | import java.util.Map;
4 |
5 | interface MapDeserializer {
6 | T deserialize(Map map);
7 | }
8 |
--------------------------------------------------------------------------------
/bugsnag-plugin-react-native/src/main/java/com/bugsnag/android/MapSerializer.java:
--------------------------------------------------------------------------------
1 | package com.bugsnag.android;
2 |
3 | import java.util.Map;
4 |
5 | interface MapSerializer {
6 | void serialize(Map map, T obj);
7 | }
8 |
--------------------------------------------------------------------------------
/bugsnag-plugin-react-native/src/main/java/com/bugsnag/android/MessageEvent.kt:
--------------------------------------------------------------------------------
1 | package com.bugsnag.android
2 |
3 | /**
4 | * Holds information about a state change event which is serialized by the BugsnagReactNative
5 | * class and emitted to the JS layer.
6 | */
7 | class MessageEvent(
8 |
9 | /**
10 | * The type of the event. E.g. `UpdateContext`
11 | */
12 | val type: String,
13 |
14 | /**
15 | * The data which underwent a state change. For instance, if a user called
16 | * `Bugsnag.setContext()`, the new context value would be present in this field.
17 | */
18 | val data: Any?
19 | )
20 |
--------------------------------------------------------------------------------
/bugsnag-plugin-react-native/src/main/java/com/bugsnag/android/MetadataDeserializer.java:
--------------------------------------------------------------------------------
1 | package com.bugsnag.android;
2 |
3 | import java.util.Map;
4 | import java.util.concurrent.ConcurrentHashMap;
5 |
6 | class MetadataDeserializer implements MapDeserializer {
7 | @Override
8 | public Metadata deserialize(Map map) {
9 | // cast map to retain original signature until next major version bump, as this
10 | // method signature is used by Unity/React native
11 | @SuppressWarnings({"unchecked", "rawtypes"})
12 | Map> data = (Map) map;
13 | ConcurrentHashMap> store = new ConcurrentHashMap<>(data);
14 | return new Metadata(store);
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/bugsnag-plugin-react-native/src/main/java/com/bugsnag/android/StackframeDeserializer.java:
--------------------------------------------------------------------------------
1 | package com.bugsnag.android;
2 |
3 | import java.util.Map;
4 |
5 | class StackframeDeserializer implements MapDeserializer {
6 |
7 | @Override
8 | public Stackframe deserialize(Map map) {
9 | return new Stackframe(
10 | MapUtils.getOrNull(map, "method"),
11 | MapUtils.getOrNull(map, "file"),
12 | MapUtils.getOrNull(map, "lineNumber"),
13 | MapUtils.getOrNull(map, "inProject"),
14 | MapUtils.