private Task getCustomModelTask()

in firebase-ml-modeldownloader/src/main/java/com/google/firebase/ml/modeldownloader/FirebaseModelDownloader.java [258:369]


  private Task<CustomModel> getCustomModelTask(
      @NonNull String modelName,
      @Nullable CustomModelDownloadConditions conditions,
      @Nullable String modelHash) {
    CustomModel currentModel = sharedPreferencesUtil.getCustomModelDetails(modelName);

    if (currentModel == null && modelHash != null) {
      Log.d(TAG, "Model hash provided but no current model; triggering fresh download.");
      modelHash = null;
    }

    Task<CustomModel> incomingModelDetails =
        modelDownloadService.getCustomModelDetails(
            firebaseOptions.getProjectId(), modelName, modelHash);

    return incomingModelDetails.continueWithTask(
        executor,
        incomingModelDetailTask -> {
          if (incomingModelDetailTask.isSuccessful()) {
            // null means we have the latest model or we failed to connect.
            if (incomingModelDetailTask.getResult() == null) {
              if (currentModel != null) {
                return getCompletedLocalCustomModelTask(currentModel);
              }
              // double check due to timing.
              CustomModel updatedModel = sharedPreferencesUtil.getCustomModelDetails(modelName);
              if (updatedModel != null) {
                return getCompletedLocalCustomModelTask(updatedModel);
              }
              // clean up model internally
              deleteModelDetails(modelName);
              return Tasks.forException(
                  new FirebaseMlException(
                      "Possible caching issues: no model associated with " + modelName + ".",
                      FirebaseMlException.INTERNAL));
            }

            // if modelHash matches current local model just return local model.
            // Should be handled by above case but just in case.
            if (currentModel != null) {
              // is this the same model?
              if (currentModel
                      .getModelHash()
                      .equals(incomingModelDetails.getResult().getModelHash())
                  && currentModel.getLocalFilePath() != null
                  && !currentModel.getLocalFilePath().isEmpty()
                  && new File(currentModel.getLocalFilePath()).exists()) {
                return getCompletedLocalCustomModelTask(currentModel);
              }

              // update is available
              if (!currentModel
                  .getModelHash()
                  .equals(incomingModelDetails.getResult().getModelHash())) {
                eventLogger.logDownloadEventWithErrorCode(
                    incomingModelDetails.getResult(),
                    false,
                    DownloadStatus.UPDATE_AVAILABLE,
                    ErrorCode.NO_ERROR);
              }

              // is download already in progress for this hash?
              if (currentModel.getDownloadId() != 0) {
                CustomModel downloadingModel =
                    sharedPreferencesUtil.getDownloadingCustomModelDetails(modelName);
                if (downloadingModel != null) {
                  if (downloadingModel
                      .getModelHash()
                      .equals(incomingModelDetails.getResult().getModelHash())) {
                    return Tasks.forResult(downloadingModel);
                  }
                  Log.d(
                      TAG, "Hash does not match with expected: " + downloadingModel.getModelHash());
                  // Note we log "DownloadStatus.SUCCEEDED" because the model file's download itself
                  // succeeded. Just the hash validation failed.
                  eventLogger.logDownloadEventWithErrorCode(
                      downloadingModel,
                      true,
                      DownloadStatus.SUCCEEDED,
                      ErrorCode.MODEL_HASH_MISMATCH);
                  return Tasks.forException(
                      new FirebaseMlException(
                          "Hash does not match with expected",
                          FirebaseMlException.MODEL_HASH_MISMATCH));
                }
                Log.d(TAG, "Download details missing for model");
                // Note we log "DownloadStatus.SUCCEEDED" because the model file's download itself
                // succeeded. Just the file copy failed.
                eventLogger.logDownloadEventWithErrorCode(
                    downloadingModel, true, DownloadStatus.SUCCEEDED, ErrorCode.DOWNLOAD_FAILED);
                return Tasks.forException(
                    new FirebaseMlException(
                        "Download details missing for model", FirebaseMlException.INTERNAL));
              }
            }

            // start download
            return fileDownloadService
                .download(incomingModelDetailTask.getResult(), conditions)
                .continueWithTask(
                    executor,
                    downloadTask -> {
                      if (downloadTask.isSuccessful()) {
                        return finishModelDownload(modelName);
                      } else {
                        return retryExpiredUrlDownload(modelName, conditions, downloadTask, 2);
                      }
                    });
          }
          return Tasks.forException(incomingModelDetailTask.getException());
        });
  }