[ApiModel] Disable stubbing of super classes on L and below

Bug: b/279780940
Change-Id: I1afd04dcb2134815162f073e186d25d2c61f6fca
diff --git a/src/main/java/com/android/tools/r8/androidapi/ApiReferenceStubber.java b/src/main/java/com/android/tools/r8/androidapi/ApiReferenceStubber.java
index dd1d6c1..ba210ce 100644
--- a/src/main/java/com/android/tools/r8/androidapi/ApiReferenceStubber.java
+++ b/src/main/java/com/android/tools/r8/androidapi/ApiReferenceStubber.java
@@ -24,6 +24,7 @@
 import com.android.tools.r8.graph.ThrowExceptionCode;
 import com.android.tools.r8.shaking.AppInfoWithLiveness;
 import com.android.tools.r8.synthesis.CommittedItems;
+import com.android.tools.r8.utils.AndroidApiLevel;
 import com.android.tools.r8.utils.ListUtils;
 import com.android.tools.r8.utils.ThreadUtils;
 import com.android.tools.r8.utils.WorkList;
@@ -108,9 +109,13 @@
     // We cannot reliably create a stub that will have the same throwing behavior for all VMs.
     // Only create stubs for exceptions to allow them being present in catch handlers and super
     // types of existing program classes. See b/258270051 and b/259076765 for more information.
-    clazz
-        .allImmediateSupertypes()
-        .forEach(superType -> findReferencedLibraryClasses(superType, clazz));
+    // Also, for L devices we can have verification issues if there are super invokes to missing
+    // members on stubbed classes. See b/279780940 for more information.
+    if (appView.options().getMinApiLevel().isGreaterThan(AndroidApiLevel.L)) {
+      clazz
+          .allImmediateSupertypes()
+          .forEach(superType -> findReferencedLibraryClasses(superType, clazz));
+    }
     clazz.forEachProgramMethodMatching(
         DexEncodedMethod::hasCode,
         method -> {
diff --git a/src/test/java/com/android/tools/r8/apimodel/ApiModelMockInheritedClassTest.java b/src/test/java/com/android/tools/r8/apimodel/ApiModelMockInheritedClassTest.java
index 322b30f..0137c9e 100644
--- a/src/test/java/com/android/tools/r8/apimodel/ApiModelMockInheritedClassTest.java
+++ b/src/test/java/com/android/tools/r8/apimodel/ApiModelMockInheritedClassTest.java
@@ -97,7 +97,8 @@
   }
 
   private void inspect(CodeInspector inspector) {
-    verifyThat(inspector, parameters, LibraryClass.class).stubbedUntil(mockLevel);
+    verifyThat(inspector, parameters, LibraryClass.class)
+        .stubbedBetween(AndroidApiLevel.L_MR1, mockLevel);
   }
 
   private void checkOutput(SingleTestRunResult<?> runResult) {
diff --git a/src/test/java/com/android/tools/r8/apimodel/ApiModelMockSuperChainClassTest.java b/src/test/java/com/android/tools/r8/apimodel/ApiModelMockSuperChainClassTest.java
index 5d4fc8f..d4eba25 100644
--- a/src/test/java/com/android/tools/r8/apimodel/ApiModelMockSuperChainClassTest.java
+++ b/src/test/java/com/android/tools/r8/apimodel/ApiModelMockSuperChainClassTest.java
@@ -121,9 +121,12 @@
   }
 
   private void inspect(CodeInspector inspector) {
-    verifyThat(inspector, parameters, LibraryClass.class).stubbedUntil(lowerMockApiLevel);
-    verifyThat(inspector, parameters, LibraryInterface.class).stubbedUntil(lowerMockApiLevel);
-    verifyThat(inspector, parameters, OtherLibraryClass.class).stubbedUntil(mockApiLevel);
+    verifyThat(inspector, parameters, LibraryClass.class)
+        .stubbedBetween(AndroidApiLevel.L_MR1, lowerMockApiLevel);
+    verifyThat(inspector, parameters, LibraryInterface.class)
+        .stubbedBetween(AndroidApiLevel.L_MR1, lowerMockApiLevel);
+    verifyThat(inspector, parameters, OtherLibraryClass.class)
+        .stubbedBetween(AndroidApiLevel.L_MR1, mockApiLevel);
   }
 
   private void checkOutput(SingleTestRunResult<?> runResult) {
diff --git a/src/test/java/com/android/tools/r8/apimodel/ApiModelingTestHelper.java b/src/test/java/com/android/tools/r8/apimodel/ApiModelingTestHelper.java
index 6a487a9..f60fb87 100644
--- a/src/test/java/com/android/tools/r8/apimodel/ApiModelingTestHelper.java
+++ b/src/test/java/com/android/tools/r8/apimodel/ApiModelingTestHelper.java
@@ -263,6 +263,16 @@
                   || parameters.getApiLevel().isGreaterThanOrEqualTo(finalApiLevel)));
     }
 
+    public void stubbedBetween(AndroidApiLevel startingApilevel, AndroidApiLevel endingApiLevel) {
+      assertThat(
+          inspector.clazz(classOfInterest),
+          notIf(
+              isPresent(),
+              parameters.isCfRuntime()
+                  || parameters.getApiLevel().isLessThan(startingApilevel)
+                  || parameters.getApiLevel().isGreaterThanOrEqualTo(endingApiLevel)));
+    }
+
     void hasCheckCastOutlinedFromUntil(Method method, AndroidApiLevel apiLevel) {
       if (parameters.isDexRuntime() && parameters.getApiLevel().isLessThan(apiLevel)) {
         hasCheckCastOutlinedFrom(method);