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