Merge "Retry intent verification 3 times before failing." into mnc-dev
diff --git a/packages/StatementService/src/com/android/statementservice/retriever/DirectStatementRetriever.java b/packages/StatementService/src/com/android/statementservice/retriever/DirectStatementRetriever.java
index e4feb90..9839329 100644
--- a/packages/StatementService/src/com/android/statementservice/retriever/DirectStatementRetriever.java
+++ b/packages/StatementService/src/com/android/statementservice/retriever/DirectStatementRetriever.java
@@ -36,6 +36,8 @@
 
     private static final long DO_NOT_CACHE_RESULT = 0L;
     private static final int HTTP_CONNECTION_TIMEOUT_MILLIS = 5000;
+    private static final int HTTP_CONNECTION_BACKOFF_MILLIS = 3000;
+    private static final int HTTP_CONNECTION_RETRY = 3;
     private static final long HTTP_CONTENT_SIZE_LIMIT_IN_BYTES = 1024 * 1024;
     private static final int MAX_INCLUDE_LEVEL = 1;
     private static final String WELL_KNOWN_STATEMENT_PATH = "/.well-known/assetlinks.json";
@@ -151,9 +153,10 @@
                     && !url.getProtocol().toLowerCase().equals("https")) {
                 return Result.create(statements, DO_NOT_CACHE_RESULT);
             }
-            webContent = mUrlFetcher.getWebContentFromUrl(url,
-                    HTTP_CONTENT_SIZE_LIMIT_IN_BYTES, HTTP_CONNECTION_TIMEOUT_MILLIS);
-        } catch (IOException e) {
+            webContent = mUrlFetcher.getWebContentFromUrlWithRetry(url,
+                    HTTP_CONTENT_SIZE_LIMIT_IN_BYTES, HTTP_CONNECTION_TIMEOUT_MILLIS,
+                    HTTP_CONNECTION_BACKOFF_MILLIS, HTTP_CONNECTION_RETRY);
+        } catch (IOException | InterruptedException e) {
             return Result.create(statements, DO_NOT_CACHE_RESULT);
         }
 
diff --git a/packages/StatementService/src/com/android/statementservice/retriever/URLFetcher.java b/packages/StatementService/src/com/android/statementservice/retriever/URLFetcher.java
index 225e26c..23cd832 100644
--- a/packages/StatementService/src/com/android/statementservice/retriever/URLFetcher.java
+++ b/packages/StatementService/src/com/android/statementservice/retriever/URLFetcher.java
@@ -49,6 +49,40 @@
     /**
      * Fetches the specified url and returns the content and ttl.
      *
+     * <p>
+     * Retry {@code retry} times if the connection failed or timed out for any reason.
+     * HTTP error code (e.g. 404/500) won't be retried.
+     *
+     * @throws IOException if it can't retrieve the content due to a network problem.
+     * @throws AssociationServiceException if the URL scheme is not http or https or the content
+     * length exceeds {code fileSizeLimit}.
+     */
+    public WebContent getWebContentFromUrlWithRetry(URL url, long fileSizeLimit,
+            int connectionTimeoutMillis, int backoffMillis, int retry)
+                    throws AssociationServiceException, IOException, InterruptedException {
+        if (retry <= 0) {
+            throw new IllegalArgumentException("retry should be a postive inetger.");
+        }
+        while (retry > 0) {
+            try {
+                return getWebContentFromUrl(url, fileSizeLimit, connectionTimeoutMillis);
+            } catch (IOException e) {
+                retry--;
+                if (retry == 0) {
+                    throw e;
+                }
+            }
+
+            Thread.sleep(backoffMillis);
+        }
+
+        // Should never reach here.
+        return null;
+    }
+
+    /**
+     * Fetches the specified url and returns the content and ttl.
+     *
      * @throws IOException if it can't retrieve the content due to a network problem.
      * @throws AssociationServiceException if the URL scheme is not http or https or the content
      * length exceeds {code fileSizeLimit}.