From 30184d2149eaf8ccdfb78dd65a0040bf9d681a65 Mon Sep 17 00:00:00 2001 From: Tejas Deshpande Date: Wed, 20 Aug 2025 16:57:31 -0400 Subject: [PATCH] Revert "Make a change to prevent false positive background app starts. (#7274)" This reverts commit e11e900b31360e6dba51adab7b26b5329903ebf4. --- firebase-perf/CHANGELOG.md | 1 - .../firebase/perf/metrics/AppStartTrace.java | 34 ++++------------- .../perf/metrics/AppStartTraceTest.java | 37 +------------------ 3 files changed, 10 insertions(+), 62 deletions(-) diff --git a/firebase-perf/CHANGELOG.md b/firebase-perf/CHANGELOG.md index 4954be336b5..b4db8bb6bc4 100644 --- a/firebase-perf/CHANGELOG.md +++ b/firebase-perf/CHANGELOG.md @@ -1,6 +1,5 @@ # Unreleased * [fixed] Fixed an ANR on app launch. [#4831] -* [fixed] Fixed app start traces on API 34+. [#5920] # 22.0.0 * [changed] **Breaking Change**: Updated minSdkVersion to API level 23 or higher. diff --git a/firebase-perf/src/main/java/com/google/firebase/perf/metrics/AppStartTrace.java b/firebase-perf/src/main/java/com/google/firebase/perf/metrics/AppStartTrace.java index ceac4b39335..7574f989d92 100644 --- a/firebase-perf/src/main/java/com/google/firebase/perf/metrics/AppStartTrace.java +++ b/firebase-perf/src/main/java/com/google/firebase/perf/metrics/AppStartTrace.java @@ -75,8 +75,6 @@ public class AppStartTrace implements ActivityLifecycleCallbacks, LifecycleObser private static final @NonNull Timer PERF_CLASS_LOAD_TIME = new Clock().getTime(); private static final long MAX_LATENCY_BEFORE_UI_INIT = TimeUnit.MINUTES.toMicros(1); - private static final long MAX_BACKGROUND_RUNNABLE_DELAY = TimeUnit.MILLISECONDS.toMicros(100); - // Core pool size 0 allows threads to shut down if they're idle private static final int CORE_POOL_SIZE = 0; private static final int MAX_POOL_SIZE = 1; // Only need single thread @@ -113,8 +111,6 @@ public class AppStartTrace implements ActivityLifecycleCallbacks, LifecycleObser private final @Nullable Timer processStartTime; private final @Nullable Timer firebaseClassLoadTime; private Timer onCreateTime = null; - - private Timer mainThreadRunnableTime = null; private Timer onStartTime = null; private Timer onResumeTime = null; private Timer firstForegroundTime = null; @@ -323,26 +319,8 @@ private void recordOnDrawFrontOfQueue() { logExperimentTrace(this.experimentTtid); } - private void resolveIsStartedFromBackground() { - // If the mainThreadRunnableTime is null, either the runnable hasn't run, or this check has - // already been made. - if (mainThreadRunnableTime == null) { - return; - } - - // Set it to true if the runnable ran more than 100ms prior to onActivityCreated() - if (mainThreadRunnableTime.getDurationMicros() > MAX_BACKGROUND_RUNNABLE_DELAY) { - isStartedFromBackground = true; - } - - // Set this to null to prevent additional checks if `onActivityCreated()` is called again. - mainThreadRunnableTime = null; - } - @Override public synchronized void onActivityCreated(Activity activity, Bundle savedInstanceState) { - resolveIsStartedFromBackground(); - if (isStartedFromBackground || onCreateTime != null // An activity already called onCreate() ) { return; @@ -582,7 +560,8 @@ public static boolean isScreenOn(Context appContext) { * We use StartFromBackgroundRunnable to detect if app is started from background or foreground. * If app is started from background, we do not generate AppStart trace. This runnable is posted * to main UI thread from FirebasePerfEarly. If app is started from background, this runnable will - * be executed earlier than 100ms of any activity's onCreate() method. + * be executed before any activity's onCreate() method. If app is started from foreground, + * activity's onCreate() method is executed before this runnable. */ public static class StartFromBackgroundRunnable implements Runnable { private final AppStartTrace trace; @@ -593,7 +572,10 @@ public StartFromBackgroundRunnable(final AppStartTrace trace) { @Override public void run() { - trace.mainThreadRunnableTime = new Timer(); + // if no activity has ever been created. + if (trace.onCreateTime == null) { + trace.isStartedFromBackground = true; + } } } @@ -632,7 +614,7 @@ Timer getOnResumeTime() { } @VisibleForTesting - void setMainThreadRunnableTime(Timer timer) { - mainThreadRunnableTime = timer; + void setIsStartFromBackground() { + isStartedFromBackground = true; } } diff --git a/firebase-perf/src/test/java/com/google/firebase/perf/metrics/AppStartTraceTest.java b/firebase-perf/src/test/java/com/google/firebase/perf/metrics/AppStartTraceTest.java index 25ad845231a..36ae3d10116 100644 --- a/firebase-perf/src/test/java/com/google/firebase/perf/metrics/AppStartTraceTest.java +++ b/firebase-perf/src/test/java/com/google/firebase/perf/metrics/AppStartTraceTest.java @@ -18,7 +18,6 @@ import static org.mockito.ArgumentMatchers.isA; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.spy; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -239,42 +238,11 @@ public void testDelayedAppStart() { } @Test - public void testStartFromBackground_within100ms() { + public void testStartFromBackground() { FakeScheduledExecutorService fakeExecutorService = new FakeScheduledExecutorService(); - Timer fakeTimer = spy(new Timer(currentTime)); AppStartTrace trace = new AppStartTrace(transportManager, clock, configResolver, fakeExecutorService); - trace.registerActivityLifecycleCallbacks(appContext); - trace.setMainThreadRunnableTime(fakeTimer); - - when(fakeTimer.getDurationMicros()).thenReturn(99L); - trace.onActivityCreated(activity1, bundle); - Assert.assertNotNull(trace.getOnCreateTime()); - ++currentTime; - trace.onActivityStarted(activity1); - Assert.assertNotNull(trace.getOnStartTime()); - ++currentTime; - trace.onActivityResumed(activity1); - Assert.assertNotNull(trace.getOnResumeTime()); - fakeExecutorService.runAll(); - // There should be a trace sent since the delay between the main thread and onActivityCreated - // is limited. - verify(transportManager, times(1)) - .log( - traceArgumentCaptor.capture(), - ArgumentMatchers.nullable(ApplicationProcessState.class)); - } - - @Test - public void testStartFromBackground_moreThan100ms() { - FakeScheduledExecutorService fakeExecutorService = new FakeScheduledExecutorService(); - Timer fakeTimer = spy(new Timer(currentTime)); - AppStartTrace trace = - new AppStartTrace(transportManager, clock, configResolver, fakeExecutorService); - trace.registerActivityLifecycleCallbacks(appContext); - trace.setMainThreadRunnableTime(fakeTimer); - - when(fakeTimer.getDurationMicros()).thenReturn(TimeUnit.MILLISECONDS.toMicros(100) + 1); + trace.setIsStartFromBackground(); trace.onActivityCreated(activity1, bundle); Assert.assertNull(trace.getOnCreateTime()); ++currentTime; @@ -284,7 +252,6 @@ public void testStartFromBackground_moreThan100ms() { trace.onActivityResumed(activity1); Assert.assertNull(trace.getOnResumeTime()); // There should be no trace sent. - fakeExecutorService.runAll(); verify(transportManager, times(0)) .log( traceArgumentCaptor.capture(),