[ApiModel] Also stub super types of program classes

Bug: b/259076765
Change-Id: I3ef545d66506dbc0295b09ffdf58def422a87428
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 4337302..586e8e5 100644
--- a/src/main/java/com/android/tools/r8/androidapi/ApiReferenceStubber.java
+++ b/src/main/java/com/android/tools/r8/androidapi/ApiReferenceStubber.java
@@ -94,6 +94,9 @@
         .isSyntheticOfKind(clazz.getType(), kinds -> kinds.API_MODEL_OUTLINE)) {
       return;
     }
+    // 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));
@@ -141,7 +144,19 @@
       DexLibraryClass libraryClass,
       ThrowExceptionCode throwExceptionCode) {
     DexItemFactory factory = appView.dexItemFactory();
-    if (!appView.options().apiModelingOptions().stubbingEnabledFor(appView, libraryClass)) {
+    // Do not stub the anything starting with java (including the object type).
+    if (libraryClass.getType() == appView.dexItemFactory().objectType
+        || libraryClass
+            .getType()
+            .getDescriptor()
+            .startsWith(appView.dexItemFactory().javaDescriptorPrefix)) {
+      return;
+    }
+    // Check if desugared library will bridge the type.
+    if (appView
+        .options()
+        .machineDesugaredLibrarySpecification
+        .isSupported(libraryClass.getType())) {
       return;
     }
     Set<ProgramDefinition> contexts = referencingContexts.get(libraryClass);
diff --git a/src/main/java/com/android/tools/r8/utils/InternalOptions.java b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
index f49f0d4..2cd8db5 100644
--- a/src/main/java/com/android/tools/r8/utils/InternalOptions.java
+++ b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
@@ -1809,9 +1809,6 @@
         System.getProperty("com.android.tools.r8.disableApiModeling") == null;
     public boolean reportUnknownApiReferences =
         System.getProperty("com.android.tools.r8.reportUnknownApiReferences") != null;
-    // TODO(b/259076765): Remove when resolved.
-    public boolean stubNonThrowableClasses =
-        System.getProperty("com.android.tools.r8.stubNonThrowableClasses") != null;
 
     // TODO(b/232823652): Enable when we can compute the offset correctly.
     public boolean useMemoryMappedByteBuffer = false;
@@ -1878,28 +1875,6 @@
       enableStubbingOfClasses = false;
     }
 
-    public boolean stubbingEnabledFor(AppView<?> appView, DexLibraryClass libraryClass) {
-      if (libraryClass.getType() == appView.dexItemFactory().objectType
-          || libraryClass
-              .getType()
-              .getDescriptor()
-              .startsWith(appView.dexItemFactory().javaDescriptorPrefix)) {
-        return false;
-      }
-      // Check if desugared library will bridge the type.
-      if (appView
-          .options()
-          .machineDesugaredLibrarySpecification
-          .isSupported(libraryClass.getType())) {
-        return false;
-      }
-      // We cannot reliably create a stub that will have the same throwing behavior for all VMs. We
-      // only create stubs for exceptions to allow them being present in catch handlers. See
-      // b/258270051 for more information. Note that throwables in the java namespace are not
-      // stubbed (bailout above).
-      return isThrowable(appView, libraryClass) || stubNonThrowableClasses;
-    }
-
     private boolean isThrowable(AppView<?> appView, DexLibraryClass libraryClass) {
       DexClass current = libraryClass;
       while (current.getSuperType() != null) {
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 5d32ca1..322b30f 100644
--- a/src/test/java/com/android/tools/r8/apimodel/ApiModelMockInheritedClassTest.java
+++ b/src/test/java/com/android/tools/r8/apimodel/ApiModelMockInheritedClassTest.java
@@ -6,8 +6,7 @@
 
 import static com.android.tools.r8.apimodel.ApiModelingTestHelper.setMockApiLevelForClass;
 import static com.android.tools.r8.apimodel.ApiModelingTestHelper.setMockApiLevelForDefaultInstanceInitializer;
-import static com.android.tools.r8.utils.codeinspector.Matchers.isAbsent;
-import static org.hamcrest.MatcherAssert.assertThat;
+import static com.android.tools.r8.apimodel.ApiModelingTestHelper.verifyThat;
 import static org.junit.Assume.assumeTrue;
 
 import com.android.tools.r8.CompilationMode;
@@ -98,7 +97,7 @@
   }
 
   private void inspect(CodeInspector inspector) {
-    assertThat(inspector.clazz(LibraryClass.class), isAbsent());
+    verifyThat(inspector, parameters, LibraryClass.class).stubbedUntil(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 a45f683..5d4fc8f 100644
--- a/src/test/java/com/android/tools/r8/apimodel/ApiModelMockSuperChainClassTest.java
+++ b/src/test/java/com/android/tools/r8/apimodel/ApiModelMockSuperChainClassTest.java
@@ -6,8 +6,7 @@
 
 import static com.android.tools.r8.apimodel.ApiModelingTestHelper.setMockApiLevelForClass;
 import static com.android.tools.r8.apimodel.ApiModelingTestHelper.setMockApiLevelForDefaultInstanceInitializer;
-import static com.android.tools.r8.utils.codeinspector.Matchers.isAbsent;
-import static org.hamcrest.MatcherAssert.assertThat;
+import static com.android.tools.r8.apimodel.ApiModelingTestHelper.verifyThat;
 import static org.junit.Assume.assumeTrue;
 
 import com.android.tools.r8.CompilationMode;
@@ -122,9 +121,9 @@
   }
 
   private void inspect(CodeInspector inspector) {
-    assertThat(inspector.clazz(LibraryClass.class), isAbsent());
-    assertThat(inspector.clazz(LibraryInterface.class), isAbsent());
-    assertThat(inspector.clazz(OtherLibraryClass.class), isAbsent());
+    verifyThat(inspector, parameters, LibraryClass.class).stubbedUntil(lowerMockApiLevel);
+    verifyThat(inspector, parameters, LibraryInterface.class).stubbedUntil(lowerMockApiLevel);
+    verifyThat(inspector, parameters, OtherLibraryClass.class).stubbedUntil(mockApiLevel);
   }
 
   private void checkOutput(SingleTestRunResult<?> runResult) {