Skip to content

Commit 0e52253

Browse files
committed
Refactor RCM fetch random delay to not depend on FirebaseApp initialization.
1 parent 0c1302f commit 0e52253

File tree

3 files changed

+26
-58
lines changed

3 files changed

+26
-58
lines changed

firebase-perf/CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# Unreleased
2-
2+
* [fixed] Made a change that should help address an ANR on app launch. [#4831]
33

44
# 22.0.0
55
* [changed] **Breaking Change**: Updated minSdkVersion to API level 23 or higher.

firebase-perf/src/main/java/com/google/firebase/perf/config/RemoteConfigManager.java

Lines changed: 12 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,6 @@
2323
import androidx.annotation.Keep;
2424
import androidx.annotation.Nullable;
2525
import androidx.annotation.VisibleForTesting;
26-
import com.google.firebase.FirebaseApp;
27-
import com.google.firebase.StartupTime;
2826
import com.google.firebase.inject.Provider;
2927
import com.google.firebase.perf.logging.AndroidLogger;
3028
import com.google.firebase.perf.util.Optional;
@@ -54,15 +52,14 @@ public class RemoteConfigManager {
5452
private static final long TIME_AFTER_WHICH_A_FETCH_IS_CONSIDERED_STALE_MS =
5553
TimeUnit.HOURS.toMillis(12);
5654
private static final long FETCH_NEVER_HAPPENED_TIMESTAMP_MS = 0;
57-
private static final long MIN_APP_START_CONFIG_FETCH_DELAY_MS = 5000;
58-
private static final int RANDOM_APP_START_CONFIG_FETCH_DELAY_MS = 25000;
55+
private static final long MIN_CONFIG_FETCH_DELAY_MS = 5000;
56+
private static final int RANDOM_CONFIG_FETCH_DELAY_MS = 25000;
57+
private final long rcmInitTimestamp = getCurrentSystemTimeMillis();
5958

6059
private final DeviceCacheManager cache;
6160
private final ConcurrentHashMap<String, FirebaseRemoteConfigValue> allRcConfigMap;
6261
private final Executor executor;
63-
private final long appStartTimeInMs;
64-
private final long appStartConfigFetchDelayInMs;
65-
62+
private final long remoteConfigFetchDelayInMs;
6663
private long firebaseRemoteConfigLastFetchTimestampMs = FETCH_NEVER_HAPPENED_TIMESTAMP_MS;
6764

6865
@Nullable private Provider<RemoteConfigComponent> firebaseRemoteConfigProvider;
@@ -80,44 +77,23 @@ private RemoteConfigManager() {
8077
TimeUnit.SECONDS,
8178
new LinkedBlockingQueue<Runnable>()),
8279
/* firebaseRemoteConfig= */ null, // set once FirebaseRemoteConfig is initialized
83-
MIN_APP_START_CONFIG_FETCH_DELAY_MS
84-
+ new Random().nextInt(RANDOM_APP_START_CONFIG_FETCH_DELAY_MS),
85-
getInitialStartupMillis());
86-
}
87-
88-
@VisibleForTesting
89-
@SuppressWarnings("FirebaseUseExplicitDependencies")
90-
static long getInitialStartupMillis() {
91-
StartupTime startupTime = null;
92-
try {
93-
startupTime = FirebaseApp.getInstance().get(StartupTime.class);
94-
} catch (IllegalStateException ex) {
95-
// This can happen if you start a trace before Firebase is init
96-
logger.debug("Unable to get StartupTime instance.");
97-
}
98-
if (startupTime != null) {
99-
return startupTime.getEpochMillis();
100-
} else {
101-
return System.currentTimeMillis();
102-
}
80+
MIN_CONFIG_FETCH_DELAY_MS + new Random().nextInt(RANDOM_CONFIG_FETCH_DELAY_MS));
10381
}
10482

10583
@VisibleForTesting
10684
RemoteConfigManager(
10785
DeviceCacheManager cache,
10886
Executor executor,
10987
FirebaseRemoteConfig firebaseRemoteConfig,
110-
long appStartConfigFetchDelayInMs,
111-
long appStartTimeInMs) {
88+
long remoteConfigFetchDelayInMs) {
11289
this.cache = cache;
11390
this.executor = executor;
11491
this.firebaseRemoteConfig = firebaseRemoteConfig;
11592
this.allRcConfigMap =
11693
firebaseRemoteConfig == null
11794
? new ConcurrentHashMap<>()
11895
: new ConcurrentHashMap<>(firebaseRemoteConfig.getAll());
119-
this.appStartTimeInMs = appStartTimeInMs;
120-
this.appStartConfigFetchDelayInMs = appStartConfigFetchDelayInMs;
96+
this.remoteConfigFetchDelayInMs = remoteConfigFetchDelayInMs;
12197
}
12298

