diff --git a/firebase-perf/CHANGELOG.md b/firebase-perf/CHANGELOG.md index d642d96ae23..b4db8bb6bc4 100644 --- a/firebase-perf/CHANGELOG.md +++ b/firebase-perf/CHANGELOG.md @@ -1,5 +1,5 @@ # Unreleased - +* [fixed] Fixed an ANR on app launch. [#4831] # 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/config/RemoteConfigManager.java b/firebase-perf/src/main/java/com/google/firebase/perf/config/RemoteConfigManager.java index 8065997974d..66b8ff8f804 100644 --- a/firebase-perf/src/main/java/com/google/firebase/perf/config/RemoteConfigManager.java +++ b/firebase-perf/src/main/java/com/google/firebase/perf/config/RemoteConfigManager.java @@ -23,8 +23,6 @@ import androidx.annotation.Keep; import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; -import com.google.firebase.FirebaseApp; -import com.google.firebase.StartupTime; import com.google.firebase.inject.Provider; import com.google.firebase.perf.logging.AndroidLogger; import com.google.firebase.perf.util.Optional; @@ -54,15 +52,14 @@ public class RemoteConfigManager { private static final long TIME_AFTER_WHICH_A_FETCH_IS_CONSIDERED_STALE_MS = TimeUnit.HOURS.toMillis(12); private static final long FETCH_NEVER_HAPPENED_TIMESTAMP_MS = 0; - private static final long MIN_APP_START_CONFIG_FETCH_DELAY_MS = 5000; - private static final int RANDOM_APP_START_CONFIG_FETCH_DELAY_MS = 25000; + private static final long MIN_CONFIG_FETCH_DELAY_MS = 5000; + private static final int RANDOM_CONFIG_FETCH_DELAY_MS = 25000; + private final long rcmInitTimestamp = getCurrentSystemTimeMillis(); private final DeviceCacheManager cache; private final ConcurrentHashMap allRcConfigMap; private final Executor executor; - private final long appStartTimeInMs; - private final long appStartConfigFetchDelayInMs; - + private final long remoteConfigFetchDelayInMs; private long firebaseRemoteConfigLastFetchTimestampMs = FETCH_NEVER_HAPPENED_TIMESTAMP_MS; @Nullable private Provider firebaseRemoteConfigProvider; @@ -80,26 +77,7 @@ private RemoteConfigManager() { TimeUnit.SECONDS, new LinkedBlockingQueue()), /* firebaseRemoteConfig= */ null, // set once FirebaseRemoteConfig is initialized - MIN_APP_START_CONFIG_FETCH_DELAY_MS - + new Random().nextInt(RANDOM_APP_START_CONFIG_FETCH_DELAY_MS), - getInitialStartupMillis()); - } - - @VisibleForTesting - @SuppressWarnings("FirebaseUseExplicitDependencies") - static long getInitialStartupMillis() { - StartupTime startupTime = null; - try { - startupTime = FirebaseApp.getInstance().get(StartupTime.class); - } catch (IllegalStateException ex) { - // This can happen if you start a trace before Firebase is init - logger.debug("Unable to get StartupTime instance."); - } - if (startupTime != null) { - return startupTime.getEpochMillis(); - } else { - return System.currentTimeMillis(); - } + MIN_CONFIG_FETCH_DELAY_MS + new Random().nextInt(RANDOM_CONFIG_FETCH_DELAY_MS)); } @VisibleForTesting @@ -107,8 +85,7 @@ static long getInitialStartupMillis() { DeviceCacheManager cache, Executor executor, FirebaseRemoteConfig firebaseRemoteConfig, - long appStartConfigFetchDelayInMs, - long appStartTimeInMs) { + long remoteConfigFetchDelayInMs) { this.cache = cache; this.executor = executor; this.firebaseRemoteConfig = firebaseRemoteConfig; @@ -116,8 +93,7 @@ static long getInitialStartupMillis() { firebaseRemoteConfig == null ? new ConcurrentHashMap<>() : new ConcurrentHashMap<>(firebaseRemoteConfig.getAll()); - this.appStartTimeInMs = appStartTimeInMs; - this.appStartConfigFetchDelayInMs = appStartConfigFetchDelayInMs; + this.remoteConfigFetchDelayInMs = remoteConfigFetchDelayInMs; } /** Gets the singleton instance. */ @@ -329,7 +305,7 @@ public boolean isLastFetchFailed() { * *
    *
  1. Firebase Remote Config is available, - *
  2. Time-since-app-start has passed a randomized delay-time (b/187985523), and + *
  3. Time has passed a randomized delay-time (b/187985523), and *
  4. At least 12 hours have passed since the previous fetch. *
