diff --git a/.buildkite/pipeline.full.yml b/.buildkite/pipeline.full.yml index 39928e0f18..b5e71d8abe 100644 --- a/.buildkite/pipeline.full.yml +++ b/.buildkite/pipeline.full.yml @@ -39,7 +39,9 @@ steps: # BitBar steps # + # Minimal tests job skipped as there are only ANR scenarios, run separately using BS - label: ':bitbar: Minimal fixture end-to-end tests' + skip: "Only ANR scenarios are run again the minimal fixture at present" depends_on: "fixture-minimal" timeout_in_minutes: 30 plugins: @@ -62,6 +64,13 @@ steps: - "--no-tunnel" - "--aws-public-ip" - "--fail-fast" + - "--format=junit" + - "--out=reports" + - "--format=pretty" + test-collector#v1.10.2: + files: "reports/TEST-*.xml" + format: "junit" + branch: "^master|next$$" concurrency: 25 concurrency_group: 'bitbar' concurrency_method: eager @@ -86,11 +95,20 @@ steps: - "--farm=bs" - "--device=ANDROID_9" - "--fail-fast" + - "--format=junit" + - "--out=reports" + - "--format=pretty" + test-collector#v1.10.2: + files: "reports/TEST-*.xml" + format: "junit" + branch: "^master|next$$" concurrency: 5 concurrency_group: 'browserstack-app' concurrency_method: eager + # Minimal tests job skipped as there are only ANR scenarios, run separately using BS - label: ':bitbar: Debug fixture smoke tests' + skip: "Only ANR scenarios are run again the minimal fixture at present" depends_on: "fixture-debug" timeout_in_minutes: 30 plugins: @@ -116,6 +134,13 @@ steps: - "--no-tunnel" - "--aws-public-ip" - "--fail-fast" + - "--format=junit" + - "--out=reports" + - "--format=pretty" + test-collector#v1.10.2: + files: "reports/TEST-*.xml" + format: "junit" + branch: "^master|next$$" env: TEST_FIXTURE_SYMBOL_DIR: "build/fixture-debug" concurrency: 25 @@ -144,6 +169,13 @@ steps: - "--farm=bs" - "--device=ANDROID_9" - "--fail-fast" + - "--format=junit" + - "--out=reports" + - "--format=pretty" + test-collector#v1.10.2: + files: "reports/TEST-*.xml" + format: "junit" + branch: "^master|next$$" env: TEST_FIXTURE_SYMBOL_DIR: "build/fixture-debug" concurrency: 5 @@ -178,6 +210,13 @@ steps: - "--exclude=features/full_tests/[^a-k].*.feature" - "--exclude=features/full_tests/anr.feature" - "--fail-fast" + - "--format=junit" + - "--out=reports" + - "--format=pretty" + test-collector#v1.10.2: + files: "reports/TEST-*.xml" + format: "junit" + branch: "^master|next$$" env: TEST_FIXTURE_SYMBOL_DIR: "build/fixture-r19" concurrency: 25 @@ -211,6 +250,13 @@ steps: - "--no-tunnel" - "--aws-public-ip" - "--fail-fast" + - "--format=junit" + - "--out=reports" + - "--format=pretty" + test-collector#v1.10.2: + files: "reports/TEST-*.xml" + format: "junit" + branch: "^master|next$$" env: TEST_FIXTURE_SYMBOL_DIR: "build/fixture-r19" concurrency: 25 @@ -242,6 +288,13 @@ steps: - "--farm=bs" - "--device=ANDROID_7" - "--fail-fast" + - "--format=junit" + - "--out=reports" + - "--format=pretty" + test-collector#v1.10.2: + files: "reports/TEST-*.xml" + format: "junit" + branch: "^master|next$$" env: TEST_FIXTURE_SYMBOL_DIR: "build/fixture-r19" concurrency: 5 @@ -274,6 +327,13 @@ steps: - "--exclude=features/full_tests/[^a-k].*.feature" - "--exclude=features/full_tests/anr.feature" - "--fail-fast" + - "--format=junit" + - "--out=reports" + - "--format=pretty" + test-collector#v1.10.2: + files: "reports/TEST-*.xml" + format: "junit" + branch: "^master|next$$" env: TEST_FIXTURE_SYMBOL_DIR: "build/fixture-r19" concurrency: 25 @@ -306,6 +366,13 @@ steps: - "--no-tunnel" - "--aws-public-ip" - "--fail-fast" + - "--format=junit" + - "--out=reports" + - "--format=pretty" + test-collector#v1.10.2: + files: "reports/TEST-*.xml" + format: "junit" + branch: "^master|next$$" env: TEST_FIXTURE_SYMBOL_DIR: "build/fixture-r19" concurrency: 25 @@ -335,6 +402,13 @@ steps: - "--farm=bs" - "--device=ANDROID_8" - "--fail-fast" + - "--format=junit" + - "--out=reports" + - "--format=pretty" + test-collector#v1.10.2: + files: "reports/TEST-*.xml" + format: "junit" + branch: "^master|next$$" env: TEST_FIXTURE_SYMBOL_DIR: "build/fixture-r19" concurrency: 5 @@ -369,6 +443,13 @@ steps: - "--exclude=features/full_tests/[^a-k].*.feature" - "--exclude=features/full_tests/anr.feature" - "--fail-fast" + - "--format=junit" + - "--out=reports" + - "--format=pretty" + test-collector#v1.10.2: + files: "reports/TEST-*.xml" + format: "junit" + branch: "^master|next$$" env: TEST_FIXTURE_SYMBOL_DIR: "build/fixture-r21" concurrency: 25 @@ -403,6 +484,13 @@ steps: - "--no-tunnel" - "--aws-public-ip" - "--fail-fast" + - "--format=junit" + - "--out=reports" + - "--format=pretty" + test-collector#v1.10.2: + files: "reports/TEST-*.xml" + format: "junit" + branch: "^master|next$$" env: TEST_FIXTURE_SYMBOL_DIR: "build/fixture-r21" concurrency: 25 @@ -434,6 +522,13 @@ steps: - "--farm=bs" - "--device=ANDROID_9" - "--fail-fast" + - "--format=junit" + - "--out=reports" + - "--format=pretty" + test-collector#v1.10.2: + files: "reports/TEST-*.xml" + format: "junit" + branch: "^master|next$$" env: TEST_FIXTURE_SYMBOL_DIR: "build/fixture-r21" concurrency: 5 @@ -468,6 +563,13 @@ steps: - "--no-tunnel" - "--aws-public-ip" - "--fail-fast" + - "--format=junit" + - "--out=reports" + - "--format=pretty" + test-collector#v1.10.2: + files: "reports/TEST-*.xml" + format: "junit" + branch: "^master|next$$" env: TEST_FIXTURE_SYMBOL_DIR: "build/fixture-r21" concurrency: 25 @@ -502,6 +604,13 @@ steps: - "--no-tunnel" - "--aws-public-ip" - "--fail-fast" + - "--format=junit" + - "--out=reports" + - "--format=pretty" + test-collector#v1.10.2: + files: "reports/TEST-*.xml" + format: "junit" + branch: "^master|next$$" env: TEST_FIXTURE_SYMBOL_DIR: "build/fixture-r21" concurrency: 25 @@ -532,6 +641,13 @@ steps: - "--farm=bs" - "--device=ANDROID_10" - "--fail-fast" + - "--format=junit" + - "--out=reports" + - "--format=pretty" + test-collector#v1.10.2: + files: "reports/TEST-*.xml" + format: "junit" + branch: "^master|next$$" env: TEST_FIXTURE_SYMBOL_DIR: "build/fixture-r21" concurrency: 5 @@ -570,6 +686,13 @@ steps: - "--no-tunnel" - "--aws-public-ip" - "--fail-fast" + - "--format=junit" + - "--out=reports" + - "--format=pretty" + test-collector#v1.10.2: + files: "reports/TEST-*.xml" + format: "junit" + branch: "^master|next$$" env: TEST_FIXTURE_SYMBOL_DIR: "build/fixture-r21" concurrency: 25 @@ -604,6 +727,13 @@ steps: - "--no-tunnel" - "--aws-public-ip" - "--fail-fast" + - "--format=junit" + - "--out=reports" + - "--format=pretty" + test-collector#v1.10.2: + files: "reports/TEST-*.xml" + format: "junit" + branch: "^master|next$$" env: TEST_FIXTURE_SYMBOL_DIR: "build/fixture-r21" concurrency: 25 @@ -634,6 +764,13 @@ steps: - "--farm=bs" - "--device=ANDROID_11" - "--fail-fast" + - "--format=junit" + - "--out=reports" + - "--format=pretty" + test-collector#v1.10.2: + files: "reports/TEST-*.xml" + format: "junit" + branch: "^master|next$$" env: TEST_FIXTURE_SYMBOL_DIR: "build/fixture-r21" concurrency: 5 @@ -668,6 +805,13 @@ steps: - "--no-tunnel" - "--aws-public-ip" - "--fail-fast" + - "--format=junit" + - "--out=reports" + - "--format=pretty" + test-collector#v1.10.2: + files: "reports/TEST-*.xml" + format: "junit" + branch: "^master|next$$" env: TEST_FIXTURE_SYMBOL_DIR: "build/fixture-r21" concurrency: 25 @@ -702,6 +846,13 @@ steps: - "--no-tunnel" - "--aws-public-ip" - "--fail-fast" + - "--format=junit" + - "--out=reports" + - "--format=pretty" + test-collector#v1.10.2: + files: "reports/TEST-*.xml" + format: "junit" + branch: "^master|next$$" env: TEST_FIXTURE_SYMBOL_DIR: "build/fixture-r21" concurrency: 25 @@ -732,6 +883,13 @@ steps: - "--farm=bs" - "--device=ANDROID_13" - "--fail-fast" + - "--format=junit" + - "--out=reports" + - "--format=pretty" + test-collector#v1.10.2: + files: "reports/TEST-*.xml" + format: "junit" + branch: "^master|next$$" env: TEST_FIXTURE_SYMBOL_DIR: "build/fixture-r21" concurrency: 5 @@ -766,6 +924,13 @@ steps: - "--no-tunnel" - "--aws-public-ip" - "--fail-fast" + - "--format=junit" + - "--out=reports" + - "--format=pretty" + test-collector#v1.10.2: + files: "reports/TEST-*.xml" + format: "junit" + branch: "^master|next$$" env: TEST_FIXTURE_SYMBOL_DIR: "build/fixture-r21" concurrency: 25 @@ -800,6 +965,13 @@ steps: - "--no-tunnel" - "--aws-public-ip" - "--fail-fast" + - "--format=junit" + - "--out=reports" + - "--format=pretty" + test-collector#v1.10.2: + files: "reports/TEST-*.xml" + format: "junit" + branch: "^master|next$$" env: TEST_FIXTURE_SYMBOL_DIR: "build/fixture-r21" concurrency: 25 @@ -830,6 +1002,13 @@ steps: - "--farm=bs" - "--device=ANDROID_14" - "--fail-fast" + - "--format=junit" + - "--out=reports" + - "--format=pretty" + test-collector#v1.10.2: + files: "reports/TEST-*.xml" + format: "junit" + branch: "^master|next$$" env: TEST_FIXTURE_SYMBOL_DIR: "build/fixture-r21" concurrency: 5 diff --git a/.buildkite/pipeline.yml b/.buildkite/pipeline.yml index 3839238e47..baf34f0931 100644 --- a/.buildkite/pipeline.yml +++ b/.buildkite/pipeline.yml @@ -130,6 +130,13 @@ steps: - "--no-tunnel" - "--aws-public-ip" - "--fail-fast" + - "--format=junit" + - "--out=reports" + - "--format=pretty" + test-collector#v1.10.2: + files: "reports/TEST-*.xml" + format: "junit" + branch: "^master|next$$" env: TEST_FIXTURE_SYMBOL_DIR: "build/fixture-r19" concurrency: 25 @@ -160,6 +167,13 @@ steps: - "--farm=bs" - "--device=ANDROID_7" - "--fail-fast" + - "--format=junit" + - "--out=reports" + - "--format=pretty" + test-collector#v1.10.2: + files: "reports/TEST-*.xml" + format: "junit" + branch: "^master|next$$" env: TEST_FIXTURE_SYMBOL_DIR: "build/fixture-r19" concurrency: 5 @@ -191,6 +205,13 @@ steps: - "--no-tunnel" - "--aws-public-ip" - "--fail-fast" + - "--format=junit" + - "--out=reports" + - "--format=pretty" + test-collector#v1.10.2: + files: "reports/TEST-*.xml" + format: "junit" + branch: "^master|next$$" env: TEST_FIXTURE_SYMBOL_DIR: "build/fixture-r19" concurrency: 25 @@ -219,6 +240,13 @@ steps: - "--farm=bs" - "--device=ANDROID_8" - "--fail-fast" + - "--format=junit" + - "--out=reports" + - "--format=pretty" + test-collector#v1.10.2: + files: "reports/TEST-*.xml" + format: "junit" + branch: "^master|next$$" env: TEST_FIXTURE_SYMBOL_DIR: "build/fixture-r19" concurrency: 5 @@ -252,6 +280,13 @@ steps: - "--no-tunnel" - "--aws-public-ip" - "--fail-fast" + - "--format=junit" + - "--out=reports" + - "--format=pretty" + test-collector#v1.10.2: + files: "reports/TEST-*.xml" + format: "junit" + branch: "^master|next$$" env: TEST_FIXTURE_SYMBOL_DIR: "build/fixture-r21" concurrency: 25 @@ -315,6 +350,13 @@ steps: - "--no-tunnel" - "--aws-public-ip" - "--fail-fast" + - "--format=junit" + - "--out=reports" + - "--format=pretty" + test-collector#v1.10.2: + files: "reports/TEST-*.xml" + format: "junit" + branch: "^master|next$$" env: TEST_FIXTURE_SYMBOL_DIR: "build/fixture-r21" concurrency: 25 @@ -345,6 +387,13 @@ steps: - "--farm=bs" - "--device=ANDROID_10" - "--fail-fast" + - "--format=junit" + - "--out=reports" + - "--format=pretty" + test-collector#v1.10.2: + files: "reports/TEST-*.xml" + format: "junit" + branch: "^master|next$$" env: TEST_FIXTURE_SYMBOL_DIR: "build/fixture-r21" concurrency: 5 @@ -379,6 +428,13 @@ steps: - "--no-tunnel" - "--aws-public-ip" - "--fail-fast" + - "--format=junit" + - "--out=reports" + - "--format=pretty" + test-collector#v1.10.2: + files: "reports/TEST-*.xml" + format: "junit" + branch: "^master|next$$" env: TEST_FIXTURE_SYMBOL_DIR: "build/fixture-r21" concurrency: 25 @@ -410,6 +466,13 @@ steps: - "--farm=bs" - "--device=ANDROID_11" - "--fail-fast" + - "--format=junit" + - "--out=reports" + - "--format=pretty" + test-collector#v1.10.2: + files: "reports/TEST-*.xml" + format: "junit" + branch: "^master|next$$" env: TEST_FIXTURE_SYMBOL_DIR: "build/fixture-r21" concurrency: 5 @@ -449,6 +512,13 @@ steps: - "--no-tunnel" - "--aws-public-ip" - "--fail-fast" + - "--format=junit" + - "--out=reports" + - "--format=pretty" + test-collector#v1.10.2: + files: "reports/TEST-*.xml" + format: "junit" + branch: "^master|next$$" env: TEST_FIXTURE_SYMBOL_DIR: "build/fixture-r21" concurrency: 25 @@ -480,6 +550,13 @@ steps: - "--farm=bs" - "--device=ANDROID_12" - "--fail-fast" + - "--format=junit" + - "--out=reports" + - "--format=pretty" + test-collector#v1.10.2: + files: "reports/TEST-*.xml" + format: "junit" + branch: "^master|next$$" env: TEST_FIXTURE_SYMBOL_DIR: "build/fixture-r21" concurrency: 5 @@ -515,6 +592,13 @@ steps: - "--no-tunnel" - "--aws-public-ip" - "--fail-fast" + - "--format=junit" + - "--out=reports" + - "--format=pretty" + test-collector#v1.10.2: + files: "reports/TEST-*.xml" + format: "junit" + branch: "^master|next$$" env: TEST_FIXTURE_SYMBOL_DIR: "build/fixture-r21" concurrency: 25 @@ -548,6 +632,13 @@ steps: - "--no-tunnel" - "--aws-public-ip" - "--fail-fast" + - "--format=junit" + - "--out=reports" + - "--format=pretty" + test-collector#v1.10.2: + files: "reports/TEST-*.xml" + format: "junit" + branch: "^master|next$$" env: TEST_FIXTURE_SYMBOL_DIR: "build/fixture-r21" concurrency: 25 @@ -578,6 +669,13 @@ steps: - "--farm=bs" - "--device=ANDROID_13" - "--fail-fast" + - "--format=junit" + - "--out=reports" + - "--format=pretty" + test-collector#v1.10.2: + files: "reports/TEST-*.xml" + format: "junit" + branch: "^master|next$$" env: TEST_FIXTURE_SYMBOL_DIR: "build/fixture-r21" concurrency: 5 @@ -611,6 +709,13 @@ steps: - "--no-tunnel" - "--aws-public-ip" - "--fail-fast" + - "--format=junit" + - "--out=reports" + - "--format=pretty" + test-collector#v1.10.2: + files: "reports/TEST-*.xml" + format: "junit" + branch: "^master|next$$" env: TEST_FIXTURE_SYMBOL_DIR: "build/fixture-r21" concurrency: 25 @@ -641,6 +746,13 @@ steps: - "--farm=bs" - "--device=ANDROID_14" - "--fail-fast" + - "--format=junit" + - "--out=reports" + - "--format=pretty" + test-collector#v1.10.2: + files: "reports/TEST-*.xml" + format: "junit" + branch: "^master|next$$" env: TEST_FIXTURE_SYMBOL_DIR: "build/fixture-r21" concurrency: 5 diff --git a/CHANGELOG.md b/CHANGELOG.md index fbfa4b275d..4d7fa3c995 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,14 @@ * Add original error class and message to metadata for link errors loading BugSnag libraries [#2070](https://github.com/bugsnag/bugsnag-android/pull/2070) +### Bug fixes + +* Sending startup crashes synchronously now uses a flexible timeout so that apps with slower startups don't ANR + [#2075](https://github.com/bugsnag/bugsnag-android/pull/2075) + [#2080](https://github.com/bugsnag/bugsnag-android/pull/2080) +* Work around a possible platform NullPointerException when calling `Intent.getExtras` (https://github.com/bugsnag/bugsnag-android/issues/2082) + [#2083](https://github.com/bugsnag/bugsnag-android/pull/2083) + ## 6.7.0 (2024-08-08) ### Enhancements diff --git a/bugsnag-android-core/detekt-baseline.xml b/bugsnag-android-core/detekt-baseline.xml index 80214ff537..e4e75d4c39 100644 --- a/bugsnag-android-core/detekt-baseline.xml +++ b/bugsnag-android-core/detekt-baseline.xml @@ -49,6 +49,7 @@ ProtectedMemberInFinalClass:EventInternal.kt$EventInternal$protected fun updateSeverityReason(@SeverityReason.SeverityReasonType reason: String) ReturnCount:DefaultDelivery.kt$DefaultDelivery$fun deliver( urlString: String, json: ByteArray, headers: Map<String, String?> ): DeliveryStatus SpreadOperator:FileStore.kt$FileStore$(*listFiles) + SwallowedException:ActivityBreadcrumbCollector.kt$ActivityBreadcrumbCollector$re: Exception SwallowedException:AppDataCollector.kt$AppDataCollector$e: Exception SwallowedException:BugsnagEventMapper.kt$BugsnagEventMapper$pe: IllegalArgumentException SwallowedException:ConnectivityCompat.kt$ConnectivityLegacy$e: NullPointerException diff --git a/bugsnag-android-core/src/main/java/com/bugsnag/android/ActivityBreadcrumbCollector.kt b/bugsnag-android-core/src/main/java/com/bugsnag/android/ActivityBreadcrumbCollector.kt index b97a2eb86a..0b031a729c 100644 --- a/bugsnag-android-core/src/main/java/com/bugsnag/android/ActivityBreadcrumbCollector.kt +++ b/bugsnag-android-core/src/main/java/com/bugsnag/android/ActivityBreadcrumbCollector.kt @@ -79,6 +79,11 @@ internal class ActivityBreadcrumbCollector( } set("hasData", intent.data != null) - set("hasExtras", intent.extras?.keySet()?.joinToString(", ") ?: false) + + try { + set("hasExtras", intent.extras?.keySet()?.joinToString(", ") ?: false) + } catch (re: Exception) { + // deliberately ignore + } } } diff --git a/bugsnag-android-core/src/main/java/com/bugsnag/android/EventStore.kt b/bugsnag-android-core/src/main/java/com/bugsnag/android/EventStore.kt index e6d8401ae9..5c3360dee9 100644 --- a/bugsnag-android-core/src/main/java/com/bugsnag/android/EventStore.kt +++ b/bugsnag-android-core/src/main/java/com/bugsnag/android/EventStore.kt @@ -1,15 +1,16 @@ package com.bugsnag.android +import android.os.SystemClock import com.bugsnag.android.EventFilenameInfo.Companion.findTimestampInFilename import com.bugsnag.android.EventFilenameInfo.Companion.fromEvent import com.bugsnag.android.EventFilenameInfo.Companion.fromFile import com.bugsnag.android.JsonStream.Streamable import com.bugsnag.android.internal.BackgroundTaskService +import com.bugsnag.android.internal.ForegroundDetector import com.bugsnag.android.internal.ImmutableConfig import com.bugsnag.android.internal.TaskType import java.io.File import java.util.Calendar -import java.util.Comparator import java.util.Date import java.util.concurrent.Callable import java.util.concurrent.ExecutionException @@ -19,8 +20,7 @@ import java.util.concurrent.TimeUnit import java.util.concurrent.TimeoutException /** - * Store and flush Event reports which couldn't be sent immediately due to - * lack of network connectivity. + * Store and flush Event reports. */ internal class EventStore( private val config: ImmutableConfig, @@ -42,7 +42,8 @@ internal class EventStore( override val logger: Logger /** - * Flush startup crashes synchronously on the main thread + * Flush startup crashes synchronously on the main thread. Startup crashes block the main thread + * when being sent (subject to [Configuration.setSendLaunchCrashesSynchronously]) */ fun flushOnLaunch() { if (!config.sendLaunchCrashesSynchronously) { @@ -58,13 +59,28 @@ internal class EventStore( return } try { - future.get(LAUNCH_CRASH_TIMEOUT_MS, TimeUnit.MILLISECONDS) + // Calculate the maximum amount of time we are prepared to block while sending + // startup crashes, based on how long we think startup has taken so-far. + // This attempts to mitigate possible startup ANRs that can occur when other SDKs + // have blocked the main thread before this code is reached. + val currentStartupDuration = + SystemClock.elapsedRealtime() - ForegroundDetector.startupTime + var timeout = LAUNCH_CRASH_TIMEOUT_MS - currentStartupDuration + + if (timeout <= 0) { + // if Bugsnag.start is called too long after Application.onCreate is expected to + // have returned, we use a full LAUNCH_CRASH_TIMEOUT_MS instead of a calculated one + // assuming that the app is already fully started + timeout = LAUNCH_CRASH_TIMEOUT_MS + } + + future.get(timeout, TimeUnit.MILLISECONDS) } catch (exc: InterruptedException) { - logger.d("Failed to send launch crash reports within 2s timeout, continuing.", exc) + logger.d("Failed to send launch crash reports within timeout, continuing.", exc) } catch (exc: ExecutionException) { - logger.d("Failed to send launch crash reports within 2s timeout, continuing.", exc) + logger.d("Failed to send launch crash reports within timeout, continuing.", exc) } catch (exc: TimeoutException) { - logger.d("Failed to send launch crash reports within 2s timeout, continuing.", exc) + logger.d("Failed to send launch crash reports within timeout, continuing.", exc) } } @@ -159,6 +175,7 @@ internal class EventStore( deleteStoredFiles(setOf(eventFile)) logger.i("Deleting sent error file $eventFile.name") } + DeliveryStatus.UNDELIVERED -> undeliveredEventPayload(eventFile) DeliveryStatus.FAILURE -> { val exc: Exception = RuntimeException("Failed to deliver event payload") diff --git a/bugsnag-android-core/src/main/java/com/bugsnag/android/internal/ForegroundDetector.kt b/bugsnag-android-core/src/main/java/com/bugsnag/android/internal/ForegroundDetector.kt index 4308c8ee9a..548c56ebdc 100644 --- a/bugsnag-android-core/src/main/java/com/bugsnag/android/internal/ForegroundDetector.kt +++ b/bugsnag-android-core/src/main/java/com/bugsnag/android/internal/ForegroundDetector.kt @@ -55,6 +55,12 @@ internal object ForegroundDetector : ActivityLifecycleCallbacks, Handler.Callbac private var waitingForActivityRestart: Boolean = false + /** + * Marks the timestamp (relative to [SystemClock.elapsedRealtime]) that we initialised for the + * first time. + */ + internal val startupTime = SystemClock.elapsedRealtime() + @VisibleForTesting internal var backgroundSent = true diff --git a/bugsnag-android-core/src/test/java/com/bugsnag/android/ActivityLifecycleBreadcrumbTest.kt b/bugsnag-android-core/src/test/java/com/bugsnag/android/ActivityLifecycleBreadcrumbTest.kt index d0e2931e36..6f96abf640 100644 --- a/bugsnag-android-core/src/test/java/com/bugsnag/android/ActivityLifecycleBreadcrumbTest.kt +++ b/bugsnag-android-core/src/test/java/com/bugsnag/android/ActivityLifecycleBreadcrumbTest.kt @@ -1,6 +1,7 @@ package com.bugsnag.android import android.app.Activity +import android.content.Intent import android.os.Bundle import org.junit.Assert.assertEquals import org.junit.Assert.assertFalse @@ -10,6 +11,8 @@ import org.junit.Before import org.junit.Test import org.junit.runner.RunWith import org.mockito.Mock +import org.mockito.Mockito.mock +import org.mockito.Mockito.`when` import org.mockito.junit.MockitoJUnitRunner @RunWith(MockitoJUnitRunner::class) @@ -120,4 +123,15 @@ internal class ActivityLifecycleBreadcrumbTest { tracker.onActivityStarted(activity2) assertEquals("onCreate()", resultMetadata!!["previous"]) } + + @Test + fun failGetExtras() { + val mockIntent = mock(Intent::class.java) + `when`(mockIntent.extras).thenThrow(NullPointerException()) + `when`(activity.intent).thenReturn(mockIntent) + + tracker.onActivityCreated(activity, null) + assertFalse(resultMetadata!!["hasBundle"] as Boolean) + assertFalse(resultMetadata!!["hasData"] as Boolean) + } } diff --git a/docker-compose.yml b/docker-compose.yml index 0b1b4d07fe..3a1a174510 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -61,6 +61,7 @@ services: - ./build:/app/build - ./features/:/app/features/ - ./maze_output:/app/maze_output + - ./reports/:/app/reports/ - /var/run/docker.sock:/var/run/docker.sock android-license-audit: