@@ -66,6 +66,10 @@ public class FirebaseInstallations implements FirebaseInstallationsApi {
66
66
private final Object lock = new Object ();
67
67
private final ExecutorService backgroundExecutor ;
68
68
private final ExecutorService networkExecutor ;
69
+ /* FID of this Firebase Installations instance. Cached after successfully registering and
70
+ persisting the FID locally. NOTE: cachedFid resets if FID is deleted.*/
71
+ @ GuardedBy ("this" )
72
+ private String cachedFid ;
69
73
70
74
@ GuardedBy ("lock" )
71
75
private final List <StateListener > listeners = new ArrayList <>();
@@ -221,8 +225,15 @@ String getName() {
221
225
@ Override
222
226
public Task <String > getId () {
223
227
preConditionChecks ();
228
+
229
+ // Return cached fid if available.
230
+ String fid = getCacheFid ();
231
+ if (fid != null ) {
232
+ return Tasks .forResult (fid );
233
+ }
234
+
224
235
Task <String > task = addGetIdListener ();
225
- backgroundExecutor .execute (this :: doGetId );
236
+ backgroundExecutor .execute (() -> doRegistrationOrRefresh ( false ) );
226
237
return task ;
227
238
}
228
239
@@ -239,11 +250,7 @@ public Task<String> getId() {
239
250
public Task <InstallationTokenResult > getToken (boolean forceRefresh ) {
240
251
preConditionChecks ();
241
252
Task <InstallationTokenResult > task = addGetAuthTokenListener ();
242
- if (forceRefresh ) {
243
- backgroundExecutor .execute (this ::doGetAuthTokenForceRefresh );
244
- } else {
245
- backgroundExecutor .execute (this ::doGetAuthTokenWithoutForceRefresh );
246
- }
253
+ backgroundExecutor .execute (() -> doRegistrationOrRefresh (forceRefresh ));
247
254
return task ;
248
255
}
249
256
@@ -261,20 +268,22 @@ public Task<Void> delete() {
261
268
private Task <String > addGetIdListener () {
262
269
TaskCompletionSource <String > taskCompletionSource = new TaskCompletionSource <>();
263
270
StateListener l = new GetIdListener (taskCompletionSource );
264
- synchronized (lock ) {
265
- listeners .add (l );
266
- }
271
+ addStateListeners (l );
267
272
return taskCompletionSource .getTask ();
268
273
}
269
274
270
275
private Task <InstallationTokenResult > addGetAuthTokenListener () {
271
276
TaskCompletionSource <InstallationTokenResult > taskCompletionSource =
272
277
new TaskCompletionSource <>();
273
278
StateListener l = new GetAuthTokenListener (utils , taskCompletionSource );
279
+ addStateListeners (l );
280
+ return taskCompletionSource .getTask ();
281
+ }
282
+
283
+ private void addStateListeners (StateListener l ) {
274
284
synchronized (lock ) {
275
285
listeners .add (l );
276
286
}
277
- return taskCompletionSource .getTask ();
278
287
}
279
288
280
289
private void triggerOnStateReached (PersistedInstallationEntry persistedInstallationEntry ) {
@@ -303,16 +312,12 @@ private void triggerOnException(PersistedInstallationEntry prefs, Exception exce
303
312
}
304
313
}
305
314
306
- private final void doGetId () {
307
- doRegistrationInternal (false );
308
- }
309
-
310
- private final void doGetAuthTokenWithoutForceRefresh () {
311
- doRegistrationInternal (false );
315
+ private synchronized void updateCacheFid (String cachedFid ) {
316
+ this .cachedFid = cachedFid ;
312
317
}
313
318
314
- private final void doGetAuthTokenForceRefresh () {
315
- doRegistrationInternal ( true ) ;
319
+ private synchronized String getCacheFid () {
320
+ return cachedFid ;
316
321
}
317
322
318
323
/**
@@ -324,7 +329,8 @@ private final void doGetAuthTokenForceRefresh() {
324
329
* @param forceRefresh true if this is for a getAuthToken call and if the caller wants to fetch a
325
330
* new auth token from the server even if an unexpired auth token exists on the client.
326
331
*/
327
- private final void doRegistrationInternal (boolean forceRefresh ) {
332
+ private final void doRegistrationOrRefresh (boolean forceRefresh ) {
333
+
328
334
PersistedInstallationEntry prefs = getPrefsWithGeneratedIdMultiProcessSafe ();
329
335
330
336
// Since the caller wants to force an authtoken refresh remove the authtoken from the
@@ -361,6 +367,11 @@ private void doNetworkCallIfNecessary(boolean forceRefresh) {
361
367
// Store the prefs to persist the result of the previous step.
362
368
insertOrUpdatePrefs (prefs );
363
369
370
+ // Update cachedFID, if FID is successfully REGISTERED and persisted.
371
+ if (prefs .isRegistered ()) {
372
+ updateCacheFid (prefs .getFirebaseInstallationId ());
373
+ }
374
+
364
375
// Let the caller know about the result.
365
376
if (prefs .isErrored ()) {
366
377
triggerOnException (prefs , new FirebaseInstallationsException (Status .BAD_CONFIG ));
@@ -520,6 +531,7 @@ private PersistedInstallationEntry fetchAuthTokenFromServer(
520
531
case AUTH_ERROR :
521
532
// The the server refused to generate a new auth token due to bad credentials, clear the
522
533
// FID to force the generation of a new one.
534
+ updateCacheFid (null );
523
535
return prefs .withNoGeneratedFid ();
524
536
default :
525
537
throw new FirebaseInstallationsException (
@@ -533,6 +545,7 @@ private PersistedInstallationEntry fetchAuthTokenFromServer(
533
545
* storage.
534
546
*/
535
547
private Void deleteFirebaseInstallationId () throws FirebaseInstallationsException {
548
+ updateCacheFid (null );
536
549
PersistedInstallationEntry entry = getMultiProcessSafePrefs ();
537
550
if (entry .isRegistered ()) {
538
551
// Call the FIS servers to delete this Firebase Installation Id.
@@ -542,7 +555,6 @@ private Void deleteFirebaseInstallationId() throws FirebaseInstallationsExceptio
542
555
/*projectID= */ getProjectIdentifier (),
543
556
/*refreshToken= */ entry .getRefreshToken ());
544
557
}
545
-
546
558
insertOrUpdatePrefs (entry .withNoGeneratedFid ());
547
559
return null ;
548
560
}
0 commit comments