*/ @@ -408,17 +384,17 @@ public boolean isFirebaseRemoteConfigAvailable() { /** Returns true if a RC fetch should be made, false otherwise. */ private boolean shouldFetchAndActivateRemoteConfigValues() { long currentTimeInMs = getCurrentSystemTimeMillis(); - return hasAppStartConfigFetchDelayElapsed(currentTimeInMs) + return hasRemoteConfigFetchDelayElapsed(currentTimeInMs) && hasLastFetchBecomeStale(currentTimeInMs); } /** - * Delay fetch by some random time since app start. This is to prevent b/187985523. + * Delay fetch by some random time. This is to prevent b/187985523. * * @return true if the random delay has elapsed, false otherwise */ - private boolean hasAppStartConfigFetchDelayElapsed(long currentTimeInMs) { - return (currentTimeInMs - appStartTimeInMs) >= appStartConfigFetchDelayInMs; + private boolean hasRemoteConfigFetchDelayElapsed(long currentTimeInMs) { + return (currentTimeInMs - rcmInitTimestamp) >= remoteConfigFetchDelayInMs; } // We want to fetch once when the app starts and every 12 hours after that. diff --git a/firebase-perf/src/test/java/com/google/firebase/perf/config/RemoteConfigManagerTest.java b/firebase-perf/src/test/java/com/google/firebase/perf/config/RemoteConfigManagerTest.java index d09d3fc686b..3e1a9623adc 100644 --- a/firebase-perf/src/test/java/com/google/firebase/perf/config/RemoteConfigManagerTest.java +++ b/firebase-perf/src/test/java/com/google/firebase/perf/config/RemoteConfigManagerTest.java @@ -835,20 +835,20 @@ public void isLastFetchFailed_frcIsNonNullAndStatusOtherThanFailedOrThrottled_re } @Test - public void triggerRemoteConfigFetchIfNecessary_doesNotFetchBeforeAppStartRandomDelay() { - long appStartConfigFetchDelay = 5000; + public void triggerRemoteConfigFetchIfNecessary_doesNotFetchBeforeRandomDelay() { + long remoteConfigFetchDelay = 5000; RemoteConfigManager remoteConfigManagerPartialMock = spy( setupTestRemoteConfigManager( createFakeTaskThatDoesNothing(), true, createDefaultRcConfigMap(), - appStartConfigFetchDelay)); + remoteConfigFetchDelay)); // Simulate time fast forward to some time before fetch time is up - long appStartTimeInMs = System.currentTimeMillis(); + long approxRcmInitTimestampMs = System.currentTimeMillis(); when(remoteConfigManagerPartialMock.getCurrentSystemTimeMillis()) - .thenReturn(appStartTimeInMs + appStartConfigFetchDelay - 2000); + .thenReturn(approxRcmInitTimestampMs + remoteConfigFetchDelay - 2000); simulateFirebaseRemoteConfigLastFetchStatus( FirebaseRemoteConfig.LAST_FETCH_STATUS_NO_FETCH_YET); @@ -861,20 +861,20 @@ public void triggerRemoteConfigFetchIfNecessary_doesNotFetchBeforeAppStartRandom } @Test - public void triggerRemoteConfigFetchIfNecessary_fetchesAfterAppStartRandomDelay() { - long appStartConfigFetchDelay = 5000; + public void triggerRemoteConfigFetchIfNecessary_fetchesAfterRandomDelay() { + long remoteConfigFetchDelay = 5000; RemoteConfigManager remoteConfigManagerPartialMock = spy( setupTestRemoteConfigManager( createFakeTaskThatDoesNothing(), true, createDefaultRcConfigMap(), - appStartConfigFetchDelay)); + remoteConfigFetchDelay)); // Simulate time fast forward to 2s after fetch delay time is up - long appStartTimeInMs = System.currentTimeMillis(); + long approxRcmInitTimestampInMs = System.currentTimeMillis(); when(remoteConfigManagerPartialMock.getCurrentSystemTimeMillis()) - .thenReturn(appStartTimeInMs + appStartConfigFetchDelay + 2000); + .thenReturn(approxRcmInitTimestampInMs + remoteConfigFetchDelay + 2000); simulateFirebaseRemoteConfigLastFetchStatus( FirebaseRemoteConfig.LAST_FETCH_STATUS_NO_FETCH_YET); @@ -918,24 +918,16 @@ private RemoteConfigManager setupTestRemoteConfigManager( Task fakeTask, boolean initializeFrc, Map configs, - long appStartConfigFetchDelayInMs) { + long remoteConfigFetchDelayInMs) { simulateFirebaseRemoteConfigLastFetchStatus(FirebaseRemoteConfig.LAST_FETCH_STATUS_SUCCESS); when(mockFirebaseRemoteConfig.fetchAndActivate()).thenReturn(fakeTask); when(mockFirebaseRemoteConfig.getAll()).thenReturn(configs); if (initializeFrc) { return new RemoteConfigManager( - cacheManager, - fakeExecutor, - mockFirebaseRemoteConfig, - appStartConfigFetchDelayInMs, - RemoteConfigManager.getInitialStartupMillis()); + cacheManager, fakeExecutor, mockFirebaseRemoteConfig, remoteConfigFetchDelayInMs); } else { return new RemoteConfigManager( - cacheManager, - fakeExecutor, - /* firebaseRemoteConfig= */ null, - appStartConfigFetchDelayInMs, - RemoteConfigManager.getInitialStartupMillis()); + cacheManager, fakeExecutor, /* firebaseRemoteConfig= */ null, remoteConfigFetchDelayInMs); } }