@@ -9,46 +9,72 @@ package com.datadog.android.rum.internal.startup
99import android.app.Activity
1010import android.os.Handler
1111import android.os.Message
12+ import android.view.View
1213import android.view.ViewTreeObserver
1314import com.datadog.android.api.InternalLogger
1415import com.datadog.android.rum.internal.utils.window.RumWindowCallbackListener
1516import com.datadog.android.rum.internal.utils.window.RumWindowCallbacksRegistry
16- import java.lang.IllegalStateException
17- import java.util.WeakHashMap
1817
19- internal class RumTTIDReporterImpl (
18+ internal class RumFirstDrawTimeReporterImpl (
2019 private val internalLogger : InternalLogger ,
2120 private val timeProviderNs : () -> Long ,
2221 private val windowCallbacksRegistry : RumWindowCallbacksRegistry ,
23- private val handler : Handler ,
24- private val listener : RumTTIDReporter .Listener
25- ) : RumTTIDReporter {
22+ private val handler : Handler
23+ ) : RumFirstDrawTimeReporter {
2624
27- private val onDrawListeners = WeakHashMap < Activity , ViewTreeObserver . OnDrawListener >()
28-
29- override fun onAppStartupDetected ( scenario : RumStartupScenario ) {
30- val activity = scenario.activity.get() ? : return
25+ override fun subscribeToFirstFrameDrawn (
26+ activity : Activity ,
27+ callback : RumFirstDrawTimeReporter . Callback
28+ ) {
3129 val window = activity.window
3230 val decorView = window.peekDecorView()
3331
3432 if (decorView == null ) {
3533 val listener = object : RumWindowCallbackListener {
3634 override fun onContentChanged () {
3735 windowCallbacksRegistry.removeListener(activity, this )
38- onDecorViewReady(scenario )
36+ onDecorViewReady(activity, callback )
3937 }
4038 }
4139 windowCallbacksRegistry.addListener(activity, listener)
4240 } else {
43- onDecorViewReady(scenario )
41+ onDecorViewReady(activity, callback )
4442 }
4543 }
4644
47- private fun onDecorViewReady (scenario : RumStartupScenario ) {
48- val activity = scenario.activity.get() ? : return
45+ private fun onDecorViewReady (
46+ activity : Activity ,
47+ callback : RumFirstDrawTimeReporter .Callback
48+ ) {
4949 val window = activity.window
5050 val decorView = window.decorView
5151
52+ if (decorView.isAttachedToWindow) {
53+ registerOnDrawListener(
54+ decorView = decorView,
55+ callback = callback
56+ )
57+ } else {
58+ val attachListener = object : View .OnAttachStateChangeListener {
59+ override fun onViewAttachedToWindow (v : View ) {
60+ registerOnDrawListener(
61+ decorView = decorView,
62+ callback = callback
63+ )
64+ decorView.removeOnAttachStateChangeListener(this )
65+ }
66+
67+ override fun onViewDetachedFromWindow (v : View ) {
68+ }
69+ }
70+ decorView.addOnAttachStateChangeListener(attachListener)
71+ }
72+ }
73+
74+ private fun registerOnDrawListener (
75+ decorView : View ,
76+ callback : RumFirstDrawTimeReporter .Callback
77+ ) {
5278 val listener = object : ViewTreeObserver .OnDrawListener {
5379 private var invoked = false
5480
@@ -57,11 +83,9 @@ internal class RumTTIDReporterImpl(
5783 return
5884 }
5985 invoked = true
60- onFirstDraw(scenario )
86+ onFirstDraw(callback )
6187
6288 handler.post {
63- onDrawListeners.remove(activity)
64-
6589 if (decorView.viewTreeObserver.isAlive) {
6690 try {
6791 decorView.viewTreeObserver.removeOnDrawListener(this )
@@ -81,26 +105,22 @@ internal class RumTTIDReporterImpl(
81105 if (decorView.viewTreeObserver.isAlive) {
82106 try {
83107 decorView.viewTreeObserver.addOnDrawListener(listener)
84- onDrawListeners.put(activity, listener)
85108 } catch (e: IllegalStateException ) {
86109 internalLogger.log(
87110 InternalLogger .Level .WARN ,
88111 InternalLogger .Target .TELEMETRY ,
89- { " RumTTIDReporterImpl unable to add onDrawListener onto viewTreeObserver" },
112+ { " RumFirstDrawTimeReporterImpl unable to add onDrawListener onto viewTreeObserver" },
90113 e
91114 )
92115 }
93116 }
94117 }
95118
96- private fun onFirstDraw (scenario : RumStartupScenario ) {
119+ private fun onFirstDraw (callback : RumFirstDrawTimeReporter . Callback ) {
97120 val nowNs = timeProviderNs()
98- val durationNs = nowNs - scenario.initialTimeNs
99121
100122 val block = Runnable {
101- listener.onTTIDCalculated(
102- RumTTIDInfo (scenario = scenario, durationNs = durationNs)
103- )
123+ callback.onFirstFrameDrawn(nowNs)
104124 }
105125
106126 handler.sendMessageAtFrontOfQueue(
0 commit comments