Add policy for not merging classes with different api level

Bug: 188388130
Change-Id: I92115876f581387918f9d4be374a8fb2788c53eb
diff --git a/src/main/java/com/android/tools/r8/horizontalclassmerging/PolicyScheduler.java b/src/main/java/com/android/tools/r8/horizontalclassmerging/PolicyScheduler.java
index 0d3bf0d..4abddc6 100644
--- a/src/main/java/com/android/tools/r8/horizontalclassmerging/PolicyScheduler.java
+++ b/src/main/java/com/android/tools/r8/horizontalclassmerging/PolicyScheduler.java
@@ -21,6 +21,7 @@
 import com.android.tools.r8.horizontalclassmerging.policies.NoDeadLocks;
 import com.android.tools.r8.horizontalclassmerging.policies.NoDefaultInterfaceMethodCollisions;
 import com.android.tools.r8.horizontalclassmerging.policies.NoDefaultInterfaceMethodMerging;
+import com.android.tools.r8.horizontalclassmerging.policies.NoDifferentApiReferenceLevel;
 import com.android.tools.r8.horizontalclassmerging.policies.NoDirectRuntimeTypeChecks;
 import com.android.tools.r8.horizontalclassmerging.policies.NoEnums;
 import com.android.tools.r8.horizontalclassmerging.policies.NoIllegalInlining;
@@ -199,6 +200,7 @@
         new SameParentClass(),
         new SyntheticItemsPolicy(appView, mode),
         new RespectPackageBoundaries(appView),
+        new NoDifferentApiReferenceLevel(appView),
         new PreventClassMethodAndDefaultMethodCollisions(appView));
   }
 
diff --git a/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/NoDifferentApiReferenceLevel.java b/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/NoDifferentApiReferenceLevel.java
new file mode 100644
index 0000000..97d8d21
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/horizontalclassmerging/policies/NoDifferentApiReferenceLevel.java
@@ -0,0 +1,42 @@
+// Copyright (c) 2020, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+package com.android.tools.r8.horizontalclassmerging.policies;
+
+import com.android.tools.r8.androidapi.AndroidApiReferenceLevelCache;
+import com.android.tools.r8.graph.AppView;
+import com.android.tools.r8.graph.DexProgramClass;
+import com.android.tools.r8.horizontalclassmerging.MultiClassSameReferencePolicy;
+import com.android.tools.r8.utils.AndroidApiLevel;
+
+public class NoDifferentApiReferenceLevel extends MultiClassSameReferencePolicy<AndroidApiLevel> {
+
+  private final AndroidApiReferenceLevelCache apiReferenceLevelCache;
+  private final AndroidApiLevel minApi;
+  // TODO(b/188388130): Remove when stabilized.
+  private final boolean enableApiCallerIdentification;
+
+  public NoDifferentApiReferenceLevel(AppView<?> appView) {
+    apiReferenceLevelCache = AndroidApiReferenceLevelCache.create(appView);
+    minApi = appView.options().minApiLevel;
+    enableApiCallerIdentification =
+        appView.options().apiModelingOptions().enableApiCallerIdentification;
+  }
+
+  @Override
+  public boolean shouldSkipPolicy() {
+    return !enableApiCallerIdentification;
+  }
+
+  @Override
+  public String getName() {
+    return "NoDifferentApiReferenceLevel";
+  }
+
+  @Override
+  public AndroidApiLevel getMergeKey(DexProgramClass clazz) {
+    assert enableApiCallerIdentification;
+    return clazz.getApiReferenceLevel(minApi, apiReferenceLevelCache::lookupMax);
+  }
+}
diff --git a/src/test/java/com/android/tools/r8/apimodel/ApiModelClassMergingWithDifferentApiFieldsTest.java b/src/test/java/com/android/tools/r8/apimodel/ApiModelClassMergingWithDifferentApiFieldsTest.java
index 2f4e83c..cb837ac 100644
--- a/src/test/java/com/android/tools/r8/apimodel/ApiModelClassMergingWithDifferentApiFieldsTest.java
+++ b/src/test/java/com/android/tools/r8/apimodel/ApiModelClassMergingWithDifferentApiFieldsTest.java
@@ -41,9 +41,15 @@
         .setMinApi(parameters.getApiLevel())
         .addKeepMainRule(Main.class)
         .enableInliningAnnotations()
-        // TODO(b/138781768): Should not be merged
         .addHorizontallyMergedClassesInspector(
-            inspector -> inspector.assertClassesMerged(A.class, B.class))
+            inspector -> {
+              if (parameters.isDexRuntime()
+                  && parameters.getApiLevel().isGreaterThanOrEqualTo(AndroidApiLevel.L_MR1)) {
+                inspector.assertClassesMerged(A.class, B.class);
+              } else {
+                inspector.assertNoClassesMerged();
+              }
+            })
         .apply(ApiModelingTestHelper::enableApiCallerIdentification)
         .apply(setMockApiLevelForClass(Api.class, AndroidApiLevel.L_MR1))
         .compile()
diff --git a/src/test/java/com/android/tools/r8/apimodel/ApiModelClassMergingWithDifferentApiMethodsTest.java b/src/test/java/com/android/tools/r8/apimodel/ApiModelClassMergingWithDifferentApiMethodsTest.java
index f174546..0eeb405 100644
--- a/src/test/java/com/android/tools/r8/apimodel/ApiModelClassMergingWithDifferentApiMethodsTest.java
+++ b/src/test/java/com/android/tools/r8/apimodel/ApiModelClassMergingWithDifferentApiMethodsTest.java
@@ -42,9 +42,15 @@
         .setMinApi(parameters.getApiLevel())
         .addKeepMainRule(Main.class)
         .enableInliningAnnotations()
-        // TODO(b/138781768): Should not be merged
         .addHorizontallyMergedClassesInspector(
-            inspector -> inspector.assertClassesMerged(A.class, B.class))
+            inspector -> {
+              if (parameters.isDexRuntime()
+                  && parameters.getApiLevel().isGreaterThanOrEqualTo(AndroidApiLevel.L_MR1)) {
+                inspector.assertClassesMerged(A.class, B.class);
+              } else {
+                inspector.assertNoClassesMerged();
+              }
+            })
         .apply(ApiModelingTestHelper::enableApiCallerIdentification)
         .apply(setMockApiLevelForMethod(apiMethod, AndroidApiLevel.L_MR1))
         .compile()