12399
/** Gets the singleton instance. */
@@ -329,7 +305,7 @@ public boolean isLastFetchFailed() {
329305
*
330306
* <ol>
331307
* <li>Firebase Remote Config is available,
332-
* <li>Time-since-app-start has passed a randomized delay-time (b/187985523), and
308+
* <li>Time has passed a randomized delay-time (b/187985523), and
333309
* <li>At least 12 hours have passed since the previous fetch.
334310
* </ol>
335311
*/
@@ -408,17 +384,17 @@ public boolean isFirebaseRemoteConfigAvailable() {
408384
/** Returns true if a RC fetch should be made, false otherwise. */
409385
private boolean shouldFetchAndActivateRemoteConfigValues() {
410386
long currentTimeInMs = getCurrentSystemTimeMillis();
411-
return hasAppStartConfigFetchDelayElapsed(currentTimeInMs)
387+
return hasRemoteConfigFetchDelayElapsed(currentTimeInMs)
412388
&& hasLastFetchBecomeStale(currentTimeInMs);
413389
}
414390

415391
/**
416-
* Delay fetch by some random time since app start. This is to prevent b/187985523.
392+
* Delay fetch by some random time. This is to prevent b/187985523.
417393
*
418394
* @return true if the random delay has elapsed, false otherwise
419395
*/
420-
private boolean hasAppStartConfigFetchDelayElapsed(long currentTimeInMs) {
421-
return (currentTimeInMs - appStartTimeInMs) >= appStartConfigFetchDelayInMs;
396+
private boolean hasRemoteConfigFetchDelayElapsed(long currentTimeInMs) {
397+
return (currentTimeInMs - rcmInitTimestamp) >= remoteConfigFetchDelayInMs;
422398
}
423399

424400
// We want to fetch once when the app starts and every 12 hours after that.

firebase-perf/src/test/java/com/google/firebase/perf/config/RemoteConfigManagerTest.java

Lines changed: 13 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -835,20 +835,20 @@ public void isLastFetchFailed_frcIsNonNullAndStatusOtherThanFailedOrThrottled_re
835835
}
836836

837837
@Test
838-
public void triggerRemoteConfigFetchIfNecessary_doesNotFetchBeforeAppStartRandomDelay() {
839-
long appStartConfigFetchDelay = 5000;
838+
public void triggerRemoteConfigFetchIfNecessary_doesNotFetchBeforeRandomDelay() {
839+
long remoteConfigFetchDelay = 5000;
840840
RemoteConfigManager remoteConfigManagerPartialMock =
841841
spy(
842842
setupTestRemoteConfigManager(
843843
createFakeTaskThatDoesNothing(),
844844
true,
845845
createDefaultRcConfigMap(),
846-
appStartConfigFetchDelay));
846+
remoteConfigFetchDelay));
847847

848848
// Simulate time fast forward to some time before fetch time is up
849-
long appStartTimeInMs = System.currentTimeMillis();
849+
long approxRcmInitTimestampMs = System.currentTimeMillis();
850850
when(remoteConfigManagerPartialMock.getCurrentSystemTimeMillis())
851-
.thenReturn(appStartTimeInMs + appStartConfigFetchDelay - 2000);
851+
.thenReturn(approxRcmInitTimestampMs + remoteConfigFetchDelay - 2000);
852852

853853
simulateFirebaseRemoteConfigLastFetchStatus(
854854
FirebaseRemoteConfig.LAST_FETCH_STATUS_NO_FETCH_YET);
@@ -861,20 +861,20 @@ public void triggerRemoteConfigFetchIfNecessary_doesNotFetchBeforeAppStartRandom
861861
}
862862

863863
@Test
864-
public void triggerRemoteConfigFetchIfNecessary_fetchesAfterAppStartRandomDelay() {
865-
long appStartConfigFetchDelay = 5000;
864+
public void triggerRemoteConfigFetchIfNecessary_fetchesAfterRandomDelay() {
865+
long remoteConfigFetchDelay = 5000;
866866
RemoteConfigManager remoteConfigManagerPartialMock =
867867
spy(
868868
setupTestRemoteConfigManager(
869869
createFakeTaskThatDoesNothing(),
870870
true,
871871
createDefaultRcConfigMap(),
872-
appStartConfigFetchDelay));
872+
remoteConfigFetchDelay));
873873

874874
// Simulate time fast forward to 2s after fetch delay time is up
875-
long appStartTimeInMs = System.currentTimeMillis();
875+
long approxRcmInitTimestampInMs = System.currentTimeMillis();
876876
when(remoteConfigManagerPartialMock.getCurrentSystemTimeMillis())
877-
.thenReturn(appStartTimeInMs + appStartConfigFetchDelay + 2000);
877+
.thenReturn(approxRcmInitTimestampInMs + remoteConfigFetchDelay + 2000);
878878

879879
simulateFirebaseRemoteConfigLastFetchStatus(
880880
FirebaseRemoteConfig.LAST_FETCH_STATUS_NO_FETCH_YET);
@@ -918,24 +918,16 @@ private RemoteConfigManager setupTestRemoteConfigManager(
918918
Task<Boolean> fakeTask,
919919
boolean initializeFrc,
920920
Map<String, FirebaseRemoteConfigValue> configs,
921-
long appStartConfigFetchDelayInMs) {
921+
long remoteConfigFetchDelayInMs) {
922922
simulateFirebaseRemoteConfigLastFetchStatus(FirebaseRemoteConfig.LAST_FETCH_STATUS_SUCCESS);
923923
when(mockFirebaseRemoteConfig.fetchAndActivate()).thenReturn(fakeTask);
924924
when(mockFirebaseRemoteConfig.getAll()).thenReturn(configs);
925925
if (initializeFrc) {
926926
return new RemoteConfigManager(
927-
cacheManager,
928-
fakeExecutor,
929-
mockFirebaseRemoteConfig,
930-
appStartConfigFetchDelayInMs,
931-
RemoteConfigManager.getInitialStartupMillis());
927+
cacheManager, fakeExecutor, mockFirebaseRemoteConfig, remoteConfigFetchDelayInMs);
932928
} else {
933929
return new RemoteConfigManager(
934-
cacheManager,
935-
fakeExecutor,
936-
/* firebaseRemoteConfig= */ null,
937-
appStartConfigFetchDelayInMs,
938-
RemoteConfigManager.getInitialStartupMillis());
930+
cacheManager, fakeExecutor, /* firebaseRemoteConfig= */ null, remoteConfigFetchDelayInMs);
939931
}
940932
}
941933

0 commit comments

Comments
 (0)