Skip to content

Commit 231e760

Browse files
committed
[RUM-8875] Add ability to manually add an activity to JankStats
Unity's main activity is started prior to initializing Datadog, so it misses adding the Activity to JankStats tracking. Add an internal method to allow manually adding an activity to JankStats tracking.
1 parent 146a8c9 commit 231e760

File tree

11 files changed

+112
-0
lines changed

11 files changed

+112
-0
lines changed

features/dd-sdk-android-rum/api/apiSurface

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,7 @@ class com.datadog.android.rum._RumInternalProxy
160160
fun updatePerformanceMetric(RumPerformanceMetric, Double)
161161
fun setInternalViewAttribute(String, Any?)
162162
fun setSyntheticsAttribute(String?, String?)
163+
fun enableJankStatsTracking(android.app.Activity)
163164
companion object
164165
fun setTelemetryConfigurationEventMapper(RumConfiguration.Builder, com.datadog.android.event.EventMapper<com.datadog.android.telemetry.model.TelemetryConfigurationEvent>): RumConfiguration.Builder
165166
fun setAdditionalConfiguration(RumConfiguration.Builder, Map<String, Any>): RumConfiguration.Builder

features/dd-sdk-android-rum/api/dd-sdk-android-rum.api

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,7 @@ public final class com/datadog/android/rum/_RumInternalProxy {
235235
public static final field Companion Lcom/datadog/android/rum/_RumInternalProxy$Companion;
236236
public final fun addLongTask (JLjava/lang/String;)V
237237
public final fun setInternalViewAttribute (Ljava/lang/String;Ljava/lang/Object;)V
238+
public final fun enableJankStatsTracking (Landroid/app/Activity;)V
238239
public final fun setSyntheticsAttribute (Ljava/lang/String;Ljava/lang/String;)V
239240
public final fun updatePerformanceMetric (Lcom/datadog/android/rum/RumPerformanceMetric;D)V
240241
}

features/dd-sdk-android-rum/src/main/kotlin/com/datadog/android/rum/_RumInternalProxy.kt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
package com.datadog.android.rum
88

9+
import android.app.Activity
910
import android.content.Intent
1011
import com.datadog.android.event.EventMapper
1112
import com.datadog.android.lint.InternalApi
@@ -60,6 +61,15 @@ class _RumInternalProxy internal constructor(private val rumMonitor: AdvancedRum
6061
rumMonitor.setSyntheticsAttribute(testId, resultId)
6162
}
6263

64+
/**
65+
* Enables the tracking of JankStats for the given activity. This should only be necessary for the
66+
* initial activity of an application if Datadog is initialized after that activity is created.
67+
* @param activity the activity to track
68+
*/
69+
fun enableJankStatsTracking(activity: Activity) {
70+
rumMonitor.enableJankStatsTracking(activity)
71+
}
72+
6373
internal fun setSyntheticsAttributeFromIntent(intent: Intent) {
6474
@Suppress("TooGenericExceptionCaught")
6575
val extras = try { intent.extras } catch (_: Exception) { null }

features/dd-sdk-android-rum/src/main/kotlin/com/datadog/android/rum/internal/RumFeature.kt

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
package com.datadog.android.rum.internal
88

9+
import android.app.Activity
910
import android.app.ActivityManager
1011
import android.app.Application
1112
import android.app.ApplicationExitInfo
@@ -379,6 +380,24 @@ internal class RumFeature(
379380
}
380381
}
381382

