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