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