383+
/**
384+
* Enables the tracking of JankStats for the given activity. This should only be necessary for the
385+
* initial activity of an application if Datadog is initialized after that activity is created.
386+
* @param activity the activity to track
387+
*/
388+
internal fun enableJankStatsTracking(activity: Activity) {
389+
try {
390+
jankStatsActivityLifecycleListener?.onActivityStarted(activity)
391+
} catch (@Suppress("TooGenericExceptionCaught") e: Exception) {
392+
sdkCore.internalLogger.log(
393+
InternalLogger.Level.ERROR,
394+
InternalLogger.Target.TELEMETRY,
395+
{ FAILED_TO_ENABLE_JANK_STATS_TRACKING_MANUALLY },
396+
e
397+
)
398+
}
399+
}
400+
382401
private fun registerTrackingStrategies(appContext: Context) {
383402
actionTrackingStrategy.register(sdkCore, appContext)
384403
viewTrackingStrategy.register(sdkCore, appContext)
@@ -619,6 +638,8 @@ internal class RumFeature(
619638
internal const val RUM_FEATURE_NOT_YET_INITIALIZED =
620639
"RUM feature is not initialized yet, you need to register it with a" +
621640
" SDK instance by calling SdkCore#registerFeature method."
641+
internal const val FAILED_TO_ENABLE_JANK_STATS_TRACKING_MANUALLY =
642+
"Manually enabling JankStats tracking threw an exception."
622643

623644
private fun provideUserTrackingStrategy(
624645
touchTargetExtraAttributesProviders: Array<ViewAttributesProvider>,

features/dd-sdk-android-rum/src/main/kotlin/com/datadog/android/rum/internal/monitor/AdvancedRumMonitor.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
package com.datadog.android.rum.internal.monitor
88

9+
import android.app.Activity
910
import com.datadog.android.core.feature.event.ThreadDump
1011
import com.datadog.android.internal.telemetry.InternalTelemetryEvent
1112
import com.datadog.android.rum.RumErrorSource
@@ -51,4 +52,6 @@ internal interface AdvancedRumMonitor : RumMonitor, AdvancedNetworkRumMonitor {
5152
fun setInternalViewAttribute(key: String, value: Any?)
5253

5354
fun setSyntheticsAttribute(testId: String, resultId: String)
55+
56+
fun enableJankStatsTracking(activity: Activity)
5457
}

features/dd-sdk-android-rum/src/main/kotlin/com/datadog/android/rum/internal/monitor/DatadogRumMonitor.kt

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
package com.datadog.android.rum.internal.monitor
88

9+
import android.app.Activity
910
import android.app.ActivityManager
1011
import android.os.Handler
1112
import com.datadog.android.api.InternalLogger
@@ -644,6 +645,16 @@ internal class DatadogRumMonitor(
644645
handleEvent(RumRawEvent.TelemetryEventWrapper(telemetryEvent))
645646
}
646647

648+
override fun enableJankStatsTracking(activity: Activity) {
649+
val rumFeatureScope = sdkCore.getFeature(Feature.RUM_FEATURE_NAME)
650+
?.unwrap<RumFeature>()
651+
if (rumFeatureScope == null) {
652+
return
653+
}
654+
655+
rumFeatureScope.enableJankStatsTracking(activity)
656+
}
657+
647658
// endregion
648659

649660
// region Internal

features/dd-sdk-android-rum/src/main/kotlin/com/datadog/android/rum/internal/vitals/JankStatsActivityLifecycleListener.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,9 @@ internal class JankStatsActivityLifecycleListener(
165165

166166
private fun trackActivity(window: Window, activity: Activity) {
167167
val list = activeActivities[window] ?: mutableListOf()
168+
if (list.find { it.get() == activity } != null) {
169+
return
170+
}
168171
list.add(WeakReference(activity))
169172
activeActivities[window] = list
170173
}

features/dd-sdk-android-rum/src/test/kotlin/com/datadog/android/rum/RumInternalProxyTest.kt

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
package com.datadog.android.rum
88

9+
import android.app.Activity
910
import com.datadog.android.rum.internal.monitor.AdvancedRumMonitor
1011
import com.datadog.android.rum.utils.forge.Configurator
1112
import fr.xgouchet.elmyr.Forge
@@ -62,4 +63,18 @@ internal class RumInternalProxyTest {
6263
// Then
6364
verify(mockRumMonitor).updatePerformanceMetric(metric, value)
6465
}
66+
67+
@Test
68+
fun `M proxy enableJankStatsTracking to RumMonitor W enableJankStatsTracking()`() {
69+
// Given
70+
val mockRumMonitor = mock(AdvancedRumMonitor::class.java)
71+
val proxy = _RumInternalProxy(mockRumMonitor)
72+
val activity: Activity = mock()
73+
74+
// When
75+
proxy.enableJankStatsTracking(activity)
76+
77+
// Then
78+
verify(mockRumMonitor).enableJankStatsTracking(activity)
79+
}
6580
}

features/dd-sdk-android-rum/src/test/kotlin/com/datadog/android/rum/internal/RumFeatureTest.kt

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
package com.datadog.android.rum.internal
88

9+
import android.app.Activity
910
import android.app.ActivityManager
1011
import android.app.Application
1112
import android.app.ApplicationExitInfo
@@ -534,6 +535,25 @@ internal class RumFeatureTest {
534535
.isNull()
535536
}
536537

538+
@Test
539+
fun `M call onActivityStarted W enableJankStatsTracking()`() {
540+
// Given
541+
val activity: Activity = mock()
542+
testedFeature = RumFeature(
543+
mockSdkCore,
544+
fakeApplicationId.toString(),
545+
fakeConfiguration,
546+
lateCrashReporterFactory = { mockLateCrashReporter }
547+
)
548+
testedFeature.jankStatsActivityLifecycleListener = mock()
549+
550+
// When
551+
testedFeature.enableJankStatsTracking(activity)
552+
553+
// Then
554+
verify(testedFeature.jankStatsActivityLifecycleListener)!!.onActivityStarted(activity)
555+
}
556+
537557
@Test
538558
fun `M use noop viewTrackingStrategy W onStop()`() {
539559
// Given

features/dd-sdk-android-rum/src/test/kotlin/com/datadog/android/rum/internal/monitor/DatadogRumMonitorTest.kt

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
package com.datadog.android.rum.internal.monitor
88

9+
import android.app.Activity
910
import android.app.ActivityManager
1011
import android.os.Handler
1112
import com.datadog.android.api.InternalLogger
@@ -1911,6 +1912,22 @@ internal class DatadogRumMonitorTest {
19111912
}
19121913
}
19131914

1915+
@Test
1916+
fun `M call enableJankStatsTracking on RUM feature W enableJankStatsTracking`() {
1917+
// Given
1918+
val mockActivity = mock<Activity>()
1919+
val mockRumScope = mock<FeatureScope>()
1920+
whenever(mockSdkCore.getFeature(Feature.RUM_FEATURE_NAME)) doReturn mockRumScope
1921+
val mockRumFeature = mock<RumFeature>()
1922+
whenever(mockRumScope.unwrap<RumFeature>()) doReturn mockRumFeature
1923+
1924+
// When
1925+
testedMonitor.enableJankStatsTracking(mockActivity)
1926+
1927+
// Then
1928+
verify(mockRumFeature).enableJankStatsTracking(mockActivity)
1929+
}
1930+
19141931
@Test
19151932
fun `M call sessionEndedMetricDispatcher W addSkippedFrame`(
19161933
@IntForgery(min = 0, max = 100) count: Int,

0 commit comments

Comments
 (0)