[ApiModel] Account for static holder on methods overriding objects
Bug: 207327566
Change-Id: I668ab78c0473963646885ec2fc07eb81505fca13
diff --git a/src/main/java/com/android/tools/r8/androidapi/AndroidApiReferenceLevelCache.java b/src/main/java/com/android/tools/r8/androidapi/AndroidApiReferenceLevelCache.java
index 2eed210..3cb2b7d 100644
--- a/src/main/java/com/android/tools/r8/androidapi/AndroidApiReferenceLevelCache.java
+++ b/src/main/java/com/android/tools/r8/androidapi/AndroidApiReferenceLevelCache.java
@@ -6,6 +6,7 @@
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexClass;
+import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.DexReference;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.ir.desugar.desugaredlibrary.DesugaredLibraryConfiguration;
@@ -18,6 +19,7 @@
private final DesugaredLibraryConfiguration desugaredLibraryConfiguration;
private final AndroidApiLevelDatabase androidApiLevelDatabase;
private final AppView<?> appView;
+ private final DexItemFactory factory;
private AndroidApiReferenceLevelCache(AppView<?> appView) {
this(appView, ImmutableList.of());
@@ -26,9 +28,9 @@
private AndroidApiReferenceLevelCache(
AppView<?> appView, List<AndroidApiForHashingClass> predefinedApiTypeLookupForHashing) {
this.appView = appView;
+ factory = appView.dexItemFactory();
androidApiLevelDatabase =
- new AndroidApiLevelHashingDatabaseImpl(
- appView.dexItemFactory(), predefinedApiTypeLookupForHashing);
+ new AndroidApiLevelHashingDatabaseImpl(factory, predefinedApiTypeLookupForHashing);
desugaredLibraryConfiguration = appView.options().desugaredLibraryConfiguration;
}
@@ -58,11 +60,10 @@
public AndroidApiLevel lookup(DexReference reference) {
DexType contextType = reference.getContextType();
if (contextType.isArrayType()) {
- if (reference.isDexMethod()
- && reference.asDexMethod().match(appView.dexItemFactory().objectMembers.clone)) {
+ if (reference.isDexMethod() && reference.asDexMethod().match(factory.objectMembers.clone)) {
return appView.options().getMinApiLevel();
}
- return lookup(contextType.toBaseType(appView.dexItemFactory()));
+ return lookup(contextType.toBaseType(factory));
}
if (contextType.isPrimitiveType() || contextType.isVoidType()) {
return appView.options().getMinApiLevel();
@@ -74,7 +75,7 @@
if (!clazz.isLibraryClass()) {
return appView.options().getMinApiLevel();
}
- if (isReferenceToJavaLangObject(reference)) {
+ if (reference.getContextType() == factory.objectType) {
return appView.options().getMinApiLevel();
}
if (desugaredLibraryConfiguration.isSupported(reference, appView)) {
@@ -82,6 +83,16 @@
// of the program.
return appView.options().getMinApiLevel();
}
+ if (reference.isDexMethod() && factory.objectMembers.isObjectMember(reference.asDexMethod())) {
+ // If we can lookup the method it was introduced/overwritten later. Take for example
+ // a default constructor that was not available before som api level. If unknown we default
+ // back to the static holder.
+ AndroidApiLevel methodApiLevel =
+ androidApiLevelDatabase.getMethodApiLevel(reference.asDexMethod());
+ return methodApiLevel == AndroidApiLevel.UNKNOWN
+ ? androidApiLevelDatabase.getTypeApiLevel(reference.getContextType())
+ : methodApiLevel;
+ }
return reference
.apply(
androidApiLevelDatabase::getTypeApiLevel,
@@ -89,12 +100,4 @@
androidApiLevelDatabase::getMethodApiLevel)
.max(appView.options().getMinApiLevel());
}
-
- private boolean isReferenceToJavaLangObject(DexReference reference) {
- if (reference.getContextType() == appView.dexItemFactory().objectType) {
- return true;
- }
- return reference.isDexMethod()
- && appView.dexItemFactory().objectMembers.isObjectMember(reference.asDexMethod());
- }
}
diff --git a/src/test/java/com/android/tools/r8/apimodel/ApiModelObjectInitTest.java b/src/test/java/com/android/tools/r8/apimodel/ApiModelObjectInitTest.java
index 07e80fa..e5118ab 100644
--- a/src/test/java/com/android/tools/r8/apimodel/ApiModelObjectInitTest.java
+++ b/src/test/java/com/android/tools/r8/apimodel/ApiModelObjectInitTest.java
@@ -75,8 +75,7 @@
Assert.assertEquals(AndroidApiLevel.L.max(currentLevel), apiLevel);
}
if (methodReference.equals(shouldBeN)) {
- // TODO(b/207327566): This should be N or minApi.
- Assert.assertEquals(AndroidApiLevel.L.max(currentLevel), apiLevel);
+ Assert.assertEquals(AndroidApiLevel.N.max(currentLevel), apiLevel);
}
}))
.addKeepMainRule(Main.class)