[ApiModel] Report diagnostic warning if database could not be generated

Bug: b/235435497
Change-Id: I306b9d2e8b3f4a5b873368fb80448b52e6bc6167
diff --git a/src/main/java/com/android/tools/r8/androidapi/AndroidApiDataAccess.java b/src/main/java/com/android/tools/r8/androidapi/AndroidApiDataAccess.java
index 0539dcf..c788d6b 100644
--- a/src/main/java/com/android/tools/r8/androidapi/AndroidApiDataAccess.java
+++ b/src/main/java/com/android/tools/r8/androidapi/AndroidApiDataAccess.java
@@ -9,7 +9,7 @@
 
 import com.android.tools.r8.DiagnosticsHandler;
 import com.android.tools.r8.dex.CompatByteBuffer;
-import com.android.tools.r8.errors.CompilationError;
+import com.android.tools.r8.errors.Unreachable;
 import com.android.tools.r8.graph.DexReference;
 import com.android.tools.r8.graph.DexString;
 import com.android.tools.r8.utils.ExceptionDiagnostic;
@@ -92,7 +92,9 @@
       InternalOptions options, DiagnosticsHandler diagnosticsHandler) {
     URL resource = AndroidApiDataAccess.class.getClassLoader().getResource(RESOURCE_NAME);
     if (resource == null) {
-      throw new CompilationError("Could not find the api database at " + RESOURCE_NAME);
+      diagnosticsHandler.warning(
+          new StringDiagnostic("Could not find the api database at " + RESOURCE_NAME));
+      return new AndroidApiDataAccessNoBacking();
     }
     if (options.apiModelingOptions().useMemoryMappedByteBuffer) {
       try {
@@ -126,11 +128,14 @@
     try (InputStream apiInputStream =
         AndroidApiDataAccess.class.getClassLoader().getResourceAsStream(RESOURCE_NAME)) {
       if (apiInputStream == null) {
-        throw new CompilationError("Could not find the api database at: " + resource);
+        diagnosticsHandler.warning(
+            new StringDiagnostic("Could not open the api database at " + RESOURCE_NAME));
+        return new AndroidApiDataAccessNoBacking();
       }
       return new AndroidApiDataAccessInMemory(ByteStreams.toByteArray(apiInputStream));
     } catch (IOException e) {
-      throw new CompilationError("Could not read the api database.", e);
+      diagnosticsHandler.warning(new ExceptionDiagnostic(e));
+      return new AndroidApiDataAccessNoBacking();
     }
   }
 
@@ -306,6 +311,10 @@
         serialized);
   }
 
+  public boolean isNoBacking() {
+    return false;
+  }
+
   public static class AndroidApiDataAccessByteMapped extends AndroidApiDataAccess {
 
     private final CompatByteBuffer mappedByteBuffer;
@@ -437,4 +446,38 @@
       return 0;
     }
   }
+
+  public static class AndroidApiDataAccessNoBacking extends AndroidApiDataAccess {
+
+    @Override
+    int readConstantPoolSize() {
+      throw new Unreachable();
+    }
+
+    @Override
+    PositionAndLength readPositionAndLength(int offset) {
+      throw new Unreachable();
+    }
+
+    @Override
+    boolean payloadHasConstantPoolValue(int offset, int length, byte[] value) {
+      throw new Unreachable();
+    }
+
+    @Override
+    int payloadContainsConstantPoolValue(
+        int offset, int length, byte[] value, BiPredicate<Integer, byte[]> predicate) {
+      throw new Unreachable();
+    }
+
+    @Override
+    byte readApiLevelForPayloadOffset(int offset, int length, byte[] value) {
+      throw new Unreachable();
+    }
+
+    @Override
+    public boolean isNoBacking() {
+      return true;
+    }
+  }
 }
diff --git a/src/main/java/com/android/tools/r8/androidapi/AndroidApiLevelHashingDatabaseImpl.java b/src/main/java/com/android/tools/r8/androidapi/AndroidApiLevelHashingDatabaseImpl.java
index 22d0c6d..2c6d00d 100644
--- a/src/main/java/com/android/tools/r8/androidapi/AndroidApiLevelHashingDatabaseImpl.java
+++ b/src/main/java/com/android/tools/r8/androidapi/AndroidApiLevelHashingDatabaseImpl.java
@@ -175,11 +175,6 @@
     return lookupApiLevel(field);
   }
 
-  private int getConstantPoolId(DexString string) {
-    return constantPoolCache.computeIfAbsent(
-        string, key -> getDataAccess(options, diagnosticsHandler).getConstantPoolIndex(string));
-  }
-
   private AndroidApiLevel lookupApiLevel(DexReference reference) {
     // We use Android platform to track if an element is unknown since no occurrences of that api
     // level exists in the database.
@@ -187,10 +182,21 @@
         lookupCache.computeIfAbsent(
             reference,
             ref -> {
+              // Prefetch the data access
+              if (dataAccess == null) {
+                getDataAccess(options, diagnosticsHandler);
+              }
+              if (dataAccess.isNoBacking()) {
+                return ANDROID_PLATFORM;
+              }
               byte[] uniqueDescriptorForReference;
               try {
                 uniqueDescriptorForReference =
-                    getUniqueDescriptorForReference(ref, this::getConstantPoolId);
+                    getUniqueDescriptorForReference(
+                        ref,
+                        string ->
+                            constantPoolCache.computeIfAbsent(
+                                string, key -> dataAccess.getConstantPoolIndex(string)));
               } catch (Exception e) {
                 uniqueDescriptorForReference = getNonExistingDescriptor();
               }
@@ -198,8 +204,7 @@
                 return ANDROID_PLATFORM;
               } else {
                 byte apiLevelForReference =
-                    getDataAccess(options, diagnosticsHandler)
-                        .getApiLevelForReference(uniqueDescriptorForReference, ref);
+                    dataAccess.getApiLevelForReference(uniqueDescriptorForReference, ref);
                 return (apiLevelForReference <= 0)
                     ? ANDROID_PLATFORM
                     : AndroidApiLevel.getAndroidApiLevel(apiLevelForReference);