Skip to content

Commit f4434c2

Browse files
committed
Add a delay to detect background starts
1 parent aac1143 commit f4434c2

File tree

1 file changed

+31
-6
lines changed

1 file changed

+31
-6
lines changed

firebase-perf/src/main/java/com/google/firebase/perf/metrics/AppStartTrace.java

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,8 @@ public class AppStartTrace implements ActivityLifecycleCallbacks, LifecycleObser
7575
private static final @NonNull Timer PERF_CLASS_LOAD_TIME = new Clock().getTime();
7676
private static final long MAX_LATENCY_BEFORE_UI_INIT = TimeUnit.MINUTES.toMicros(1);
7777

78+
private static final long MAX_BACKGROUND_THREAD_DELAY = TimeUnit.MILLISECONDS.toMicros(100);
79+
7880
// Core pool size 0 allows threads to shut down if they're idle
7981
private static final int CORE_POOL_SIZE = 0;
8082
private static final int MAX_POOL_SIZE = 1; // Only need single thread
@@ -111,6 +113,8 @@ public class AppStartTrace implements ActivityLifecycleCallbacks, LifecycleObser
111113
private final @Nullable Timer processStartTime;
112114
private final @Nullable Timer firebaseClassLoadTime;
113115
private Timer onCreateTime = null;
116+
117+
private Timer mainThreadRunnableTime = null;
114118
private Timer onStartTime = null;
115119
private Timer onResumeTime = null;
116120
private Timer firstForegroundTime = null;
@@ -319,10 +323,28 @@ private void recordOnDrawFrontOfQueue() {
319323
logExperimentTrace(this.experimentTtid);
320324
}
321325

326+
private boolean isStartedFromBackground() {
327+
// This a fix for b/339891952 where the runnable on the background thread can run before the
328+
// activity lifecycle callbacks.
329+
if (mainThreadRunnableTime == null) {
330+
return false;
331+
}
332+
333+
if (isStartedFromBackground
334+
&& (mainThreadRunnableTime.getDurationMicros() < MAX_BACKGROUND_THREAD_DELAY)) {
335+
// Reset it to false as it was executed pre-emptively.
336+
isStartedFromBackground = false;
337+
}
338+
339+
return isStartedFromBackground;
340+
}
341+
322342
@Override
323343
public synchronized void onActivityCreated(Activity activity, Bundle savedInstanceState) {
324-
if (isStartedFromBackground || onCreateTime != null // An activity already called onCreate()
344+
if (isStartedFromBackground() || onCreateTime != null // An activity already called onCreate()
325345
) {
346+
AndroidLogger.getInstance()
347+
.debug("onActivityCreated: isStartedFromBackground - " + isStartedFromBackground());
326348
return;
327349
}
328350

@@ -337,7 +359,7 @@ public synchronized void onActivityCreated(Activity activity, Bundle savedInstan
337359

338360
@Override
339361
public synchronized void onActivityStarted(Activity activity) {
340-
if (isStartedFromBackground
362+
if (isStartedFromBackground()
341363
|| onStartTime != null // An activity already called onStart()
342364
|| isTooLateToInitUI) {
343365
return;
@@ -347,7 +369,7 @@ public synchronized void onActivityStarted(Activity activity) {
347369

348370
@Override
349371
public synchronized void onActivityResumed(Activity activity) {
350-
if (isStartedFromBackground || isTooLateToInitUI) {
372+
if (isStartedFromBackground() || isTooLateToInitUI) {
351373
return;
352374
}
353375

@@ -440,7 +462,7 @@ private void logAppStartTrace() {
440462

441463
@Override
442464
public void onActivityPaused(Activity activity) {
443-
if (isStartedFromBackground
465+
if (isStartedFromBackground()
444466
|| isTooLateToInitUI
445467
|| !configResolver.getIsExperimentTTIDEnabled()) {
446468
return;
@@ -458,7 +480,7 @@ public void onActivityStopped(Activity activity) {}
458480
@Keep
459481
@OnLifecycleEvent(Lifecycle.Event.ON_START)
460482
public void onAppEnteredForeground() {
461-
if (isStartedFromBackground || isTooLateToInitUI || firstForegroundTime != null) {
483+
if (isStartedFromBackground() || isTooLateToInitUI || firstForegroundTime != null) {
462484
return;
463485
}
464486
// firstForeground is equivalent to the first Activity onStart. This marks the beginning of
@@ -476,7 +498,7 @@ public void onAppEnteredForeground() {
476498
@Keep
477499
@OnLifecycleEvent(Lifecycle.Event.ON_STOP)
478500
public void onAppEnteredBackground() {
479-
if (isStartedFromBackground || isTooLateToInitUI || firstBackgroundTime != null) {
501+
if (isStartedFromBackground() || isTooLateToInitUI || firstBackgroundTime != null) {
480502
return;
481503
}
482504
firstBackgroundTime = clock.getTime();
@@ -574,6 +596,9 @@ public StartFromBackgroundRunnable(final AppStartTrace trace) {
574596
public void run() {
575597
// if no activity has ever been created.
576598
if (trace.onCreateTime == null) {
599+
trace.mainThreadRunnableTime = new Timer();
600+
AndroidLogger.getInstance()
601+
.debug("StartFromBackgroundThreadRunnable: " + trace.onCreateTime);
577602
trace.isStartedFromBackground = true;
578603
}
579604
}

0 commit comments

Comments
 (0)