Ensure rebound target has same or lower api level as static target

Bug: b/234613774
Change-Id: Icae862637d3a886b1f66967c012116ddd4cb0fd8
diff --git a/src/main/java/com/android/tools/r8/optimize/MemberRebindingAnalysis.java b/src/main/java/com/android/tools/r8/optimize/MemberRebindingAnalysis.java
index b7e591b..c7395e9 100644
--- a/src/main/java/com/android/tools/r8/optimize/MemberRebindingAnalysis.java
+++ b/src/main/java/com/android/tools/r8/optimize/MemberRebindingAnalysis.java
@@ -103,7 +103,8 @@
           currentResolutionResult.withInitialResolutionHolder(
               currentResolutionResult.getResolvedHolder()),
           contexts,
-          invokeType)) {
+          invokeType,
+          original)) {
         eligibleLibraryMethod = currentResolvedMethod.asLibraryMethod();
       }
       if (appView.appInfo().isAssumeMethod(currentResolvedMethod)) {
@@ -140,7 +141,8 @@
       DexClassAndMethod resolvedMethod,
       SingleResolutionResult resolutionResult,
       ProgramMethodSet contexts,
-      Type invokeType) {
+      Type invokeType,
+      DexMethod original) {
     // TODO(b/194422791): It could potentially be that `original.holder` is not a subtype of
     //  `original.holder` on all API levels, in which case it is not OK to rebind to the resolved
     //  method.
@@ -149,7 +151,7 @@
         && !isInvokeSuperToInterfaceMethod(resolvedMethod, invokeType)
         && !isInvokeSuperToAbstractMethod(resolvedMethod, invokeType)
         && isApiSafeForMemberRebinding(
-            resolvedMethod.asLibraryMethod(), androidApiLevelCompute, options);
+            resolvedMethod.asLibraryMethod(), original, androidApiLevelCompute, options);
   }
 
   private boolean isAccessibleInAllContexts(
diff --git a/src/main/java/com/android/tools/r8/utils/AndroidApiLevelUtils.java b/src/main/java/com/android/tools/r8/utils/AndroidApiLevelUtils.java
index 8eb6b51..374459a 100644
--- a/src/main/java/com/android/tools/r8/utils/AndroidApiLevelUtils.java
+++ b/src/main/java/com/android/tools/r8/utils/AndroidApiLevelUtils.java
@@ -8,6 +8,7 @@
 import com.android.tools.r8.androidapi.ComputedApiLevel;
 import com.android.tools.r8.graph.AppView;
 import com.android.tools.r8.graph.DexEncodedMethod;
+import com.android.tools.r8.graph.DexMethod;
 import com.android.tools.r8.graph.DexProgramClass;
 import com.android.tools.r8.graph.LibraryMethod;
 import com.android.tools.r8.graph.ProgramMethod;
@@ -78,6 +79,7 @@
 
   public static boolean isApiSafeForMemberRebinding(
       LibraryMethod method,
+      DexMethod original,
       AndroidApiLevelCompute androidApiLevelCompute,
       InternalOptions options) {
     ComputedApiLevel apiLevel =
@@ -87,6 +89,17 @@
       return false;
     }
     assert options.apiModelingOptions().enableApiCallerIdentification;
-    return apiLevel.asKnownApiLevel().getApiLevel().isLessThanOrEqualTo(options.getMinApiLevel());
+    ComputedApiLevel apiLevelOfOriginal =
+        androidApiLevelCompute.computeApiLevelForLibraryReference(
+            original, ComputedApiLevel.unknown());
+    if (apiLevelOfOriginal.isUnknownApiLevel()) {
+      return false;
+    }
+    return apiLevelOfOriginal
+        .asKnownApiLevel()
+        .max(apiLevel)
+        .asKnownApiLevel()
+        .getApiLevel()
+        .isLessThanOrEqualTo(options.getMinApiLevel());
   }
 }
diff --git a/src/test/java/com/android/tools/r8/memberrebinding/LibraryMemberRebindingSuperTypeWithApiMethodTest.java b/src/test/java/com/android/tools/r8/memberrebinding/LibraryMemberRebindingSuperTypeWithApiMethodTest.java
index 04a051a..c474de2 100644
--- a/src/test/java/com/android/tools/r8/memberrebinding/LibraryMemberRebindingSuperTypeWithApiMethodTest.java
+++ b/src/test/java/com/android/tools/r8/memberrebinding/LibraryMemberRebindingSuperTypeWithApiMethodTest.java
@@ -55,8 +55,7 @@
         .run(parameters.getRuntime(), Main.class)
         .applyIf(
             parameters.getDexRuntimeVersion().isOlderThan(Version.V8_1_0),
-            // TODO(b/234613774): We should not introduce ICCE.
-            result -> result.assertFailureWithErrorThatThrows(IncompatibleClassChangeError.class),
+            result -> result.assertFailureWithErrorThatThrows(NoSuchMethodError.class),
             result -> result.assertFailureWithErrorThatThrows(DestroyFailedException.class));
   }