diff --git a/.buildkite/pipeline.full.yml b/.buildkite/pipeline.full.yml
index be25736eb5..535bec7060 100644
--- a/.buildkite/pipeline.full.yml
+++ b/.buildkite/pipeline.full.yml
@@ -35,6 +35,7 @@ steps:
plugins:
artifacts#v1.2.0:
download: "build/release/fixture-minimal.apk"
+ upload: "maze_output/failed/**/*"
docker-compose#v3.7.0:
pull: android-maze-runner
run: android-maze-runner
@@ -44,8 +45,6 @@ steps:
- "--farm=bs"
- "--device=ANDROID_9_0"
- "--fail-fast"
- - "--tags"
- - "not @Flaky"
concurrency: 9
concurrency_group: 'browserstack-app'
@@ -66,6 +65,7 @@ steps:
run: android-ci
env:
INSTRUMENTATION_DEVICES: '["Google Pixel-7.1"]'
+ TEST_APK_LOCATION: 'bugsnag-android-core/build/outputs/apk/androidTest/debug/bugsnag-android-core-debug-androidTest.apk'
concurrency: 9
concurrency_group: 'browserstack-app'
@@ -79,6 +79,7 @@ steps:
run: android-ci
env:
INSTRUMENTATION_DEVICES: '["Google Pixel 3-9.0"]'
+ TEST_APK_LOCATION: 'bugsnag-android-core/build/outputs/apk/androidTest/debug/bugsnag-android-core-debug-androidTest.apk'
concurrency: 9
concurrency_group: 'browserstack-app'
@@ -90,6 +91,7 @@ steps:
plugins:
artifacts#v1.2.0:
download: "build/release/fixture-r16.apk"
+ upload: "maze_output/failed/**/*"
docker-compose#v3.7.0:
pull: android-maze-runner
run: android-maze-runner
@@ -99,8 +101,6 @@ steps:
- "--farm=bs"
- "--device=ANDROID_5_0"
- "--fail-fast"
- - "--tags"
- - "not @Flaky"
concurrency: 9
concurrency_group: 'browserstack-app'
soft_fail:
@@ -114,6 +114,7 @@ steps:
plugins:
artifacts#v1.2.0:
download: "build/release/fixture-r16.apk"
+ upload: "maze_output/failed/**/*"
docker-compose#v3.7.0:
pull: android-maze-runner
run: android-maze-runner
@@ -123,8 +124,6 @@ steps:
- "--farm=bs"
- "--device=ANDROID_5_0"
- "--fail-fast"
- - "--tags"
- - "not @Flaky"
concurrency: 9
concurrency_group: 'browserstack-app'
soft_fail:
@@ -138,6 +137,7 @@ steps:
plugins:
artifacts#v1.2.0:
download: "build/release/fixture-r16.apk"
+ upload: "maze_output/failed/**/*"
docker-compose#v3.7.0:
pull: android-maze-runner
run: android-maze-runner
@@ -147,8 +147,6 @@ steps:
- "--farm=bs"
- "--device=ANDROID_6_0"
- "--fail-fast"
- - "--tags"
- - "not @Flaky"
concurrency: 9
concurrency_group: 'browserstack-app'
@@ -160,6 +158,7 @@ steps:
plugins:
artifacts#v1.2.0:
download: "build/release/fixture-r16.apk"
+ upload: "maze_output/failed/**/*"
docker-compose#v3.7.0:
pull: android-maze-runner
run: android-maze-runner
@@ -169,8 +168,6 @@ steps:
- "--farm=bs"
- "--device=ANDROID_6_0"
- "--fail-fast"
- - "--tags"
- - "not @Flaky"
concurrency: 9
concurrency_group: 'browserstack-app'
@@ -182,6 +179,7 @@ steps:
plugins:
artifacts#v1.2.0:
download: "build/release/fixture-r19.apk"
+ upload: "maze_output/failed/**/*"
docker-compose#v3.7.0:
pull: android-maze-runner
run: android-maze-runner
@@ -191,8 +189,6 @@ steps:
- "--farm=bs"
- "--device=ANDROID_7_1"
- "--fail-fast"
- - "--tags"
- - "not @Flaky"
concurrency: 9
concurrency_group: 'browserstack-app'
@@ -204,6 +200,7 @@ steps:
plugins:
artifacts#v1.2.0:
download: "build/release/fixture-r19.apk"
+ upload: "maze_output/failed/**/*"
docker-compose#v3.7.0:
pull: android-maze-runner
run: android-maze-runner
@@ -213,8 +210,6 @@ steps:
- "--farm=bs"
- "--device=ANDROID_7_1"
- "--fail-fast"
- - "--tags"
- - "not @Flaky"
concurrency: 9
concurrency_group: 'browserstack-app'
@@ -226,6 +221,7 @@ steps:
plugins:
artifacts#v1.2.0:
download: "build/release/fixture-r19.apk"
+ upload: "maze_output/failed/**/*"
docker-compose#v3.7.0:
pull: android-maze-runner
run: android-maze-runner
@@ -235,8 +231,6 @@ steps:
- "--farm=bs"
- "--device=ANDROID_8_1"
- "--fail-fast"
- - "--tags"
- - "not @Flaky"
concurrency: 9
concurrency_group: 'browserstack-app'
@@ -248,6 +242,7 @@ steps:
plugins:
artifacts#v1.2.0:
download: "build/release/fixture-r19.apk"
+ upload: "maze_output/failed/**/*"
docker-compose#v3.7.0:
pull: android-maze-runner
run: android-maze-runner
@@ -257,8 +252,6 @@ steps:
- "--farm=bs"
- "--device=ANDROID_8_1"
- "--fail-fast"
- - "--tags"
- - "not @Flaky"
concurrency: 9
concurrency_group: 'browserstack-app'
@@ -270,6 +263,7 @@ steps:
plugins:
artifacts#v1.2.0:
download: "build/release/fixture-r21.apk"
+ upload: "maze_output/failed/**/*"
docker-compose#v3.7.0:
pull: android-maze-runner
run: android-maze-runner
@@ -279,8 +273,6 @@ steps:
- "--farm=bs"
- "--device=ANDROID_10_0"
- "--fail-fast"
- - "--tags"
- - "not @Flaky"
concurrency: 9
concurrency_group: 'browserstack-app'
@@ -292,6 +284,7 @@ steps:
plugins:
artifacts#v1.2.0:
download: "build/release/fixture-r21.apk"
+ upload: "maze_output/failed/**/*"
docker-compose#v3.7.0:
pull: android-maze-runner
run: android-maze-runner
@@ -301,8 +294,6 @@ steps:
- "--farm=bs"
- "--device=ANDROID_10_0"
- "--fail-fast"
- - "--tags"
- - "not @Flaky"
concurrency: 9
concurrency_group: 'browserstack-app'
@@ -318,6 +309,7 @@ steps:
plugins:
artifacts#v1.2.0:
download: "build/release/fixture-r21.apk"
+ upload: "maze_output/failed/**/*"
docker-compose#v3.7.0:
pull: android-maze-runner
run: android-maze-runner
@@ -327,8 +319,6 @@ steps:
- "--farm=bs"
- "--device=ANDROID_11_0"
- "--fail-fast"
- - "--tags"
- - "not @Flaky"
concurrency: 9
concurrency_group: 'browserstack-app'
@@ -340,6 +330,7 @@ steps:
plugins:
artifacts#v1.2.0:
download: "build/release/fixture-r21.apk"
+ upload: "maze_output/failed/**/*"
docker-compose#v3.7.0:
pull: android-maze-runner
run: android-maze-runner
@@ -349,173 +340,6 @@ steps:
- "--farm=bs"
- "--device=ANDROID_11_0"
- "--fail-fast"
- - "--tags"
- - "not @Flaky"
- concurrency: 9
- concurrency_group: 'browserstack-app'
-
- #
- # Flaky scenarios. These should be skipped if there are no scenarios annotated with the @Flaky tag (as we should
- # always be aiming for) to avoid unnecessary CI wait times and potential flakes from resource unavailability.
- #
- - label: ':hankey: Flaky Android 4.4 NDK r16 end-to-end tests'
- skip: There are no @Flaky scenarios at present
- depends_on:
- - "fixture-r16"
- timeout_in_minutes: 90
- plugins:
- artifacts#v1.2.0:
- download: "build/release/fixture-r16.apk"
- docker-compose#v3.7.0:
- pull: android-maze-runner
- run: android-maze-runner
- command:
- - "features/full_tests"
- - "--retry=2"
- - "--strict-undefined"
- - "--strict-pending"
- - "--app=/app/build/release/fixture-r16.apk"
- - "--farm=bs"
- - "--device=ANDROID_4_4"
- - "--tags=@Flaky"
- concurrency: 9
- concurrency_group: 'browserstack-app'
-
- - label: ':hankey: Flaky Android 5 NDK r16 end-to-end tests'
- skip: There are no @Flaky scenarios at present
- depends_on:
- - "fixture-r16"
- timeout_in_minutes: 90
- plugins:
- artifacts#v1.2.0:
- download: "build/release/fixture-r16.apk"
- docker-compose#v3.7.0:
- pull: android-maze-runner
- run: android-maze-runner
- command:
- - "features/full_tests"
- - "--retry=2"
- - "--strict-undefined"
- - "--strict-pending"
- - "--app=/app/build/release/fixture-r16.apk"
- - "--farm=bs"
- - "--device=ANDROID_5_0"
- - "--tags=@Flaky"
- concurrency: 9
- concurrency_group: 'browserstack-app'
-
- - label: ':hankey: Flaky Android 6 NDK r16 end-to-end tests'
- skip: There are no @Flaky scenarios at present
- depends_on:
- - "fixture-r16"
- timeout_in_minutes: 90
- plugins:
- artifacts#v1.2.0:
- download: "build/release/fixture-r16.apk"
- docker-compose#v3.7.0:
- pull: android-maze-runner
- run: android-maze-runner
- command:
- - "features/full_tests"
- - "--retry=2"
- - "--strict-undefined"
- - "--strict-pending"
- - "--app=/app/build/release/fixture-r16.apk"
- - "--farm=bs"
- - "--device=ANDROID_6_0"
- - "--tags=@Flaky"
- concurrency: 9
- concurrency_group: 'browserstack-app'
-
- - label: ':hankey: Flaky Android 7 NDK r19 end-to-end tests'
- skip: There are no @Flaky scenarios at present
- depends_on:
- - "fixture-r19"
- timeout_in_minutes: 60
- plugins:
- artifacts#v1.2.0:
- download: "build/release/fixture-r19.apk"
- docker-compose#v3.7.0:
- pull: android-maze-runner
- run: android-maze-runner
- command:
- - "features/full_tests"
- - "--retry=2"
- - "--strict-undefined"
- - "--strict-pending"
- - "--app=/app/build/release/fixture-r19.apk"
- - "--farm=bs"
- - "--device=ANDROID_7_1"
- - "--tags=@Flaky"
- concurrency: 9
- concurrency_group: 'browserstack-app'
-
- - label: ':hankey: Flaky Android 8.1 NDK r19 end-to-end tests'
- skip: There are no @Flaky scenarios at present
- depends_on:
- - "fixture-r19"
- timeout_in_minutes: 60
- plugins:
- artifacts#v1.2.0:
- download: "build/release/fixture-r19.apk"
- docker-compose#v3.7.0:
- pull: android-maze-runner
- run: android-maze-runner
- command:
- - "features/full_tests"
- - "--retry=2"
- - "--strict-undefined"
- - "--strict-pending"
- - "--app=/app/build/release/fixture-r19.apk"
- - "--farm=bs"
- - "--device=ANDROID_8_1"
- - "--tags=@Flaky"
- concurrency: 9
- concurrency_group: 'browserstack-app'
-
- - label: ':hankey: Flaky Android 10 NDK r21 end-to-end tests'
- skip: There are no @Flaky scenarios at present
- depends_on:
- - "fixture-r21"
- timeout_in_minutes: 60
- plugins:
- artifacts#v1.2.0:
- download: "build/release/fixture-r21.apk"
- docker-compose#v3.7.0:
- pull: android-maze-runner
- run: android-maze-runner
- command:
- - "features/full_tests"
- - "--retry=2"
- - "--strict-undefined"
- - "--strict-pending"
- - "--app=/app/build/release/fixture-r21.apk"
- - "--farm=bs"
- - "--device=ANDROID_10_0"
- - "--tags=@Flaky"
- concurrency: 9
- concurrency_group: 'browserstack-app'
-
- - label: ':hankey: Flaky Android 11 NDK r21 end-to-end tests'
- skip: There are no @Flaky scenarios at present
- depends_on:
- - "fixture-r21"
- timeout_in_minutes: 60
- plugins:
- artifacts#v1.2.0:
- download: "build/release/fixture-r21.apk"
- docker-compose#v3.7.0:
- pull: android-maze-runner
- run: android-maze-runner
- command:
- - "features/full_tests"
- - "--retry=2"
- - "--strict-undefined"
- - "--strict-pending"
- - "--app=/app/build/release/fixture-r21.apk"
- - "--farm=bs"
- - "--device=ANDROID_11_0"
- - "--tags=@Flaky"
concurrency: 9
concurrency_group: 'browserstack-app'
diff --git a/.buildkite/pipeline.quick.yml b/.buildkite/pipeline.quick.yml
index 4857af1412..c82b4942f7 100644
--- a/.buildkite/pipeline.quick.yml
+++ b/.buildkite/pipeline.quick.yml
@@ -6,6 +6,7 @@ steps:
plugins:
artifacts#v1.2.0:
download: "build/release/fixture-r16.apk"
+ upload: "maze_output/failed/**/*"
docker-compose#v3.7.0:
pull: android-maze-runner
run: android-maze-runner
@@ -27,6 +28,7 @@ steps:
plugins:
artifacts#v1.2.0:
download: "build/release/fixture-r16.apk"
+ upload: "maze_output/failed/**/*"
docker-compose#v3.7.0:
pull: android-maze-runner
run: android-maze-runner
@@ -46,6 +48,7 @@ steps:
plugins:
artifacts#v1.2.0:
download: "build/release/fixture-r19.apk"
+ upload: "maze_output/failed/**/*"
docker-compose#v3.7.0:
pull: android-maze-runner
run: android-maze-runner
@@ -65,6 +68,7 @@ steps:
plugins:
artifacts#v1.2.0:
download: "build/release/fixture-r19.apk"
+ upload: "maze_output/failed/**/*"
docker-compose#v3.7.0:
pull: android-maze-runner
run: android-maze-runner
@@ -84,6 +88,7 @@ steps:
plugins:
artifacts#v1.2.0:
download: "build/release/fixture-r21.apk"
+ upload: "maze_output/failed/**/*"
docker-compose#v3.7.0:
pull: android-maze-runner
run: android-maze-runner
@@ -104,6 +109,7 @@ steps:
plugins:
artifacts#v1.2.0:
download: "build/release/fixture-r21.apk"
+ upload: "maze_output/failed/**/*"
docker-compose#v3.7.0:
pull: android-maze-runner
run: android-maze-runner
@@ -112,8 +118,6 @@ steps:
- "--app=/app/build/release/fixture-r21.apk"
- "--farm=bs"
- "--device=ANDROID_9_0"
- - "--tags"
- - "not @Flaky"
concurrency: 9
concurrency_group: 'browserstack-app'
@@ -125,6 +129,7 @@ steps:
plugins:
artifacts#v1.2.0:
download: "build/release/fixture-r21.apk"
+ upload: "maze_output/failed/**/*"
docker-compose#v3.7.0:
pull: android-maze-runner
run: android-maze-runner
@@ -133,35 +138,6 @@ steps:
- "--app=/app/build/release/fixture-r21.apk"
- "--farm=bs"
- "--device=ANDROID_9_0"
- - "--tags"
- - "not @Flaky"
- concurrency: 9
- concurrency_group: 'browserstack-app'
-
- #
- # Flaky scenarios. These should be skipped if there are no scenarios annotated with the @Flaky tag (as we should
- # always be aiming for) to avoid unnecessary CI wait times and potential flakes from resource unavailability.
- #
- - label: ':hankey: Flaky Android 9 NDK r21 end-to-end tests'
- skip: There are no @Flaky scenarios at present
- depends_on:
- - "fixture-r21"
- timeout_in_minutes: 60
- plugins:
- artifacts#v1.2.0:
- download: "build/release/fixture-r21.apk"
- docker-compose#v3.7.0:
- pull: android-maze-runner
- run: android-maze-runner
- command:
- - "features/full_tests"
- - "--retry=2"
- - "--strict-undefined"
- - "--strict-pending"
- - "--app=/app/build/release/fixture-r21.apk"
- - "--farm=bs"
- - "--device=ANDROID_9_0"
- - "--tags=@Flaky"
concurrency: 9
concurrency_group: 'browserstack-app'
@@ -172,6 +148,7 @@ steps:
plugins:
artifacts#v1.2.0:
download: "build/release/fixture-r21.apk"
+ upload: "maze_output/failed/**/*"
docker-compose#v3.7.0:
pull: android-maze-runner
run: android-maze-runner
diff --git a/.buildkite/pipeline.yml b/.buildkite/pipeline.yml
index 64f967e71d..d0a685f200 100644
--- a/.buildkite/pipeline.yml
+++ b/.buildkite/pipeline.yml
@@ -164,6 +164,22 @@ steps:
run: android-ci
env:
INSTRUMENTATION_DEVICES: '["Google Pixel-7.1"]'
+ TEST_APK_LOCATION: 'bugsnag-android-core/build/outputs/apk/androidTest/debug/bugsnag-android-core-debug-androidTest.apk'
+ concurrency: 9
+ concurrency_group: 'browserstack-app'
+
+ - label: ':android: Performance benchmarks'
+ key: 'perf-benchmarks'
+ depends_on:
+ - "android-ci"
+ timeout_in_minutes: 30
+ command: ./scripts/build-instrumentation-tests.sh && ./scripts/run-instrumentation-test.sh
+ plugins:
+ - docker-compose#v3.7.0:
+ run: android-ci
+ env:
+ INSTRUMENTATION_DEVICES: '["Google Pixel-7.1"]'
+ TEST_APK_LOCATION: 'bugsnag-benchmarks/build/outputs/apk/androidTest/release/bugsnag-benchmarks-release-androidTest.apk'
concurrency: 9
concurrency_group: 'browserstack-app'
@@ -174,6 +190,7 @@ steps:
plugins:
artifacts#v1.2.0:
download: "build/release/fixture-r16.apk"
+ upload: "maze_output/failed/**/*"
docker-compose#v3.7.0:
pull: android-maze-runner
run: android-maze-runner
@@ -197,6 +214,7 @@ steps:
plugins:
artifacts#v1.2.0:
download: "build/release/fixture-r21.apk"
+ upload: "maze_output/failed/**/*"
docker-compose#v3.7.0:
pull: android-maze-runner
run: android-maze-runner
diff --git a/CHANGELOG.md b/CHANGELOG.md
index db31db94e9..36cdd124c9 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,55 @@
# Changelog
+## 5.9.5 (2021-06-25)
+
+* Unity: Properly handle ANRs after multiple calls to autoNotify and autoDetectAnrs
+ [#1265](https://github.com/bugsnag/bugsnag-android/pull/1265)
+
+* Cache value of app.backgroundWorkRestricted
+ [#1275](https://github.com/bugsnag/bugsnag-android/pull/1275)
+
+* Optimize execution of callbacks
+ [#1276](https://github.com/bugsnag/bugsnag-android/pull/1276)
+
+* Optimize implementation of internal state change observers
+ [#1274](https://github.com/bugsnag/bugsnag-android/pull/1274)
+
+* Optimize metadata implementation by reducing type casts
+ [#1277](https://github.com/bugsnag/bugsnag-android/pull/1277)
+
+* Trim stacktraces to <200 frames before attempting to construct POJOs
+ [#1281](https://github.com/bugsnag/bugsnag-android/pull/1281)
+
+* Use direct field access when adding breadcrumbs and state updates
+ [#1279](https://github.com/bugsnag/bugsnag-android/pull/1279)
+
+* Avoid using regex to validate api key
+ [#1282](https://github.com/bugsnag/bugsnag-android/pull/1282)
+
+* Discard unwanted automatic data earlier where possible
+ [#1280](https://github.com/bugsnag/bugsnag-android/pull/1280)
+
+* Enable ANR handling on immediately if started from the main thread
+ [#1283](https://github.com/bugsnag/bugsnag-android/pull/1283)
+
+* Include `app.binaryArch` in all events
+ [#1287](https://github.com/bugsnag/bugsnag-android/pull/1287)
+
+* Cache results from PackageManager
+ [#1288](https://github.com/bugsnag/bugsnag-android/pull/1288)
+
+* Use ring buffer to store breadcrumbs
+ [#1286](https://github.com/bugsnag/bugsnag-android/pull/1286)
+
+* Avoid expensive set construction in Config constructor
+ [#1289](https://github.com/bugsnag/bugsnag-android/pull/1289)
+
+* Replace calls to String.format() with concatenation
+ [#1293](https://github.com/bugsnag/bugsnag-android/pull/1293)
+
+* Optimize capture of thread traces
+ [#1300](https://github.com/bugsnag/bugsnag-android/pull/1300)
+
## 5.9.4 (2021-05-26)
* Unity: add methods for setting autoNotify and autoDetectAnrs
diff --git a/bugsnag-android-core/build.gradle b/bugsnag-android-core/build.gradle
index db07e7e9b7..ce57159a6a 100644
--- a/bugsnag-android-core/build.gradle
+++ b/bugsnag-android-core/build.gradle
@@ -15,3 +15,5 @@ dokka {
outputFormat = "html"
outputDirectory = "$buildDir/dokka"
}
+
+apply from: "../gradle/kotlin.gradle"
diff --git a/bugsnag-android-core/detekt-baseline.xml b/bugsnag-android-core/detekt-baseline.xml
index 3173ed5f4f..0c3e0f3b63 100644
--- a/bugsnag-android-core/detekt-baseline.xml
+++ b/bugsnag-android-core/detekt-baseline.xml
@@ -2,6 +2,7 @@
+ ImplicitDefaultLocale:DeliveryHeaders.kt$String.format("%02x", byte)
LongParameterList:App.kt$App$( /** * The architecture of the running application binary */ var binaryArch: String?, /** * The package name of the application */ var id: String?, /** * The release stage set in [Configuration.releaseStage] */ var releaseStage: String?, /** * The version of the application set in [Configuration.version] */ var version: String?, /** The revision ID from the manifest (React Native apps only) */ var codeBundleId: String?, /** * The unique identifier for the build of the application set in [Configuration.buildUuid] */ var buildUuid: String?, /** * The application type set in [Configuration#version] */ var type: String?, /** * The version code of the application set in [Configuration.versionCode] */ var versionCode: Number? )
LongParameterList:AppDataCollector.kt$AppDataCollector$( appContext: Context, private val packageManager: PackageManager?, private val config: ImmutableConfig, private val sessionTracker: SessionTracker, private val activityManager: ActivityManager?, private val launchCrashTracker: LaunchCrashTracker, private val logger: Logger )
LongParameterList:AppWithState.kt$AppWithState$( binaryArch: String?, id: String?, releaseStage: String?, version: String?, codeBundleId: String?, buildUuid: String?, type: String?, versionCode: Number?, /** * The number of milliseconds the application was running before the event occurred */ var duration: Number?, /** * The number of milliseconds the application was running in the foreground before the * event occurred */ var durationInForeground: Number?, /** * Whether the application was in the foreground when the event occurred */ var inForeground: Boolean?, /** * Whether the application was launching when the event occurred */ var isLaunching: Boolean? )
@@ -11,20 +12,27 @@
LongParameterList:DeviceDataCollector.kt$DeviceDataCollector$( private val connectivity: Connectivity, private val appContext: Context, private val resources: Resources?, private val deviceId: String?, private val buildInfo: DeviceBuildInfo, private val dataDirectory: File, rootDetector: RootDetector, bgTaskService: BackgroundTaskService, private val logger: Logger )
LongParameterList:DeviceWithState.kt$DeviceWithState$( buildInfo: DeviceBuildInfo, jailbroken: Boolean?, id: String?, locale: String?, totalMemory: Long?, runtimeVersions: MutableMap<String, Any>, /** * The number of free bytes of storage available on the device */ var freeDisk: Long?, /** * The number of free bytes of memory available on the device */ var freeMemory: Long?, /** * The orientation of the device when the event occurred: either portrait or landscape */ var orientation: String?, /** * The timestamp on the device when the event occurred */ var time: Date? )
LongParameterList:EventFilenameInfo.kt$EventFilenameInfo.Companion$( obj: Any, uuid: String = UUID.randomUUID().toString(), apiKey: String?, timestamp: Long = System.currentTimeMillis(), config: ImmutableConfig, isLaunching: Boolean? = null )
- LongParameterList:StateEvent.kt$StateEvent.Install$( val apiKey: String, val autoDetectNdkCrashes: Boolean, val appVersion: String?, val buildUuid: String?, val releaseStage: String?, val lastRunInfoPath: String, val consecutiveLaunchCrashes: Int )
- LongParameterList:ThreadState.kt$ThreadState$( exc: Throwable?, isUnhandled: Boolean, sendThreads: ThreadSendPolicy, projectPackages: Collection<String>, logger: Logger, currentThread: java.lang.Thread = java.lang.Thread.currentThread(), stackTraces: MutableMap<java.lang.Thread, Array<StackTraceElement>> = java.lang.Thread.getAllStackTraces() )
+ LongParameterList:StateEvent.kt$StateEvent.Install$( @JvmField val apiKey: String, @JvmField val autoDetectNdkCrashes: Boolean, @JvmField val appVersion: String?, @JvmField val buildUuid: String?, @JvmField val releaseStage: String?, @JvmField val lastRunInfoPath: String, @JvmField val consecutiveLaunchCrashes: Int )
LongParameterList:ThreadState.kt$ThreadState$( stackTraces: MutableMap<java.lang.Thread, Array<StackTraceElement>>, currentThread: java.lang.Thread, exc: Throwable?, isUnhandled: Boolean, projectPackages: Collection<String>, logger: Logger )
MagicNumber:DefaultDelivery.kt$DefaultDelivery$299
MagicNumber:DefaultDelivery.kt$DefaultDelivery$429
MagicNumber:DefaultDelivery.kt$DefaultDelivery$499
MagicNumber:LastRunInfoStore.kt$LastRunInfoStore$3
MaxLineLength:LastRunInfo.kt$LastRunInfo$return "LastRunInfo(consecutiveLaunchCrashes=$consecutiveLaunchCrashes, crashed=$crashed, crashedDuringLaunch=$crashedDuringLaunch)"
- ProtectedMemberInFinalClass:ConfigInternal.kt$ConfigInternal$protected val plugins = mutableSetOf<Plugin>()
+ ProtectedMemberInFinalClass:ConfigInternal.kt$ConfigInternal$protected val plugins = HashSet<Plugin>()
ProtectedMemberInFinalClass:EventInternal.kt$EventInternal$protected fun isAnr(event: Event): Boolean
ProtectedMemberInFinalClass:EventInternal.kt$EventInternal$protected fun shouldDiscardClass(): Boolean
ProtectedMemberInFinalClass:EventInternal.kt$EventInternal$protected fun updateSeverityInternal(severity: Severity)
- ProtectedMemberInFinalClass:PluginClient.kt$PluginClient$protected val plugins: Set<Plugin>
ReturnCount:DefaultDelivery.kt$DefaultDelivery$fun deliver( urlString: String, streamable: JsonStream.Streamable, headers: Map<String, String?> ): DeliveryStatus
+ SwallowedException:AppDataCollector.kt$AppDataCollector$catch (exception: Exception) { logger.w("Could not check lowMemory status") }
+ SwallowedException:ContextExtensions.kt$catch (exc: RuntimeException) { null }
+ SwallowedException:DeviceDataCollector.kt$DeviceDataCollector$catch (exc: Exception) { false }
+ SwallowedException:DeviceDataCollector.kt$DeviceDataCollector$catch (exception: Exception) { logger.w("Could not get battery status") }
+ SwallowedException:DeviceDataCollector.kt$DeviceDataCollector$catch (exception: Exception) { logger.w("Could not get locationStatus") }
+ SwallowedException:DeviceIdStore.kt$DeviceIdStore$catch (exc: OverlappingFileLockException) { Thread.sleep(FILE_LOCK_WAIT_MS) }
+ SwallowedException:PluginClient.kt$PluginClient$catch (exc: ClassNotFoundException) { logger.d("Plugin '$clz' is not on the classpath - functionality will not be enabled.") null }
+ UnusedPrivateMember:ThreadStateTest.kt$ThreadStateTest$private val configuration = generateImmutableConfig()
+ VarCouldBeVal:SystemBroadcastReceiverTest.kt$SystemBroadcastReceiverTest$var config = BugsnagTestUtils.generateConfiguration()
VariableNaming:EventInternal.kt$EventInternal$/** * @return user information associated with this Event */ internal var _user = User(null, null, null)
diff --git a/bugsnag-android-core/src/androidTest/java/com/bugsnag/android/BreadcrumbFilterTest.kt b/bugsnag-android-core/src/androidTest/java/com/bugsnag/android/BreadcrumbFilterTest.kt
index 678e4009d1..d8092ece01 100644
--- a/bugsnag-android-core/src/androidTest/java/com/bugsnag/android/BreadcrumbFilterTest.kt
+++ b/bugsnag-android-core/src/androidTest/java/com/bugsnag/android/BreadcrumbFilterTest.kt
@@ -24,8 +24,7 @@ class BreadcrumbFilterTest {
client = generateClient(configuration)
client.leaveBreadcrumb("Hello World")
-
- assertEquals(1, client.breadcrumbState.store.size)
+ assertEquals(1, client.breadcrumbState.copy().size)
}
@Test
@@ -36,6 +35,6 @@ class BreadcrumbFilterTest {
client.leaveBreadcrumb("Hello World")
- assertEquals(1, client.breadcrumbState.store.size)
+ assertEquals(1, client.breadcrumbState.copy().size)
}
}
diff --git a/bugsnag-android-core/src/androidTest/java/com/bugsnag/android/BreadcrumbStateTest.kt b/bugsnag-android-core/src/androidTest/java/com/bugsnag/android/BreadcrumbStateTest.kt
index 34ff644a55..1f5831ca20 100644
--- a/bugsnag-android-core/src/androidTest/java/com/bugsnag/android/BreadcrumbStateTest.kt
+++ b/bugsnag-android-core/src/androidTest/java/com/bugsnag/android/BreadcrumbStateTest.kt
@@ -31,7 +31,7 @@ class BreadcrumbStateTest {
fun testClientMethods() {
client = generateClient()
client!!.leaveBreadcrumb("Hello World")
- val store = client!!.breadcrumbState.store
+ val store = client!!.breadcrumbState.copy()
var count = 0
for (breadcrumb in store) {
diff --git a/bugsnag-android-core/src/androidTest/java/com/bugsnag/android/BugsnagTestUtils.java b/bugsnag-android-core/src/androidTest/java/com/bugsnag/android/BugsnagTestUtils.java
index 1841aed26c..92ac16e01e 100644
--- a/bugsnag-android-core/src/androidTest/java/com/bugsnag/android/BugsnagTestUtils.java
+++ b/bugsnag-android-core/src/androidTest/java/com/bugsnag/android/BugsnagTestUtils.java
@@ -1,5 +1,8 @@
package com.bugsnag.android;
+import com.bugsnag.android.internal.ImmutableConfig;
+import com.bugsnag.android.internal.ImmutableConfigKt;
+
import androidx.annotation.NonNull;
import androidx.test.core.app.ApplicationProvider;
@@ -87,7 +90,7 @@ static ImmutableConfig convert(Configuration config) {
} catch (IOException ignored) {
// swallow
}
- return ImmutableConfigKt.convertToImmutableConfig(config, null);
+ return ImmutableConfigKt.convertToImmutableConfig(config, null, null, null);
}
static Device generateDevice() {
diff --git a/bugsnag-android-core/src/androidTest/java/com/bugsnag/android/ClientTest.java b/bugsnag-android-core/src/androidTest/java/com/bugsnag/android/ClientTest.java
index f09093c666..94aba83749 100644
--- a/bugsnag-android-core/src/androidTest/java/com/bugsnag/android/ClientTest.java
+++ b/bugsnag-android-core/src/androidTest/java/com/bugsnag/android/ClientTest.java
@@ -76,14 +76,14 @@ public void testMaxBreadcrumbs() {
config.setEnabledBreadcrumbTypes(new HashSet<>(breadcrumbTypes));
config.setMaxBreadcrumbs(2);
client = generateClient(config);
- assertEquals(0, client.breadcrumbState.getStore().size());
+ assertEquals(0, client.breadcrumbState.copy().size());
client.leaveBreadcrumb("test");
client.leaveBreadcrumb("another");
client.leaveBreadcrumb("yet another");
- assertEquals(2, client.breadcrumbState.getStore().size());
+ assertEquals(2, client.breadcrumbState.copy().size());
- Breadcrumb poll = client.breadcrumbState.getStore().poll();
+ Breadcrumb poll = client.breadcrumbState.copy().get(0);
assertEquals(BreadcrumbType.MANUAL, poll.getType());
assertEquals("another", poll.getMessage());
}
@@ -126,10 +126,12 @@ public void testClientUser() {
@Test
public void testClientBreadcrumbRetrieval() {
- client = generateClient();
+ Configuration config = new Configuration("api-key");
+ config.setEnabledBreadcrumbTypes(Collections.emptySet());
+ client = generateClient(config);
client.leaveBreadcrumb("Hello World");
List breadcrumbs = client.getBreadcrumbs();
- List store = new ArrayList<>(client.breadcrumbState.getStore());
+ List store = new ArrayList<>(client.breadcrumbState.copy());
assertEquals(store, breadcrumbs);
assertNotSame(store, breadcrumbs);
}
@@ -153,8 +155,8 @@ public void testBreadcrumbStoreNotModified() {
breadcrumbs.clear(); // only the copy should be cleared
assertTrue(breadcrumbs.isEmpty());
- assertEquals(1, client.breadcrumbState.getStore().size());
- assertEquals("Manual breadcrumb", client.breadcrumbState.getStore().remove().getMessage());
+ assertEquals(1, client.breadcrumbState.copy().size());
+ assertEquals("Manual breadcrumb", client.breadcrumbState.copy().get(0).getMessage());
}
@Test
diff --git a/bugsnag-android-core/src/androidTest/java/com/bugsnag/android/EventPayloadTest.java b/bugsnag-android-core/src/androidTest/java/com/bugsnag/android/EventPayloadTest.java
index 6c143b2176..da9c1c4ee9 100644
--- a/bugsnag-android-core/src/androidTest/java/com/bugsnag/android/EventPayloadTest.java
+++ b/bugsnag-android-core/src/androidTest/java/com/bugsnag/android/EventPayloadTest.java
@@ -5,6 +5,8 @@
import static com.bugsnag.android.BugsnagTestUtils.streamableToJson;
import static org.junit.Assert.assertEquals;
+import com.bugsnag.android.internal.ImmutableConfig;
+
import androidx.test.filters.SmallTest;
import org.json.JSONArray;
@@ -22,7 +24,6 @@ public class EventPayloadTest {
/**
* Generates a eventPayload
- *
*/
@Before
public void setUp() {
diff --git a/bugsnag-android-core/src/androidTest/java/com/bugsnag/android/LastRunInfoStoreTest.kt b/bugsnag-android-core/src/androidTest/java/com/bugsnag/android/LastRunInfoStoreTest.kt
index 06ae6b0fe9..e6b503264d 100644
--- a/bugsnag-android-core/src/androidTest/java/com/bugsnag/android/LastRunInfoStoreTest.kt
+++ b/bugsnag-android-core/src/androidTest/java/com/bugsnag/android/LastRunInfoStoreTest.kt
@@ -3,6 +3,7 @@ package com.bugsnag.android
import android.content.Context
import androidx.test.core.app.ApplicationProvider
import com.bugsnag.android.BugsnagTestUtils.generateConfiguration
+import com.bugsnag.android.internal.convertToImmutableConfig
import org.junit.Assert.assertEquals
import org.junit.Assert.assertFalse
import org.junit.Assert.assertNull
@@ -21,7 +22,9 @@ internal class LastRunInfoStoreTest {
val config = convertToImmutableConfig(
generateConfiguration().apply {
persistenceDirectory = ApplicationProvider.getApplicationContext().cacheDir
- }
+ },
+ packageInfo = null,
+ appInfo = null
)
file = File(config.persistenceDirectory, "last-run-info")
file.delete()
diff --git a/bugsnag-android-core/src/androidTest/java/com/bugsnag/android/MemoryTrimTest.java b/bugsnag-android-core/src/androidTest/java/com/bugsnag/android/MemoryTrimTest.java
index 3d0804b030..9d6cfe6cf7 100644
--- a/bugsnag-android-core/src/androidTest/java/com/bugsnag/android/MemoryTrimTest.java
+++ b/bugsnag-android-core/src/androidTest/java/com/bugsnag/android/MemoryTrimTest.java
@@ -40,7 +40,7 @@ public void onLowMemoryEvent() {
verify(context, times(1)).registerComponentCallbacks(componentCallbacksCaptor.capture());
BugsnagTestObserver observer = new BugsnagTestObserver();
- client.registerObserver(observer);
+ client.addObserver(observer);
ComponentCallbacks callbacks = componentCallbacksCaptor.getValue();
callbacks.onLowMemory();
@@ -55,7 +55,7 @@ public void onLowMemoryEvent() {
assertTrue(
"observed event should be marked isLowMemory",
- ((StateEvent.UpdateMemoryTrimEvent) observedEvent).isLowMemory()
+ ((StateEvent.UpdateMemoryTrimEvent) observedEvent).isLowMemory
);
}
diff --git a/bugsnag-android-core/src/androidTest/java/com/bugsnag/android/ObserverInterfaceTest.java b/bugsnag-android-core/src/androidTest/java/com/bugsnag/android/ObserverInterfaceTest.java
index 1adc99f61f..329d68de4e 100644
--- a/bugsnag-android-core/src/androidTest/java/com/bugsnag/android/ObserverInterfaceTest.java
+++ b/bugsnag-android-core/src/androidTest/java/com/bugsnag/android/ObserverInterfaceTest.java
@@ -8,10 +8,13 @@
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
+import com.bugsnag.android.internal.StateObserver;
+
import androidx.annotation.NonNull;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.filters.SmallTest;
+import org.jetbrains.annotations.NotNull;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
@@ -19,8 +22,6 @@
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
-import java.util.Observable;
-import java.util.Observer;
import java.util.Set;
@SmallTest
@@ -47,7 +48,7 @@ public void setUp() {
config.addMetadata("foo", "bar", true);
client = new Client(ApplicationProvider.getApplicationContext(), config);
observer = new BugsnagTestObserver();
- client.registerObserver(observer);
+ client.addObserver(observer);
}
@After
@@ -84,9 +85,9 @@ public void testSyncInitialState() {
public void testAddMetadataSendsMessage() {
client.addMetadata("foo", "bar", "baz");
StateEvent.AddMetadata msg = findMessageInQueue(StateEvent.AddMetadata.class);
- assertEquals("foo", msg.getSection());
- assertEquals("bar", msg.getKey());
- assertEquals("baz", msg.getValue());
+ assertEquals("foo", msg.section);
+ assertEquals("bar", msg.key);
+ assertEquals("baz", msg.value);
}
@Test
@@ -94,8 +95,8 @@ public void testAddNullMetadataSendsMessage() {
client.addMetadata("foo", "bar", "baz");
client.addMetadata("foo", "bar", null);
StateEvent.ClearMetadataValue msg = findMessageInQueue(StateEvent.ClearMetadataValue.class);
- assertEquals("foo", msg.getSection());
- assertEquals("bar", msg.getKey());
+ assertEquals("foo", msg.section);
+ assertEquals("bar", msg.key);
}
@Test
@@ -103,7 +104,7 @@ public void testClearTopLevelTabSendsMessage() {
client.clearMetadata("axis");
StateEvent.ClearMetadataSection value
= findMessageInQueue(StateEvent.ClearMetadataSection.class);
- assertEquals("axis", value.getSection());
+ assertEquals("axis", value.section);
}
@Test
@@ -111,8 +112,8 @@ public void testClearTabSendsMessage() {
client.clearMetadata("axis", "foo");
StateEvent.ClearMetadataValue value
= findMessageInQueue(StateEvent.ClearMetadataValue.class);
- assertEquals("axis", value.getSection());
- assertEquals("foo", value.getKey());
+ assertEquals("axis", value.section);
+ assertEquals("foo", value.key);
}
@Test
@@ -126,9 +127,9 @@ public void testNotifySendsMessage() {
public void testStartSessionSendsMessage() {
client.startSession();
StateEvent.StartSession sessionInfo = findMessageInQueue(StateEvent.StartSession.class);
- assertNotNull(sessionInfo.getId());
- assertNotNull(sessionInfo.getStartedAt());
- assertEquals(0, sessionInfo.getHandledCount());
+ assertNotNull(sessionInfo.id);
+ assertNotNull(sessionInfo.startedAt);
+ assertEquals(0, sessionInfo.handledCount);
assertEquals(0, sessionInfo.getUnhandledCount());
}
@@ -149,32 +150,32 @@ public void testRegisterSessionSendsMessage() {
public void testClientSetContextSendsMessage() {
client.setContext("Pod Bay");
StateEvent.UpdateContext msg = findMessageInQueue(StateEvent.UpdateContext.class);
- assertEquals("Pod Bay", msg.getContext());
+ assertEquals("Pod Bay", msg.context);
}
@Test
public void testClientMarkLaunchCompletedSendsMessage() {
client.markLaunchCompleted();
StateEvent.UpdateIsLaunching msg = findMessageInQueue(StateEvent.UpdateIsLaunching.class);
- assertFalse(msg.isLaunching());
+ assertFalse(msg.isLaunching);
}
@Test
public void testClientSetUserId() {
client.setUser("personX", "bip@example.com", "Loblaw");
StateEvent.UpdateUser idMsg = findMessageInQueue(StateEvent.UpdateUser.class);
- assertEquals("personX", idMsg.getUser().getId());
- assertEquals("bip@example.com", idMsg.getUser().getEmail());
- assertEquals("Loblaw", idMsg.getUser().getName());
+ assertEquals("personX", idMsg.user.getId());
+ assertEquals("bip@example.com", idMsg.user.getEmail());
+ assertEquals("Loblaw", idMsg.user.getName());
}
@Test
public void testLeaveStringBreadcrumbSendsMessage() {
client.leaveBreadcrumb("Drift 4 units left");
StateEvent.AddBreadcrumb crumb = findMessageInQueue(StateEvent.AddBreadcrumb.class);
- assertEquals(BreadcrumbType.MANUAL, crumb.getType());
- assertEquals("Drift 4 units left", crumb.getMessage());
- assertTrue(crumb.getMetadata().isEmpty());
+ assertEquals(BreadcrumbType.MANUAL, crumb.type);
+ assertEquals("Drift 4 units left", crumb.message);
+ assertTrue(crumb.metadata.isEmpty());
}
@Test
@@ -182,18 +183,18 @@ public void testLeaveStringBreadcrumbDirectlySendsMessage() {
Breadcrumb obj = new Breadcrumb("Drift 4 units left", NoopLogger.INSTANCE);
client.breadcrumbState.add(obj);
StateEvent.AddBreadcrumb crumb = findMessageInQueue(StateEvent.AddBreadcrumb.class);
- assertEquals(BreadcrumbType.MANUAL, crumb.getType());
- assertEquals("Drift 4 units left", crumb.getMessage());
- assertTrue(crumb.getMetadata().isEmpty());
+ assertEquals(BreadcrumbType.MANUAL, crumb.type);
+ assertEquals("Drift 4 units left", crumb.message);
+ assertTrue(crumb.metadata.isEmpty());
}
@Test
public void testLeaveBreadcrumbSendsMessage() {
client.leaveBreadcrumb("Rollback", new HashMap(), BreadcrumbType.LOG);
StateEvent.AddBreadcrumb crumb = findMessageInQueue(StateEvent.AddBreadcrumb.class);
- assertEquals(BreadcrumbType.LOG, crumb.getType());
- assertEquals("Rollback", crumb.getMessage());
- assertEquals(0, crumb.getMetadata().size());
+ assertEquals(BreadcrumbType.LOG, crumb.type);
+ assertEquals("Rollback", crumb.message);
+ assertEquals(0, crumb.metadata.size());
}
@NonNull
@@ -206,7 +207,7 @@ private T findMessageInQueue(Class argClass) {
throw new RuntimeException("Failed to find StateEvent message " + argClass.getSimpleName());
}
- static class BugsnagTestObserver implements Observer {
+ static class BugsnagTestObserver implements StateObserver {
final ArrayList