19
19
import android .util .Log ;
20
20
import androidx .annotation .GuardedBy ;
21
21
import androidx .annotation .VisibleForTesting ;
22
+ import com .google .android .gms .common .util .Clock ;
23
+ import com .google .android .gms .common .util .DefaultClock ;
22
24
import com .google .android .gms .tasks .Task ;
23
25
import com .google .android .gms .tasks .Tasks ;
24
26
import com .google .firebase .remoteconfig .ConfigUpdate ;
31
33
import java .io .InputStream ;
32
34
import java .io .InputStreamReader ;
33
35
import java .net .HttpURLConnection ;
36
+ import java .util .Date ;
34
37
import java .util .Random ;
35
38
import java .util .Set ;
36
39
import java .util .concurrent .ScheduledExecutorService ;
@@ -43,6 +46,7 @@ public class ConfigAutoFetch {
43
46
private static final int MAXIMUM_FETCH_ATTEMPTS = 3 ;
44
47
private static final String TEMPLATE_VERSION_KEY = "latestTemplateVersionNumber" ;
45
48
private static final String REALTIME_DISABLED_KEY = "featureDisabled" ;
49
+ private static final String REALTIME_RETRY_INTERVAL = "retryIntervalSeconds" ;
46
50
47
51
@ GuardedBy ("this" )
48
52
private final Set <ConfigUpdateListener > eventListeners ;
@@ -54,6 +58,8 @@ public class ConfigAutoFetch {
54
58
private final ConfigUpdateListener retryCallback ;
55
59
private final ScheduledExecutorService scheduledExecutorService ;
56
60
private final Random random ;
61
+ private final Clock clock ;
62
+ private final ConfigSharedPrefsClient sharedPrefsClient ;
57
63
private boolean isInBackground ;
58
64
59
65
public ConfigAutoFetch (
@@ -62,7 +68,8 @@ public ConfigAutoFetch(
62
68
ConfigCacheClient activatedCache ,
63
69
Set <ConfigUpdateListener > eventListeners ,
64
70
ConfigUpdateListener retryCallback ,
65
- ScheduledExecutorService scheduledExecutorService ) {
71
+ ScheduledExecutorService scheduledExecutorService ,
72
+ ConfigSharedPrefsClient sharedPrefsClient ) {
66
73
this .httpURLConnection = httpURLConnection ;
67
74
this .configFetchHandler = configFetchHandler ;
68
75
this .activatedCache = activatedCache ;
@@ -71,6 +78,19 @@ public ConfigAutoFetch(
71
78
this .scheduledExecutorService = scheduledExecutorService ;
72
79
this .random = new Random ();
73
80
this .isInBackground = false ;
81
+ this .sharedPrefsClient = sharedPrefsClient ;
82
+ this .clock = DefaultClock .getInstance ();
83
+ }
84
+
85
+ // Increase the backoff duration with a new end time based on Retry Interval
86
+ private synchronized void updateBackoffMetadataWithRetryInterval (
87
+ int realtimeRetryIntervalInSeconds ) {
88
+ Date currentTime = new Date (clock .currentTimeMillis ());
89
+ long backoffDurationInMillis = realtimeRetryIntervalInSeconds * 1000L ;
90
+ Date backoffEndTime = new Date (currentTime .getTime () + backoffDurationInMillis );
91
+
92
+ // Persist the new values to disk-backed metadata.
93
+ sharedPrefsClient .setRealtimeBackoffEndTime (backoffEndTime );
74
94
}
75
95
76
96
private synchronized void propagateErrors (FirebaseRemoteConfigException exception ) {
@@ -190,6 +210,15 @@ private void handleNotifications(InputStream inputStream) throws IOException {
190
210
autoFetch (MAXIMUM_FETCH_ATTEMPTS , targetTemplateVersion );
191
211
}
192
212
}
213
+
214
+ // This field in the response indicates that the realtime request should retry after the
215
+ // specified interval to establish a long-lived connection. This interval extends the
216
+ // backoff duration without affecting the number of retries, so it will not enter an
217
+ // exponential backoff state.
218
+ if (jsonObject .has (REALTIME_RETRY_INTERVAL )) {
219
+ int realtimeRetryIntervalInSeconds = jsonObject .getInt (REALTIME_RETRY_INTERVAL );
220
+ updateBackoffMetadataWithRetryInterval (realtimeRetryIntervalInSeconds );
221
+ }
193
222
} catch (JSONException ex ) {
194
223
// Message was mangled up and so it was unable to be parsed. User is notified of this
195
224
// because it there could be a new configuration that needs to be fetched.
0 commit comments