14
14
package com .google .firebase .ml .modeldownloader ;
15
15
16
16
import android .os .Build .VERSION_CODES ;
17
+ import android .util .Log ;
17
18
import androidx .annotation .NonNull ;
18
19
import androidx .annotation .Nullable ;
19
20
import androidx .annotation .RequiresApi ;
20
21
import androidx .annotation .VisibleForTesting ;
21
- import com .google .android .datatransport .TransportFactory ;
22
22
import com .google .android .gms .common .internal .Preconditions ;
23
23
import com .google .android .gms .tasks .Task ;
24
24
import com .google .android .gms .tasks .TaskCompletionSource ;
40
40
41
41
public class FirebaseModelDownloader {
42
42
43
+ private static final String TAG = "FirebaseModelDownld" ;
43
44
private final FirebaseOptions firebaseOptions ;
44
45
private final SharedPreferencesUtil sharedPreferencesUtil ;
45
46
private final ModelFileDownloadService fileDownloadService ;
@@ -51,15 +52,13 @@ public class FirebaseModelDownloader {
51
52
52
53
@ RequiresApi (api = VERSION_CODES .KITKAT )
53
54
FirebaseModelDownloader (
54
- FirebaseApp firebaseApp ,
55
- FirebaseInstallationsApi firebaseInstallationsApi ,
56
- TransportFactory transportFactory ) {
55
+ FirebaseApp firebaseApp , FirebaseInstallationsApi firebaseInstallationsApi ) {
57
56
this .firebaseOptions = firebaseApp .getOptions ();
58
57
this .sharedPreferencesUtil = new SharedPreferencesUtil (firebaseApp );
59
58
this .eventLogger = FirebaseMlLogger .getInstance ();
60
- this .fileDownloadService = new ModelFileDownloadService (firebaseApp , transportFactory );
59
+ this .fileDownloadService = new ModelFileDownloadService (firebaseApp );
61
60
this .modelDownloadService =
62
- new CustomModelDownloadService (firebaseApp , firebaseInstallationsApi , transportFactory );
61
+ new CustomModelDownloadService (firebaseApp , firebaseInstallationsApi );
63
62
64
63
this .executor = Executors .newSingleThreadExecutor ();
65
64
fileManager = ModelFileManager .getInstance ();
@@ -250,7 +249,7 @@ private Task<CustomModel> getCustomModelTask(
250
249
CustomModel currentModel = sharedPreferencesUtil .getCustomModelDetails (modelName );
251
250
252
251
if (currentModel == null && modelHash != null ) {
253
- // todo(annzimmer) log something about mismatched state and use hash = null
252
+ Log . d ( TAG , "Model hash provided but no current model; triggering fresh download." );
254
253
modelHash = null ;
255
254
}
256
255
@@ -273,7 +272,7 @@ private Task<CustomModel> getCustomModelTask(
273
272
return getCompletedLocalCustomModelTask (updatedModel );
274
273
}
275
274
// clean up model internally
276
- deleteModelDetails (currentModel . getName () );
275
+ deleteModelDetails (modelName );
277
276
return Tasks .forException (
278
277
new FirebaseMlException (
279
278
"Possible caching issues: no model associated with " + modelName + "." ,
@@ -308,16 +307,34 @@ && new File(currentModel.getLocalFilePath()).exists()) {
308
307
if (currentModel .getDownloadId () != 0 ) {
309
308
CustomModel downloadingModel =
310
309
sharedPreferencesUtil .getDownloadingCustomModelDetails (modelName );
311
- if (downloadingModel != null
312
- && downloadingModel
313
- .getModelHash ()
314
- .equals (incomingModelDetails .getResult ().getModelHash ())) {
315
- return Tasks .forResult (downloadingModel );
310
+ if (downloadingModel != null ) {
311
+ if (downloadingModel
312
+ .getModelHash ()
313
+ .equals (incomingModelDetails .getResult ().getModelHash ())) {
314
+ return Tasks .forResult (downloadingModel );
315
+ }
316
+ Log .d (
317
+ TAG , "Hash does not match with expected: " + downloadingModel .getModelHash ());
318
+ // Note we log "DownloadStatus.SUCCEEDED" because the model file's download itself
319
+ // succeeded. Just the hash validation failed.
320
+ eventLogger .logDownloadEventWithErrorCode (
321
+ downloadingModel ,
322
+ true ,
323
+ DownloadStatus .SUCCEEDED ,
324
+ ErrorCode .MODEL_HASH_MISMATCH );
325
+ return Tasks .forException (
326
+ new FirebaseMlException (
327
+ "Hash does not match with expected" ,
328
+ FirebaseMlException .MODEL_HASH_MISMATCH ));
316
329
}
317
- // todo(annzimmer) this shouldn't happen unless they are calling the sdk with
318
- // multiple
319
- // sets of download types/conditions.
320
- // this should be a download in progress - add appropriate handling.
330
+ Log .d (TAG , "Download details missing for model" );
331
+ // Note we log "DownloadStatus.SUCCEEDED" because the model file's download itself
332
+ // succeeded. Just the file copy failed.
333
+ eventLogger .logDownloadEventWithErrorCode (
334
+ downloadingModel , true , DownloadStatus .SUCCEEDED , ErrorCode .DOWNLOAD_FAILED );
335
+ return Tasks .forException (
336
+ new FirebaseMlException (
337
+ "Download details missing for model" , FirebaseMlException .INTERNAL ));
321
338
}
322
339
}
323
340
@@ -343,7 +360,9 @@ private Task<CustomModel> retryExpiredUrlDownload(
343
360
@ Nullable CustomModelDownloadConditions conditions ,
344
361
Task <Void > downloadTask ,
345
362
int retryCounter ) {
346
- if (downloadTask .getException ().getMessage ().contains ("Retry: Expired URL" )) {
363
+ if (downloadTask .getException () instanceof FirebaseMlException
364
+ && ((FirebaseMlException ) downloadTask .getException ()).getCode ()
365
+ == FirebaseMlException .DOWNLOAD_URL_EXPIRED ) {
347
366
// this is likely an expired url - retry.
348
367
Task <CustomModel > retryModelDetails =
349
368
modelDownloadService .getNewDownloadUrlWithExpiry (
@@ -367,13 +386,18 @@ private Task<CustomModel> retryExpiredUrlDownload(
367
386
modelName , conditions , downloadTask , retryCounter - 1 );
368
387
}
369
388
return Tasks .forException (
370
- new Exception ("File download failed. Too many attempts." ));
389
+ new FirebaseMlException (
390
+ "File download failed after multiple attempts, possible expired url." ,
391
+ FirebaseMlException .DOWNLOAD_URL_EXPIRED ));
371
392
});
372
393
}
373
394
return Tasks .forException (retryModelDetailTask .getException ());
374
395
});
396
+ } else if (downloadTask .getException () instanceof FirebaseMlException ) {
397
+ return Tasks .forException (downloadTask .getException ());
375
398
}
376
- return Tasks .forException (new Exception ("File download failed." ));
399
+ return Tasks .forException (
400
+ new FirebaseMlException ("File download failed." , FirebaseMlException .INTERNAL ));
377
401
}
378
402
379
403
private Task <CustomModel > finishModelDownload (@ NonNull String modelName ) {
0 commit comments