[ApiModel] Add default instance initializer for stubbed classes
Bug: 211031432
Bug: 211601391
Change-Id: I395c5eb94f394ae64d682e318ed3352e8e2840ca
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 5071174..a62e3a8 100644
--- a/src/main/java/com/android/tools/r8/androidapi/ApiReferenceStubber.java
+++ b/src/main/java/com/android/tools/r8/androidapi/ApiReferenceStubber.java
@@ -6,6 +6,7 @@
import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
import com.android.tools.r8.graph.AppView;
+import com.android.tools.r8.graph.DefaultInstanceInitializerCode;
import com.android.tools.r8.graph.DexClass;
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexField;
@@ -285,14 +286,20 @@
|| !method.isStatic()
|| appView.options().canUseDefaultAndStaticInterfaceMethods();
DexMethod newMethod = method.getReference().withHolder(clazz.type, appView.dexItemFactory());
- boolean isVirtualInterfaceMethod = method.isVirtualMethod() && clazz.isInterface();
- return DexEncodedMethod.syntheticBuilder(method)
- .setMethod(newMethod)
- .modifyAccessFlags(MethodAccessFlags::setSynthetic)
- .applyIf(isVirtualInterfaceMethod, b -> b.modifyAccessFlags(MethodAccessFlags::setAbstract))
- .applyIf(
- !isVirtualInterfaceMethod && !method.isAbstract(),
- b -> b.modifyAccessFlags(MethodAccessFlags::setNative))
- .build();
+ DexEncodedMethod.Builder methodBuilder =
+ DexEncodedMethod.syntheticBuilder(method)
+ .setMethod(newMethod)
+ .modifyAccessFlags(MethodAccessFlags::setSynthetic);
+ if (method.isInstanceInitializer()) {
+ methodBuilder.setCode(DefaultInstanceInitializerCode.get());
+ } else if (method.isVirtualMethod() && clazz.isInterface()) {
+ methodBuilder.modifyAccessFlags(MethodAccessFlags::setAbstract);
+ } else if (method.isAbstract()) {
+ methodBuilder.modifyAccessFlags(MethodAccessFlags::setAbstract);
+ } else {
+ // To allow us not adding a trivial throwing code body we set the access flag as native.
+ methodBuilder.modifyAccessFlags(MethodAccessFlags::setNative);
+ }
+ return methodBuilder.build();
}
}
diff --git a/src/test/java/com/android/tools/r8/apimodel/ApiModelMockClassInstanceInitTest.java b/src/test/java/com/android/tools/r8/apimodel/ApiModelMockClassInstanceInitTest.java
index 78b4d5d..153759b 100644
--- a/src/test/java/com/android/tools/r8/apimodel/ApiModelMockClassInstanceInitTest.java
+++ b/src/test/java/com/android/tools/r8/apimodel/ApiModelMockClassInstanceInitTest.java
@@ -8,6 +8,7 @@
import static com.android.tools.r8.apimodel.ApiModelingTestHelper.setMockApiLevelForDefaultInstanceInitializer;
import static com.android.tools.r8.apimodel.ApiModelingTestHelper.verifyThat;
import static org.hamcrest.CoreMatchers.containsString;
+import static org.hamcrest.CoreMatchers.not;
import static org.junit.Assume.assumeFalse;
import com.android.tools.r8.NeverInline;
@@ -62,15 +63,7 @@
!isMockApiLevel
&& parameters.isDexRuntime()
&& parameters.getDexRuntimeVersion().isNewerThanOrEqual(Version.V7_0_0),
- result -> {
- result.assertStderrMatches(containsString("This dex file is invalid"));
- result.assertStderrMatches(
- containsString(
- "Constructor 2("
- + descriptor(LibraryClass.class)
- + ".<init>)"
- + " must not be abstract or native"));
- });
+ result -> result.assertStderrMatches(not(containsString("This dex file is invalid"))));
}
// Only present from api level 23.