[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);