Skip to content

Commit fd31d41

Browse files
Merge pull request #2921 from DataDog/aleksandr-gringauz/feature/app-launch-prs
Umbrella PR for TTID telemetry reporting
2 parents 7fa9000 + 7f05efa commit fd31d41

File tree

52 files changed

+2287
-106
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

52 files changed

+2287
-106
lines changed

dd-sdk-android-core/src/main/kotlin/com/datadog/android/core/internal/DatadogCore.kt

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -743,8 +743,5 @@ internal class DatadogCore(
743743
"SDK core already has \"%s\" listener registered."
744744

745745
internal val CONFIGURATION_TELEMETRY_DELAY_MS = TimeUnit.SECONDS.toMillis(5)
746-
747-
// fallback for APIs below Android N, see [DefaultAppStartTimeProvider].
748-
internal val startupTimeNs: Long = System.nanoTime()
749746
}
750747
}

dd-sdk-android-core/src/main/kotlin/com/datadog/android/core/internal/time/DefaultAppStartTimeProvider.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ import android.annotation.SuppressLint
1010
import android.os.Build
1111
import android.os.Process
1212
import android.os.SystemClock
13-
import com.datadog.android.core.internal.DatadogCore
1413
import com.datadog.android.core.internal.system.BuildSdkVersionProvider
14+
import com.datadog.android.rum.DdRumContentProvider
1515
import java.util.concurrent.TimeUnit
1616

1717
internal class DefaultAppStartTimeProvider(
@@ -25,7 +25,7 @@ internal class DefaultAppStartTimeProvider(
2525
val diffMs = SystemClock.elapsedRealtime() - Process.getStartElapsedRealtime()
2626
System.nanoTime() - TimeUnit.MILLISECONDS.toNanos(diffMs)
2727
}
28-
else -> DatadogCore.startupTimeNs
28+
else -> DdRumContentProvider.createTimeNs
2929
}
3030
}
3131
}

dd-sdk-android-core/src/test/kotlin/com/datadog/android/core/internal/time/DefaultAppStartTimeProviderTest.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ package com.datadog.android.core.internal.time
99
import android.os.Build
1010
import android.os.Process
1111
import android.os.SystemClock
12-
import com.datadog.android.core.internal.DatadogCore
1312
import com.datadog.android.core.internal.system.BuildSdkVersionProvider
13+
import com.datadog.android.rum.DdRumContentProvider
1414
import fr.xgouchet.elmyr.annotation.IntForgery
1515
import fr.xgouchet.elmyr.junit5.ForgeExtension
1616
import org.assertj.core.api.Assertions.assertThat
@@ -47,13 +47,13 @@ class DefaultAppStartTimeProviderTest {
4747
}
4848

