@@ -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