diff --git a/embrace-android-core/src/main/kotlin/io/embrace/android/embracesdk/internal/config/behavior/AutoDataCaptureBehavior.kt b/embrace-android-core/src/main/kotlin/io/embrace/android/embracesdk/internal/config/behavior/AutoDataCaptureBehavior.kt index e2e4567961..aa052e5335 100644 --- a/embrace-android-core/src/main/kotlin/io/embrace/android/embracesdk/internal/config/behavior/AutoDataCaptureBehavior.kt +++ b/embrace-android-core/src/main/kotlin/io/embrace/android/embracesdk/internal/config/behavior/AutoDataCaptureBehavior.kt @@ -56,4 +56,9 @@ interface AutoDataCaptureBehavior { * for apps with a lot of local files. */ fun isDiskUsageCaptureEnabled(): Boolean + + /** + * Whether the SDK is configured to capture traces for the performance of the opening of Activities. + */ + fun isActivityOpenTracingEnabled(): Boolean } diff --git a/embrace-android-core/src/main/kotlin/io/embrace/android/embracesdk/internal/config/behavior/AutoDataCaptureBehaviorImpl.kt b/embrace-android-core/src/main/kotlin/io/embrace/android/embracesdk/internal/config/behavior/AutoDataCaptureBehaviorImpl.kt index 55a5268745..c12f452e71 100644 --- a/embrace-android-core/src/main/kotlin/io/embrace/android/embracesdk/internal/config/behavior/AutoDataCaptureBehaviorImpl.kt +++ b/embrace-android-core/src/main/kotlin/io/embrace/android/embracesdk/internal/config/behavior/AutoDataCaptureBehaviorImpl.kt @@ -27,6 +27,7 @@ class AutoDataCaptureBehaviorImpl( const val CRASH_HANDLER_ENABLED_DEFAULT = true const val CAPTURE_COMPOSE_ONCLICK_DEFAULT = false const val REPORT_DISK_USAGE_DEFAULT = true + const val ACTIVITY_OPEN_ENABLED_DEFAULT = false } override fun isMemoryWarningCaptureEnabled(): Boolean { @@ -80,4 +81,7 @@ class AutoDataCaptureBehaviorImpl( override fun isDiskUsageCaptureEnabled(): Boolean = local?.sdkConfig?.app?.reportDiskUsage ?: REPORT_DISK_USAGE_DEFAULT + + override fun isActivityOpenTracingEnabled(): Boolean = + local?.sdkConfig?.automaticDataCaptureConfig?.activityOpenEnabled ?: ACTIVITY_OPEN_ENABLED_DEFAULT } diff --git a/embrace-android-core/src/test/java/io/embrace/android/embracesdk/internal/config/behavior/AutoDataCaptureBehaviorImplTest.kt b/embrace-android-core/src/test/java/io/embrace/android/embracesdk/internal/config/behavior/AutoDataCaptureBehaviorImplTest.kt index f1a7e0e5e4..687ee6924a 100644 --- a/embrace-android-core/src/test/java/io/embrace/android/embracesdk/internal/config/behavior/AutoDataCaptureBehaviorImplTest.kt +++ b/embrace-android-core/src/test/java/io/embrace/android/embracesdk/internal/config/behavior/AutoDataCaptureBehaviorImplTest.kt @@ -24,7 +24,8 @@ internal class AutoDataCaptureBehaviorImplTest { memoryServiceEnabled = false, powerSaveModeServiceEnabled = false, networkConnectivityServiceEnabled = false, - anrServiceEnabled = false + anrServiceEnabled = false, + activityOpenEnabled = true, ), crashHandler = CrashHandlerLocalConfig(false), composeConfig = ComposeLocalConfig(true), @@ -53,6 +54,7 @@ internal class AutoDataCaptureBehaviorImplTest { assertFalse(isNativeCrashCaptureEnabled()) assertTrue(isDiskUsageCaptureEnabled()) assertTrue(isThermalStatusCaptureEnabled()) + assertFalse(isActivityOpenTracingEnabled()) } } @@ -68,6 +70,7 @@ internal class AutoDataCaptureBehaviorImplTest { assertTrue(is3rdPartySigHandlerDetectionEnabled()) assertTrue(isNativeCrashCaptureEnabled()) assertFalse(isDiskUsageCaptureEnabled()) + assertTrue(isActivityOpenTracingEnabled()) } } diff --git a/embrace-android-features/src/main/kotlin/io/embrace/android/embracesdk/internal/capture/startup/StartupTracker.kt b/embrace-android-features/src/main/kotlin/io/embrace/android/embracesdk/internal/capture/startup/StartupTracker.kt index be52e37449..49db6a3ec8 100644 --- a/embrace-android-features/src/main/kotlin/io/embrace/android/embracesdk/internal/capture/startup/StartupTracker.kt +++ b/embrace-android-features/src/main/kotlin/io/embrace/android/embracesdk/internal/capture/startup/StartupTracker.kt @@ -11,6 +11,7 @@ import android.view.ViewTreeObserver import android.view.Window import io.embrace.android.embracesdk.annotation.StartupActivity import io.embrace.android.embracesdk.internal.logging.EmbLogger +import io.embrace.android.embracesdk.internal.session.lifecycle.ActivityLifecycleListener import io.embrace.android.embracesdk.internal.utils.VersionChecker /** @@ -37,6 +38,7 @@ import io.embrace.android.embracesdk.internal.utils.VersionChecker */ class StartupTracker( private val appStartupDataCollector: AppStartupDataCollector, + private val activityOpenEventEmitter: ActivityLifecycleListener?, private val logger: EmbLogger, private val versionChecker: VersionChecker, ) : Application.ActivityLifecycleCallbacks { @@ -117,6 +119,9 @@ class StartupTracker( private fun startupComplete(application: Application) { if (!startupDataCollectionComplete) { application.unregisterActivityLifecycleCallbacks(this) + activityOpenEventEmitter?.apply { + application.registerActivityLifecycleCallbacks(this) + } startupDataCollectionComplete = true } } diff --git a/embrace-android-features/src/main/kotlin/io/embrace/android/embracesdk/internal/injection/DataCaptureServiceModule.kt b/embrace-android-features/src/main/kotlin/io/embrace/android/embracesdk/internal/injection/DataCaptureServiceModule.kt index 42684b4fd9..e6de121974 100644 --- a/embrace-android-features/src/main/kotlin/io/embrace/android/embracesdk/internal/injection/DataCaptureServiceModule.kt +++ b/embrace-android-features/src/main/kotlin/io/embrace/android/embracesdk/internal/injection/DataCaptureServiceModule.kt @@ -1,5 +1,7 @@ package io.embrace.android.embracesdk.internal.injection +import io.embrace.android.embracesdk.internal.capture.activity.OpenEventEmitter +import io.embrace.android.embracesdk.internal.capture.activity.OpenEvents import io.embrace.android.embracesdk.internal.capture.crumbs.ActivityBreadcrumbTracker import io.embrace.android.embracesdk.internal.capture.crumbs.PushNotificationCaptureService import io.embrace.android.embracesdk.internal.capture.startup.AppStartupDataCollector @@ -35,7 +37,11 @@ interface DataCaptureServiceModule { */ val startupService: StartupService + val appStartupDataCollector: AppStartupDataCollector + val startupTracker: StartupTracker - val appStartupDataCollector: AppStartupDataCollector + val activityOpenTraceEmitter: OpenEvents + + val activityOpenTracker: OpenEventEmitter? } diff --git a/embrace-android-features/src/main/kotlin/io/embrace/android/embracesdk/internal/injection/DataCaptureServiceModuleImpl.kt b/embrace-android-features/src/main/kotlin/io/embrace/android/embracesdk/internal/injection/DataCaptureServiceModuleImpl.kt index 23a6b73df2..2cd936e474 100644 --- a/embrace-android-features/src/main/kotlin/io/embrace/android/embracesdk/internal/injection/DataCaptureServiceModuleImpl.kt +++ b/embrace-android-features/src/main/kotlin/io/embrace/android/embracesdk/internal/injection/DataCaptureServiceModuleImpl.kt @@ -1,6 +1,9 @@ package io.embrace.android.embracesdk.internal.injection import io.embrace.android.embracesdk.internal.Systrace +import io.embrace.android.embracesdk.internal.capture.activity.OpenEventEmitter +import io.embrace.android.embracesdk.internal.capture.activity.OpenEvents +import io.embrace.android.embracesdk.internal.capture.activity.OpenTraceEmitter import io.embrace.android.embracesdk.internal.capture.crumbs.ActivityBreadcrumbTracker import io.embrace.android.embracesdk.internal.capture.crumbs.PushNotificationCaptureService import io.embrace.android.embracesdk.internal.capture.startup.AppStartupDataCollector @@ -63,8 +66,28 @@ internal class DataCaptureServiceModuleImpl @JvmOverloads constructor( override val startupTracker: StartupTracker by singleton { StartupTracker( appStartupDataCollector = appStartupDataCollector, + activityOpenEventEmitter = activityOpenTracker, logger = initModule.logger, versionChecker = versionChecker, ) } + + override val activityOpenTraceEmitter: OpenEvents by singleton { + OpenTraceEmitter( + spanService = openTelemetryModule.spanService, + versionChecker = versionChecker, + ) + } + + override val activityOpenTracker: OpenEventEmitter? by singleton { + if (configService.autoDataCaptureBehavior.isActivityOpenTracingEnabled()) { + OpenEventEmitter( + openEvents = activityOpenTraceEmitter, + clock = openTelemetryModule.openTelemetryClock, + versionChecker = versionChecker, + ) + } else { + null + } + } } diff --git a/embrace-android-features/src/test/java/io/embrace/android/embracesdk/internal/capture/startup/StartupTrackerTest.kt b/embrace-android-features/src/test/java/io/embrace/android/embracesdk/internal/capture/startup/StartupTrackerTest.kt index 76ef2eb736..598f37b928 100644 --- a/embrace-android-features/src/test/java/io/embrace/android/embracesdk/internal/capture/startup/StartupTrackerTest.kt +++ b/embrace-android-features/src/test/java/io/embrace/android/embracesdk/internal/capture/startup/StartupTrackerTest.kt @@ -10,6 +10,7 @@ import io.embrace.android.embracesdk.fakes.FakeClock import io.embrace.android.embracesdk.fakes.FakeEmbLogger import io.embrace.android.embracesdk.fakes.FakeSplashScreenActivity import io.embrace.android.embracesdk.internal.logging.EmbLogger +import io.embrace.android.embracesdk.internal.session.lifecycle.ActivityLifecycleListener import io.embrace.android.embracesdk.internal.utils.BuildVersionChecker import org.junit.Assert.assertEquals import org.junit.Before @@ -37,6 +38,7 @@ internal class StartupTrackerTest { dataCollector = FakeAppStartupDataCollector(clock = clock) startupTracker = StartupTracker( appStartupDataCollector = dataCollector, + activityOpenEventEmitter = object : ActivityLifecycleListener { }, logger = logger, versionChecker = BuildVersionChecker ) diff --git a/embrace-android-payload/src/main/kotlin/io/embrace/android/embracesdk/internal/config/local/AutomaticDataCaptureLocalConfig.kt b/embrace-android-payload/src/main/kotlin/io/embrace/android/embracesdk/internal/config/local/AutomaticDataCaptureLocalConfig.kt index 85df3e9709..eb4549820c 100644 --- a/embrace-android-payload/src/main/kotlin/io/embrace/android/embracesdk/internal/config/local/AutomaticDataCaptureLocalConfig.kt +++ b/embrace-android-payload/src/main/kotlin/io/embrace/android/embracesdk/internal/config/local/AutomaticDataCaptureLocalConfig.kt @@ -11,5 +11,7 @@ class AutomaticDataCaptureLocalConfig( @Json(name = "network_connectivity_info") val networkConnectivityServiceEnabled: Boolean? = null, - @Json(name = "anr_info") val anrServiceEnabled: Boolean? = null + @Json(name = "anr_info") val anrServiceEnabled: Boolean? = null, + + @Json(name = "activity_open_info") val activityOpenEnabled: Boolean? = null ) diff --git a/embrace-android-sdk/src/integrationTest/kotlin/io/embrace/android/embracesdk/IntegrationTestRuleExtensions.kt b/embrace-android-sdk/src/integrationTest/kotlin/io/embrace/android/embracesdk/IntegrationTestRuleExtensions.kt index 8594f7be1b..1a774a770a 100644 --- a/embrace-android-sdk/src/integrationTest/kotlin/io/embrace/android/embracesdk/IntegrationTestRuleExtensions.kt +++ b/embrace-android-sdk/src/integrationTest/kotlin/io/embrace/android/embracesdk/IntegrationTestRuleExtensions.kt @@ -11,6 +11,7 @@ import io.embrace.android.embracesdk.internal.utils.Provider import org.json.JSONObject import org.junit.Assert import org.robolectric.Robolectric +import org.robolectric.android.controller.ActivityController import java.io.IOException import java.util.concurrent.CountDownLatch import java.util.concurrent.TimeUnit @@ -153,6 +154,62 @@ internal fun IntegrationTestRule.Harness.recordSession( return getLastSentSession() } +internal fun IntegrationTestRule.Harness.openActivities( + addStartupActivity: Boolean = true, + startInBackground: Boolean = false, + createFirstActivity: Boolean = true, + activitiesAndActions: List, () -> Unit>> = listOf(), + lifecycleEventGap: Long = 100L, + postActionDwell: Long = 20000L, + activityGap: Long = 50L, +): Envelope? { + val activityService = checkNotNull(Embrace.getImpl().activityService) + var lastActivity: ActivityController<*>? = if (addStartupActivity) { + Robolectric.buildActivity(Activity::class.java) + } else { + null + }?.apply { + create() + start() + activityService.onForeground() + resume() + pause() + if (startInBackground) { + stop() + activityService.onBackground() + overriddenClock.tick(10000L) + } else { + overriddenClock.tick(activityGap) + } + } + activitiesAndActions.forEachIndexed { index, (activityController, action) -> + if (index != 0 || createFirstActivity) { + activityController.create() + overriddenClock.tick(lifecycleEventGap) + } + activityController.start() + overriddenClock.tick(lifecycleEventGap) + if (index == 0 && startInBackground) { + activityService.onForeground() + } + activityController.resume() + overriddenClock.tick(lifecycleEventGap) + lastActivity?.stop() + overriddenClock.tick() + + action() + + overriddenClock.tick(postActionDwell) + activityController.pause() + overriddenClock.tick(activityGap) + lastActivity = activityController + } + lastActivity?.stop() + overriddenClock.tick() + activityService.onBackground() + return getLastSentSession() +} + /** * Validates a payload against a golden file in the test resources. If the payload does not match * the golden file, the assertion fails. diff --git a/embrace-android-sdk/src/integrationTest/kotlin/io/embrace/android/embracesdk/features/ActivityOpenTest.kt b/embrace-android-sdk/src/integrationTest/kotlin/io/embrace/android/embracesdk/features/ActivityOpenTest.kt new file mode 100644 index 0000000000..84c63bb679 --- /dev/null +++ b/embrace-android-sdk/src/integrationTest/kotlin/io/embrace/android/embracesdk/features/ActivityOpenTest.kt @@ -0,0 +1,221 @@ +package io.embrace.android.embracesdk.features + +import android.app.Activity +import android.os.Build +import androidx.test.ext.junit.runners.AndroidJUnit4 +import io.embrace.android.embracesdk.IntegrationTestRule +import io.embrace.android.embracesdk.annotation.ObservedActivity +import io.embrace.android.embracesdk.assertions.assertEmbraceSpanData +import io.embrace.android.embracesdk.fakes.fakeAutoDataCaptureBehavior +import io.embrace.android.embracesdk.findSpansByName +import io.embrace.android.embracesdk.findSpansOfType +import io.embrace.android.embracesdk.getLastSentBackgroundActivity +import io.embrace.android.embracesdk.internal.arch.schema.EmbType +import io.embrace.android.embracesdk.internal.capture.activity.OpenTraceEmitter.LifecycleEvent +import io.embrace.android.embracesdk.internal.config.local.AutomaticDataCaptureLocalConfig +import io.embrace.android.embracesdk.internal.config.local.LocalConfig +import io.embrace.android.embracesdk.internal.config.local.SdkLocalConfig +import io.embrace.android.embracesdk.openActivities +import io.opentelemetry.api.trace.SpanId +import org.junit.Assert.assertEquals +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith +import org.robolectric.Robolectric +import org.robolectric.annotation.Config + +@RunWith(AndroidJUnit4::class) +internal class ActivityOpenTest { + + @Rule + @JvmField + val testRule = IntegrationTestRule { + IntegrationTestRule.Harness(startImmediately = false) + } + + @Config(sdk = [Build.VERSION_CODES.LOLLIPOP]) + @Test + fun `activity open does not create a trace if feature flag is disabled`() { + with(testRule) { + startSdk() + val payload = checkNotNull( + harness.openActivities( + addStartupActivity = false, + startInBackground = true, + activitiesAndActions = listOf( + Robolectric.buildActivity(Activity1::class.java) to {}, + Robolectric.buildActivity(Activity2::class.java) to {}, + ) + ) + ) + + assertEquals(0, payload.findSpansOfType(EmbType.Performance.ActivityOpen).size) + } + } + + @Config(sdk = [Build.VERSION_CODES.LOLLIPOP]) + @Test + fun `opening first non-startup activity creates cold open trace in L`() { + with(testRule) { + enableActivityOpenTracing() + startSdk() + val preLaunchTimeMs = harness.overriddenClock.now() + val payload = checkNotNull( + harness.openActivities( + addStartupActivity = false, + startInBackground = true, + activitiesAndActions = listOf( + Robolectric.buildActivity(Activity1::class.java) to {}, + Robolectric.buildActivity(Activity2::class.java) to {}, + ) + ) + ) + + val trace = payload.findSpansOfType(EmbType.Performance.ActivityOpen).single() + assertEquals("emb-$ACTIVITY2_NAME-cold-open", trace.name) + val rootSpanId = checkNotNull(trace.spanId) + + val expectedTraceStartTime = preLaunchTimeMs + 20301 + assertEmbraceSpanData( + span = trace, + expectedStartTimeMs = expectedTraceStartTime, + expectedEndTimeMs = expectedTraceStartTime + 250, + expectedParentId = SpanId.getInvalid(), + key = true + ) + + assertEmbraceSpanData( + span = payload.findSpansByName("emb-${LifecycleEvent.CREATE.spanName(ACTIVITY2_NAME)}").single(), + expectedStartTimeMs = expectedTraceStartTime + 50, + expectedEndTimeMs = expectedTraceStartTime + 150, + expectedParentId = rootSpanId, + ) + + assertEmbraceSpanData( + span = payload.findSpansByName("emb-${LifecycleEvent.START.spanName(ACTIVITY2_NAME)}").single(), + expectedStartTimeMs = expectedTraceStartTime + 150, + expectedEndTimeMs = expectedTraceStartTime + 250, + expectedParentId = rootSpanId, + ) + } + } + + @Config(sdk = [Build.VERSION_CODES.LOLLIPOP]) + @Test + fun `foregrounding and initializing new activity creates cold open trace in L`() { + with(testRule) { + enableActivityOpenTracing() + startSdk() + val preLaunchTimeMs = harness.overriddenClock.now() + val payload = checkNotNull( + harness.openActivities( + addStartupActivity = true, + startInBackground = true, + activitiesAndActions = listOf( + Robolectric.buildActivity(Activity1::class.java) to {} + ) + ) + ) + + val trace = payload.findSpansOfType(EmbType.Performance.ActivityOpen).single() + assertEquals("emb-$ACTIVITY1_NAME-cold-open", trace.name) + val rootSpanId = checkNotNull(trace.spanId) + + val expectedTraceStartTime = preLaunchTimeMs + 10000 + assertEmbraceSpanData( + span = trace, + expectedStartTimeMs = expectedTraceStartTime, + expectedEndTimeMs = expectedTraceStartTime + 200, + expectedParentId = SpanId.getInvalid(), + key = true + ) + + val lastBackgroundActivity = checkNotNull(harness.getLastSentBackgroundActivity()) + assertEmbraceSpanData( + span = lastBackgroundActivity.findSpansByName("emb-${LifecycleEvent.CREATE.spanName(ACTIVITY1_NAME)}").single(), + expectedStartTimeMs = expectedTraceStartTime, + expectedEndTimeMs = expectedTraceStartTime + 100, + expectedParentId = rootSpanId, + ) + + assertEmbraceSpanData( + span = payload.findSpansByName("emb-${LifecycleEvent.START.spanName(ACTIVITY1_NAME)}").single(), + expectedStartTimeMs = expectedTraceStartTime + 100, + expectedEndTimeMs = expectedTraceStartTime + 200, + expectedParentId = rootSpanId, + ) + } + } + + @Config(sdk = [Build.VERSION_CODES.LOLLIPOP]) + @Test + fun `foregrounding already-created activity creates hot open trace in L`() { + with(testRule) { + enableActivityOpenTracing() + startSdk() + val preLaunchTimeMs = harness.overriddenClock.now() + val payload = checkNotNull( + harness.openActivities( + addStartupActivity = true, + startInBackground = true, + createFirstActivity = false, + activitiesAndActions = listOf( + Robolectric.buildActivity(Activity1::class.java) to {}, + ) + ) + ) + + val trace = payload.findSpansOfType(EmbType.Performance.ActivityOpen).single() + assertEquals("emb-$ACTIVITY1_NAME-hot-open", trace.name) + val rootSpanId = checkNotNull(trace.spanId) + + val expectedTraceStartTime = preLaunchTimeMs + 10000 + assertEmbraceSpanData( + span = trace, + expectedStartTimeMs = expectedTraceStartTime, + expectedEndTimeMs = expectedTraceStartTime + 100, + expectedParentId = SpanId.getInvalid(), + key = true + ) + + assertEmbraceSpanData( + span = payload.findSpansByName("emb-${LifecycleEvent.START.spanName(ACTIVITY1_NAME)}").single(), + expectedStartTimeMs = expectedTraceStartTime, + expectedEndTimeMs = expectedTraceStartTime + 100, + expectedParentId = rootSpanId, + ) + } + } + + private fun enableActivityOpenTracing() { + with(testRule) { + val appId = harness.overriddenConfigService.appId + val ndkEnabled = harness.overriddenConfigService.autoDataCaptureBehavior.isNdkEnabled() + harness.overriddenConfigService.autoDataCaptureBehavior = + fakeAutoDataCaptureBehavior( + localCfg = { + LocalConfig( + appId = appId, + ndkEnabled = ndkEnabled, + sdkConfig = SdkLocalConfig( + automaticDataCaptureConfig = AutomaticDataCaptureLocalConfig( + activityOpenEnabled = true + ) + ) + ) + } + ) + } + } + + private companion object { + @ObservedActivity + class Activity1 : Activity() + + @ObservedActivity + class Activity2 : Activity() + + val ACTIVITY1_NAME = Robolectric.buildActivity(Activity1::class.java).get().localClassName + val ACTIVITY2_NAME = Robolectric.buildActivity(Activity2::class.java).get().localClassName + } +} \ No newline at end of file diff --git a/embrace-android-sdk/src/main/java/io/embrace/android/embracesdk/internal/injection/ModuleInitBootstrapper.kt b/embrace-android-sdk/src/main/java/io/embrace/android/embracesdk/internal/injection/ModuleInitBootstrapper.kt index f97a0d6547..a790e15ed1 100644 --- a/embrace-android-sdk/src/main/java/io/embrace/android/embracesdk/internal/injection/ModuleInitBootstrapper.kt +++ b/embrace-android-sdk/src/main/java/io/embrace/android/embracesdk/internal/injection/ModuleInitBootstrapper.kt @@ -271,7 +271,8 @@ internal class ModuleInitBootstrapper( serviceRegistry.registerServices( lazy { dataCaptureServiceModule.webviewService }, lazy { dataCaptureServiceModule.activityBreadcrumbTracker }, - lazy { dataCaptureServiceModule.pushNotificationService } + lazy { dataCaptureServiceModule.pushNotificationService }, + lazy { dataCaptureServiceModule.activityOpenTraceEmitter }, ) } diff --git a/embrace-android-sdk/src/test/java/io/embrace/android/embracesdk/fakes/injection/FakeDataCaptureServiceModule.kt b/embrace-android-sdk/src/test/java/io/embrace/android/embracesdk/fakes/injection/FakeDataCaptureServiceModule.kt index 4d1039647d..1464936278 100644 --- a/embrace-android-sdk/src/test/java/io/embrace/android/embracesdk/fakes/injection/FakeDataCaptureServiceModule.kt +++ b/embrace-android-sdk/src/test/java/io/embrace/android/embracesdk/fakes/injection/FakeDataCaptureServiceModule.kt @@ -4,6 +4,8 @@ import io.embrace.android.embracesdk.fakes.FakeConfigService import io.embrace.android.embracesdk.fakes.FakeFeatureModule import io.embrace.android.embracesdk.fakes.FakeStartupService import io.embrace.android.embracesdk.fakes.FakeWebViewService +import io.embrace.android.embracesdk.internal.capture.activity.OpenEventEmitter +import io.embrace.android.embracesdk.internal.capture.activity.OpenEvents import io.embrace.android.embracesdk.internal.capture.crumbs.ActivityBreadcrumbTracker import io.embrace.android.embracesdk.internal.capture.crumbs.PushNotificationCaptureService import io.embrace.android.embracesdk.internal.capture.startup.AppStartupDataCollector @@ -24,7 +26,11 @@ internal class FakeDataCaptureServiceModule( override val startupService: StartupService = FakeStartupService() + override val appStartupDataCollector: AppStartupDataCollector = mockk(relaxed = true) + override val startupTracker: StartupTracker = mockk(relaxed = true) - override val appStartupDataCollector: AppStartupDataCollector = mockk(relaxed = true) + override val activityOpenTraceEmitter: OpenEvents = mockk(relaxed = true) + + override val activityOpenTracker: OpenEventEmitter = mockk(relaxed = true) }