4949
@Test
50-
fun `M return rum load time W appStartTime { Legacy }`(
50+
fun `M return content provider load time W appStartTime { Legacy }`(
5151
@IntForgery(min = Build.VERSION_CODES.M, max = Build.VERSION_CODES.N) apiVersion: Int
5252
) {
5353
// GIVEN
5454
val mockBuildSdkVersionProvider: BuildSdkVersionProvider = mock()
5555
whenever(mockBuildSdkVersionProvider.version) doReturn apiVersion
56-
val startTimeNs = DatadogCore.startupTimeNs
56+
val startTimeNs = DdRumContentProvider.createTimeNs
5757

5858
// WHEN
5959
val timeProvider = DefaultAppStartTimeProvider(mockBuildSdkVersionProvider)

dd-sdk-android-internal/api/apiSurface

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,13 @@ interface com.datadog.android.internal.time.TimeProvider
100100
fun getServerOffsetNanos(): Long
101101
fun getServerOffsetMillis(): Long
102102
fun ByteArray.toHexString(): String
103+
interface com.datadog.android.internal.utils.DDCoreSubscription<T: Any>
104+
fun addListener(T)
105+
fun removeListener(T)
106+
fun notifyListeners(T.() -> Unit)
107+
val listenersCount: Int
108+
companion object
109+
fun <T: Any> create(): DDCoreSubscription<T>
103110
object com.datadog.android.internal.utils.ImageViewUtils
104111
fun resolveParentRectAbsPosition(android.view.View, Boolean = true): android.graphics.Rect
105112
fun calculateClipping(android.graphics.Rect, android.graphics.Rect, Float): android.graphics.Rect
@@ -118,5 +125,15 @@ fun Thread.safeGetThreadId(): Long
118125
fun Thread.State.asString(): String
119126
fun Array<StackTraceElement>.loggableStackTrace(): String
120127
fun Throwable.loggableStackTrace(): String
128+
class com.datadog.android.rum.DdRumContentProvider : android.content.ContentProvider
129+
override fun onCreate(): Boolean
130+
override fun query(android.net.Uri, Array<String>?, String?, Array<String>?, String?): android.database.Cursor?
131+
override fun getType(android.net.Uri): String?
132+
override fun insert(android.net.Uri, android.content.ContentValues?): android.net.Uri?
133+
override fun delete(android.net.Uri, String?, Array<String>?): Int
134+
override fun update(android.net.Uri, android.content.ContentValues?, String?, Array<String>?): Int
135+
companion object
136+
var processImportance: Int
137+
val createTimeNs: Long
121138
annotation com.datadog.tools.annotation.NoOpImplementation
122139
constructor(Boolean = false)

dd-sdk-android-internal/api/dd-sdk-android-internal.api

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,18 @@ public final class com/datadog/android/internal/utils/ByteArrayExtKt {
259259
public static final fun toHexString ([B)Ljava/lang/String;
260260
}
261261

262+
public abstract interface class com/datadog/android/internal/utils/DDCoreSubscription {
263+
public static final field Companion Lcom/datadog/android/internal/utils/DDCoreSubscription$Companion;
264+
public abstract fun addListener (Ljava/lang/Object;)V
265+
public abstract fun getListenersCount ()I
266+
public abstract fun notifyListeners (Lkotlin/jvm/functions/Function1;)V
267+
public abstract fun removeListener (Ljava/lang/Object;)V
268+
}
269+
270+
public final class com/datadog/android/internal/utils/DDCoreSubscription$Companion {
271+
public final fun create ()Lcom/datadog/android/internal/utils/DDCoreSubscription;
272+
}
273+
262274
public final class com/datadog/android/internal/utils/ImageViewUtils {
263275
public static final field INSTANCE Lcom/datadog/android/internal/utils/ImageViewUtils;
264276
public final fun calculateClipping (Landroid/graphics/Rect;Landroid/graphics/Rect;F)Landroid/graphics/Rect;
@@ -306,6 +318,23 @@ public final class com/datadog/android/internal/utils/ThrowableExtKt {
306318
public static final fun loggableStackTrace (Ljava/lang/Throwable;)Ljava/lang/String;
307319
}
308320

321+
public final class com/datadog/android/rum/DdRumContentProvider : android/content/ContentProvider {
322+
public static final field Companion Lcom/datadog/android/rum/DdRumContentProvider$Companion;
323+
public fun <init> ()V
324+
public fun delete (Landroid/net/Uri;Ljava/lang/String;[Ljava/lang/String;)I
325+
public fun getType (Landroid/net/Uri;)Ljava/lang/String;
326+
public fun insert (Landroid/net/Uri;Landroid/content/ContentValues;)Landroid/net/Uri;
327+
public fun onCreate ()Z
328+
public fun query (Landroid/net/Uri;[Ljava/lang/String;Ljava/lang/String;[Ljava/lang/String;Ljava/lang/String;)Landroid/database/Cursor;
329+
public fun update (Landroid/net/Uri;Landroid/content/ContentValues;Ljava/lang/String;[Ljava/lang/String;)I
330+
}
331+
332+
public final class com/datadog/android/rum/DdRumContentProvider$Companion {
333+
public final fun getCreateTimeNs ()J
334+
public final fun getProcessImportance ()I
335+
public final fun setProcessImportance (I)V
336+
}
337+
309338
public abstract interface annotation class com/datadog/tools/annotation/NoOpImplementation : java/lang/annotation/Annotation {
310339
public abstract fun publicNoOpImplementation ()Z
311340
}

dd-sdk-android-internal/build.gradle.kts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ plugins {
2222
id("com.github.ben-manes.versions")
2323

2424
// Tests
25+
id("de.mobilej.unmock")
2526
id("org.jetbrains.kotlinx.kover")
2627

2728
// Internal Generation
@@ -69,6 +70,7 @@ dependencies {
6970
)
7071
}
7172
}
73+
unmock(libs.robolectric)
7274
}
7375

7476
kotlinConfig(jvmBytecodeTarget = JvmTarget.JVM_11)
@@ -80,3 +82,24 @@ publishingConfig(
8082
"Internal library to be used by the Datadog SDK modules."
8183
)
8284
detektCustomConfig()
85+
86+
unMock {
87+
keep("android.os.BaseBundle")
88+
keep("android.os.Bundle")
89+
keep("android.os.Parcel")
90+
keepStartingWith("com.android.internal.util.")
91+
keepStartingWith("android.util.")
92+
keep("android.content.ComponentName")
93+
keep("android.content.ContentProvider")
94+
keep("android.content.IContentProvider")
95+
keep("android.content.ContentProviderNative")
96+
keep("android.net.Uri")
97+
keep("android.os.Handler")
98+
keep("android.os.IMessenger")
99+
keep("android.os.Looper")
100+
keep("android.os.Message")
101+
keep("android.os.MessageQueue")
102+
keep("android.os.SystemProperties")
103+
keep("android.view.DisplayEventReceiver")
104+
keepStartingWith("org.json")
105+
}

features/dd-sdk-android-rum/src/main/AndroidManifest.xml renamed to dd-sdk-android-internal/src/main/AndroidManifest.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
<application>
1010

1111
<provider
12-
android:name=".DdRumContentProvider"
12+
android:name="com.datadog.android.rum.DdRumContentProvider"
1313
android:authorities="${applicationId}.provider.datadog.rum"
1414
android:exported="false" />
1515

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
/*
2+
* Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0.
3+
* This product includes software developed at Datadog (https://www.datadoghq.com/).
4+
* Copyright 2016-Present Datadog, Inc.
5+
*/
6+
7+
package com.datadog.android.internal.utils
8+
9+
import java.util.concurrent.CopyOnWriteArraySet
10+
11+
/**
12+
* A utility that holds listeners and notifies them. It satisfies the following requirements:
13+
* 1. All methods can be called from any thread.
14+
* 2. It is possible to call [addListener] and [removeListener] inside a listener callback.
15+
* 3. Listeners are notified in the order [addListener] is called on them.
16+
*/
17+
@Suppress("UndocumentedPublicFunction", "UndocumentedPublicProperty")
18+
interface DDCoreSubscription<T : Any> {
19+
fun addListener(listener: T)
20+
21+
fun removeListener(listener: T)
22+
23+
fun notifyListeners(block: T.() -> Unit)
24+
25+
val listenersCount: Int
26+
27+
companion object {
28+
fun <T : Any> create(): DDCoreSubscription<T> {
29+
return DDCoreSubscriptionImpl()
30+
}
31+
}
32+
}
33+
34+
private class DDCoreSubscriptionImpl<T : Any> : DDCoreSubscription<T> {
35+
private val listeners = CopyOnWriteArraySet<T>()
36+
37+
override fun addListener(listener: T) {
38+
listeners.add(listener)
39+
}
40+
41+
override fun removeListener(listener: T) {
42+
listeners.remove(listener)
43+
}
44+
45+
override fun notifyListeners(block: T.() -> Unit) {
46+
listeners.forEach { it.block() }
47+
}
48+
49+
override val listenersCount: Int get() = listeners.size
50+
}
Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -64,19 +64,19 @@ class DdRumContentProvider : ContentProvider() {
6464
return 0
6565
}
6666

67-
internal companion object {
67+
companion object {
6868
internal const val DEFAULT_IMPORTANCE: Int =
6969
ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND
70-
internal var processImportance = 0
7170

72-
@Suppress("unused") // Used for instrumented tests
73-
@JvmStatic
74-
private fun overrideProcessImportance(importance: Int) {
75-
Log.w(
76-
"DdRumContentProvider",
77-
"override processImportance: $processImportance -> $importance"
78-
)
79-
processImportance = importance
80-
}
71+
/**
72+
* Process importance at the moment of creating [DdRumContentProvider]
73+
* Should be set from the outside only in tests.
74+
*/
75+
var processImportance: Int = 0
76+
77+
/**
78+
* fallback for APIs below Android N, see [DefaultAppStartTimeProvider].
79+
*/
80+
val createTimeNs: Long = System.nanoTime()
8181
}
8282
}

dd-sdk-android-internal/src/test/java/com/datadog/android/internal/forge/Configurator.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,13 @@ package com.datadog.android.internal.forge
99
import com.datadog.android.internal.tests.elmyr.InternalTelemetryErrorLogForgeryFactory
1010
import com.datadog.tools.unit.forge.BaseConfigurator
1111
import fr.xgouchet.elmyr.Forge
12+
import fr.xgouchet.elmyr.jvm.useJvmFactories
1213

1314
internal class Configurator :
1415
BaseConfigurator() {
1516
override fun configure(forge: Forge) {
1617
super.configure(forge)
18+
forge.useJvmFactories()
1719
forge.addFactory(InternalTelemetryErrorLogForgeryFactory())
1820
}
1921
}

0 commit comments

Comments
 (0)