19
19
import android .app .Application .ActivityLifecycleCallbacks ;
20
20
import android .content .Context ;
21
21
import android .os .Bundle ;
22
- import android .util .SparseIntArray ;
23
22
import androidx .annotation .NonNull ;
24
23
import androidx .core .app .FrameMetricsAggregator ;
24
+ import androidx .fragment .app .FragmentActivity ;
25
25
import com .google .android .gms .common .util .VisibleForTesting ;
26
26
import com .google .firebase .perf .config .ConfigResolver ;
27
27
import com .google .firebase .perf .logging .AndroidLogger ;
28
+ import com .google .firebase .perf .metrics .FrameMetricsCalculator ;
28
29
import com .google .firebase .perf .metrics .Trace ;
29
30
import com .google .firebase .perf .session .SessionManager ;
30
31
import com .google .firebase .perf .transport .TransportManager ;
31
32
import com .google .firebase .perf .util .Clock ;
32
33
import com .google .firebase .perf .util .Constants ;
33
34
import com .google .firebase .perf .util .Constants .CounterNames ;
35
+ import com .google .firebase .perf .util .ScreenTraceUtil ;
34
36
import com .google .firebase .perf .util .Timer ;
35
- import com .google .firebase .perf .util .Utils ;
36
37
import com .google .firebase .perf .v1 .ApplicationProcessState ;
37
38
import com .google .firebase .perf .v1 .TraceMetric ;
38
39
import java .lang .ref .WeakReference ;
@@ -52,6 +53,7 @@ public class AppStateMonitor implements ActivityLifecycleCallbacks {
52
53
"androidx.core.app.FrameMetricsAggregator" ;
53
54
54
55
private static volatile AppStateMonitor instance ;
56
+ private static boolean hasFrameMetricsAggregator = false ;
55
57
56
58
private final WeakHashMap <Activity , Boolean > activityToResumedMap = new WeakHashMap <>();
57
59
private final WeakHashMap <Activity , Trace > activityToScreenTraceMap = new WeakHashMap <>();
@@ -75,7 +77,6 @@ public class AppStateMonitor implements ActivityLifecycleCallbacks {
75
77
76
78
private boolean isRegisteredForLifecycleCallbacks = false ;
77
79
private boolean isColdStart = true ;
78
- private boolean hasFrameMetricsAggregator = false ;
79
80
80
81
public static AppStateMonitor getInstance () {
81
82
if (instance == null ) {
@@ -89,13 +90,22 @@ public static AppStateMonitor getInstance() {
89
90
}
90
91
91
92
AppStateMonitor (TransportManager transportManager , Clock clock ) {
93
+ this (
94
+ transportManager ,
95
+ clock ,
96
+ ConfigResolver .getInstance (),
97
+ hasFrameMetricsAggregatorClass () ? new FrameMetricsAggregator () : null );
98
+ }
99
+
100
+ AppStateMonitor (
101
+ TransportManager transportManager ,
102
+ Clock clock ,
103
+ ConfigResolver configResolver ,
104
+ FrameMetricsAggregator frameMetricsAggregator ) {
92
105
this .transportManager = transportManager ;
93
106
this .clock = clock ;
94
- configResolver = ConfigResolver .getInstance ();
95
- hasFrameMetricsAggregator = hasFrameMetricsAggregatorClass ();
96
- if (hasFrameMetricsAggregator ) {
97
- frameMetricsAggregator = new FrameMetricsAggregator ();
98
- }
107
+ this .configResolver = configResolver ;
108
+ this .frameMetricsAggregator = frameMetricsAggregator ;
99
109
}
100
110
101
111
public synchronized void registerActivityLifecycleCallbacks (Context context ) {
@@ -140,7 +150,18 @@ public void incrementTsnsCount(int value) {
140
150
}
141
151
142
152
@ Override
143
- public void onActivityCreated (Activity activity , Bundle savedInstanceState ) {}
153
+ public void onActivityCreated (Activity activity , Bundle savedInstanceState ) {
154
+ if (isScreenTraceSupported () && configResolver .isPerformanceMonitoringEnabled ()) {
155
+ if (activity instanceof FragmentActivity ) {
156
+ FragmentActivity fragmentActivity = (FragmentActivity ) activity ;
157
+ fragmentActivity
158
+ .getSupportFragmentManager ()
159
+ .registerFragmentLifecycleCallbacks (
160
+ new FragmentStateMonitor (clock , transportManager , this , frameMetricsAggregator ),
161
+ true );
162
+ }
163
+ }
164
+ }
144
165
145
166
@ Override
146
167
public void onActivityDestroyed (Activity activity ) {}
@@ -192,7 +213,7 @@ public synchronized void onActivityResumed(Activity activity) {
192
213
}
193
214
194
215
// Screen trace is after session update so the sessionId is not added twice to the Trace
195
- if (isScreenTraceSupported (activity ) && configResolver .isPerformanceMonitoringEnabled ()) {
216
+ if (isScreenTraceSupported () && configResolver .isPerformanceMonitoringEnabled ()) {
196
217
// Starts recording frame metrics for this activity.
197
218
/**
198
219
* TODO: Only add activities that are hardware acceleration enabled so that calling {@link
@@ -297,7 +318,7 @@ public void onActivityPaused(Activity activity) {}
297
318
/** Stops screen trace right after onPause because of b/210055697 */
298
319
@ Override
299
320
public void onActivityPostPaused (@ NonNull Activity activity ) {
300
- if (isScreenTraceSupported (activity )) {
321
+ if (isScreenTraceSupported ()) {
301
322
sendScreenTrace (activity );
302
323
}
303
324
}
@@ -333,50 +354,15 @@ private void sendScreenTrace(Activity activity) {
333
354
} catch (IllegalArgumentException ignored ) {
334
355
logger .debug ("View not hardware accelerated. Unable to collect screen trace." );
335
356
}
336
- SparseIntArray [] arr = frameMetricsAggregator .reset ();
337
- if (arr != null ) {
338
- SparseIntArray frameTimes = arr [FrameMetricsAggregator .TOTAL_INDEX ];
339
- if (frameTimes != null ) {
340
- for (int i = 0 ; i < frameTimes .size (); i ++) {
341
- int frameTime = frameTimes .keyAt (i );
342
- int numFrames = frameTimes .valueAt (i );
343
- totalFrames += numFrames ;
344
- if (frameTime > Constants .FROZEN_FRAME_TIME ) {
345
- // Frozen frames mean the app appear frozen. The recommended thresholds is 700ms
346
- frozenFrames += numFrames ;
347
- }
348
- if (frameTime > Constants .SLOW_FRAME_TIME ) {
349
- // Slow frames are anything above 16ms (i.e. 60 frames/second)
350
- slowFrames += numFrames ;
351
- }
352
- }
353
- }
354
- }
355
- if (totalFrames == 0 && slowFrames == 0 && frozenFrames == 0 ) {
357
+ FrameMetricsCalculator .PerfFrameMetrics perfFrameMetrics =
358
+ FrameMetricsCalculator .calculateFrameMetrics (frameMetricsAggregator .reset ());
359
+ if (perfFrameMetrics .getTotalFrames () == 0
360
+ && perfFrameMetrics .getSlowFrames () == 0
361
+ && perfFrameMetrics .getFrozenFrames () == 0 ) {
356
362
// All metrics are zero, no need to send screen trace.
357
- // return;
358
- }
359
- // Only incrementMetric if corresponding metric is non-zero.
360
- if (totalFrames > 0 ) {
361
- screenTrace .putMetric (Constants .CounterNames .FRAMES_TOTAL .toString (), totalFrames );
362
- }
363
- if (slowFrames > 0 ) {
364
- screenTrace .putMetric (Constants .CounterNames .FRAMES_SLOW .toString (), slowFrames );
365
- }
366
- if (frozenFrames > 0 ) {
367
- screenTrace .putMetric (Constants .CounterNames .FRAMES_FROZEN .toString (), frozenFrames );
368
- }
369
- if (Utils .isDebugLoggingEnabled (activity .getApplicationContext ())) {
370
- logger .debug (
371
- "sendScreenTrace name:"
372
- + getScreenTraceName (activity )
373
- + " _fr_tot:"
374
- + totalFrames
375
- + " _fr_slo:"
376
- + slowFrames
377
- + " _fr_fzn:"
378
- + frozenFrames );
363
+ return ;
379
364
}
365
+ ScreenTraceUtil .addFrameCounters (screenTrace , perfFrameMetrics );
380
366
// Stop and record trace
381
367
screenTrace .stop ();
382
368
}
@@ -418,10 +404,9 @@ private void sendSessionLog(String name, Timer startTime, Timer endTime) {
418
404
/**
419
405
* Only send screen trace if FrameMetricsAggregator exists.
420
406
*
421
- * @param activity The Activity for which we're monitoring the screen rendering performance.
422
407
* @return true if supported, false if not.
423
408
*/
424
- private boolean isScreenTraceSupported (Activity activity ) {
409
+ protected boolean isScreenTraceSupported () {
425
410
return hasFrameMetricsAggregator ;
426
411
}
427
412
@@ -430,11 +415,13 @@ private boolean isScreenTraceSupported(Activity activity) {
430
415
* updated to 26.1.0 (b/69954793), there will be ClassNotFoundException. This method is to check
431
416
* if FrameMetricsAggregator exists to avoid ClassNotFoundException.
432
417
*/
433
- private boolean hasFrameMetricsAggregatorClass () {
418
+ private static boolean hasFrameMetricsAggregatorClass () {
434
419
try {
435
420
Class <?> initializerClass = Class .forName (FRAME_METRICS_AGGREGATOR_CLASSNAME );
421
+ hasFrameMetricsAggregator = true ;
436
422
return true ;
437
423
} catch (ClassNotFoundException e ) {
424
+ hasFrameMetricsAggregator = false ;
438
425
return false ;
439
426
}
440
427
}
0 commit comments