Fix interface method linking for an edge case.

Make sure we select the implementation from the most-derived
class for an interface method if the superclass has more
than one method with the matching signature in its vtable.

Test: New tests in 182-method-linking.
Test: m test-art-host-gtest
Test: testrunner.py --host --optimizing --jvm
Bug: 211854716
Change-Id: Iee843e1acf56b576b864abbcd9c28a69b1862eeb
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index 580ae03..64adc55 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -8096,10 +8096,22 @@
       } else {
         auto it2 = super_vtable_signatures.FindWithHash(interface_method, hash);
         if (it2 != super_vtable_signatures.end()) {
-          // FIXME: If there are multiple vtable methods with the same signature, the one
-          // with the highest vtable index is not nessarily the one in most-derived class.
-          // However, we're preserving old behavior for now. b/211854716
+          // If there are multiple vtable methods with the same signature, the one with
+          // the highest vtable index is not nessarily the one in most-derived class.
+          // Find the most-derived method. See b/211854716 .
           vtable_method = super_vtable_accessor.GetVTableEntry(*it2);
+          if (UNLIKELY(!same_signature_vtable_lists.empty())) {
+            size_t current_index = *it2;
+            while (same_signature_vtable_lists[current_index] != dex::kDexNoIndex) {
+              DCHECK_LT(same_signature_vtable_lists[current_index], current_index);
+              current_index = same_signature_vtable_lists[current_index];
+              ArtMethod* current_method = super_vtable_accessor.GetVTableEntry(current_index);
+              ObjPtr<mirror::Class> current_class = current_method->GetDeclaringClass();
+              if (current_class->IsSubClass(vtable_method->GetDeclaringClass())) {
+                vtable_method = current_method;
+              }
+            }
+          }
           found = true;
         }
       }
@@ -8107,6 +8119,7 @@
       if (found) {
         DCHECK(vtable_method != nullptr);
         if (!vtable_method->IsAbstract() && !vtable_method->IsPublic()) {
+          // FIXME: Delay the exception until we actually try to call the method. b/211854716
           sants.reset();
           ThrowIllegalAccessErrorForImplementingMethod(klass, vtable_method, interface_method);
           return 0u;
diff --git a/test/182-method-linking/expected-stdout.txt b/test/182-method-linking/expected-stdout.txt
index 712b0d7..56ad59d 100644
--- a/test/182-method-linking/expected-stdout.txt
+++ b/test/182-method-linking/expected-stdout.txt
@@ -32,3 +32,19 @@
 pkg2.D2.foo
 Calling pkg2.D2.foo on pkg2.D2
 pkg2.D2.foo
+Calling pkg1.I1.foo on pkg1.C2I1
+pkg1.C2.foo
+Calling pkg2.I2.foo on pkg1.C2I2
+pkg1.C2.foo
+Calling pkg1.I1.foo on pkg2.D2I1
+pkg2.D2.foo
+Calling pkg2.I2.foo on pkg2.D2I2
+pkg2.D2.foo
+Calling pkg1.I1.foo on pkg1.CXI1
+Caught IllegalAccessError
+Calling pkg2.I2.foo on pkg1.CXI2
+Caught IllegalAccessError
+Calling pkg1.I1.foo on pkg2.DXI1
+Caught IllegalAccessError
+Calling pkg2.I2.foo on pkg2.DXI2
+Caught IllegalAccessError
diff --git a/test/182-method-linking/src/Main.java b/test/182-method-linking/src/Main.java
index 50102c1..3902956 100644
--- a/test/182-method-linking/src/Main.java
+++ b/test/182-method-linking/src/Main.java
@@ -17,12 +17,28 @@
 import pkg1.A;
 import pkg1.C;
 import pkg1.C2;
+import pkg1.C2I1;
+import pkg1.C2I2;
+import pkg1.CXI1;
+import pkg1.CXI2;
+import pkg1.I1;
 import pkg2.B;
 import pkg2.D;
 import pkg2.D2;
+import pkg2.D2I1;
+import pkg2.D2I2;
+import pkg2.DXI1;
+import pkg2.DXI2;
+import pkg2.I2;
 
 public class Main {
     public static void main(String args[]) {
+        try {
+            Class.forName("dalvik.system.PathClassLoader");
+        } catch (ClassNotFoundException e) {
+            usingRI = true;
+        }
+
         // A single method signature can result in multiple vtable entries
         // when package-private methods from different packages are involved.
         // All classes here define the method `void foo()` but classes
@@ -63,5 +79,82 @@
         d2.callBFoo();  // pkg2.D2.foo (overrides package-private pkg2.B.foo in the same package)
         d2.callC2Foo();  // pkg2.D2.foo (overrides public pkg2.C2.foo)
         d2.callD2Foo();  // pkg2.D2.foo
+
+        // Interface methods always target the method in the most-derived class with implementation
+        // even when package-private methods from different packages are involved.
+        //
+        // Test interface calls through the following interfaces:
+        //    interface pkg1.I1 { ... }
+        //    interface pkg2.I2 { ... }
+        // that declare a public `void foo()` for concrete classes
+        //    class pkg1.C2I1 extends pkg1.C2 implements pkg1.I1 {}
+        //    class pkg1.C2I2 extends pkg1.C2 implements pkg2.I2 {}
+        //    class pkg2.D2I1 extends pkg2.D2 implements pkg1.I1 {}
+        //    class pkg2.D2I2 extends pkg2.D2 implements pkg2.I2 {}
+        //    class pkg1.CXI1 extends pkg1.CX implements pkg1.I1 {}
+        //    class pkg1.CXI2 extends pkg1.CX implements pkg2.I2 {}
+        //    class pkg2.DXI1 extends pkg2.DX implements pkg1.I1 {}
+        //    class pkg2.DXI2 extends pkg2.DX implements pkg2.I2 {}
+        // with helper classes `pkg1.C2` and `pkg2.D2` from previous tests and helper class
+        //    class pkg2.BX extends pkg1.A { ... }
+        // defining a public `void foo()` but helper classes
+        //    class pkg1.CX extends pkg2.BX { ... }
+        //    class pkg2.DX extends pkg1.CX { ... }
+        // defining a package-private `void foo()`. This is a compilation error in Java,
+        // so we're using different definitions for `pkg1.I1`, `pkg2.I2` and `pkg2.BX` in
+        // src/ for compiling other classes and in src2/ for their run-time definition.
+
+        C2I1 c2i1 = new C2I1();
+        I1.callI1Foo(c2i1);  // pkg1.C2.foo
+
+        C2I2 c2i2 = new C2I2();
+        I2.callI2Foo(c2i2);  // pkg1.C2.foo
+
+        D2I1 d2i1 = new D2I1();
+        I1.callI1Foo(d2i1);  // pkg1.D2.foo
+
+        D2I2 d2i2 = new D2I2();
+        I2.callI2Foo(d2i2);  // pkg1.D2.foo
+
+        try {
+            CXI1 cxi1 = new CXI1();
+            I1.callI1Foo(cxi1);
+        } catch (IllegalAccessError expected) {
+            printOnDalvik("Calling pkg1.I1.foo on pkg1.CXI1");
+            System.out.println("Caught IllegalAccessError");
+        }
+
+        try {
+            CXI2 cxi2 = new CXI2();
+            I2.callI2Foo(cxi2);
+        } catch (IllegalAccessError expected) {
+            printOnDalvik("Calling pkg2.I2.foo on pkg1.CXI2");
+            System.out.println("Caught IllegalAccessError");
+        }
+
+        try {
+            DXI1 dxi1 = new DXI1();
+            I1.callI1Foo(dxi1);
+        } catch (IllegalAccessError expected) {
+            printOnDalvik("Calling pkg1.I1.foo on pkg2.DXI1");
+            System.out.println("Caught IllegalAccessError");
+        }
+
+        try {
+            DXI2 dxi2 = new DXI2();
+            I2.callI2Foo(dxi2);
+        } catch (IllegalAccessError expected) {
+            printOnDalvik("Calling pkg2.I2.foo on pkg2.DXI2");
+            System.out.println("Caught IllegalAccessError");
+        }
     }
+
+    private static void printOnDalvik(String line) {
+        if (!usingRI) {
+            // FIXME: Delay IAE until calling the method. Bug: 211854716
+            System.out.println(line);
+        }
+    }
+
+    private static boolean usingRI = false;
 }
diff --git a/test/182-method-linking/src/pkg1/C2I1.java b/test/182-method-linking/src/pkg1/C2I1.java
new file mode 100644
index 0000000..de4f7a2
--- /dev/null
+++ b/test/182-method-linking/src/pkg1/C2I1.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package pkg1;
+
+public class C2I1 extends C2 implements I1 {
+}
diff --git a/test/182-method-linking/src/pkg1/C2I2.java b/test/182-method-linking/src/pkg1/C2I2.java
new file mode 100644
index 0000000..43464e7
--- /dev/null
+++ b/test/182-method-linking/src/pkg1/C2I2.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package pkg1;
+
+import pkg2.I2;
+
+public class C2I2 extends C2 implements I2 {
+}
diff --git a/test/182-method-linking/src/pkg1/CX.java b/test/182-method-linking/src/pkg1/CX.java
new file mode 100644
index 0000000..ffb0d03
--- /dev/null
+++ b/test/182-method-linking/src/pkg1/CX.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package pkg1;
+
+import pkg2.BX;
+
+public class CX extends BX {
+    /*package-private*/ void foo() {
+        System.out.println("pkg1.CX.foo");
+    }
+}
diff --git a/test/182-method-linking/src/pkg1/CXI1.java b/test/182-method-linking/src/pkg1/CXI1.java
new file mode 100644
index 0000000..2884d3a
--- /dev/null
+++ b/test/182-method-linking/src/pkg1/CXI1.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package pkg1;
+
+public class CXI1 extends CX implements I1 {
+}
diff --git a/test/182-method-linking/src/pkg1/CXI2.java b/test/182-method-linking/src/pkg1/CXI2.java
new file mode 100644
index 0000000..1029e03
--- /dev/null
+++ b/test/182-method-linking/src/pkg1/CXI2.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package pkg1;
+
+import pkg2.I2;
+
+public class CXI2 extends CX implements I2 {
+}
diff --git a/test/182-method-linking/src/pkg1/I1.java b/test/182-method-linking/src/pkg1/I1.java
new file mode 100644
index 0000000..793dca5
--- /dev/null
+++ b/test/182-method-linking/src/pkg1/I1.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package pkg1;
+
+// This definition is used for compiling but the interface used at runtime is in src2/.
+// The commented out code below is enabled in src2/.
+public interface I1 {
+    static void callI1Foo(I1 i1) {
+        System.out.println("Calling pkg1.I1.foo on " + i1.getClass().getName());
+        // i1.foo();
+    };
+
+    // void foo();
+}
diff --git a/test/182-method-linking/src/pkg2/BX.java b/test/182-method-linking/src/pkg2/BX.java
new file mode 100644
index 0000000..2265d24
--- /dev/null
+++ b/test/182-method-linking/src/pkg2/BX.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package pkg2;
+
+import pkg1.A;
+
+// This definition is used for compiling but the class used at runtime is in src2/.
+public class BX extends A {
+    /* public in src2/ */ void foo() {
+        System.out.println("pkg2.BX.foo");
+    }
+}
diff --git a/test/182-method-linking/src/pkg2/D2I1.java b/test/182-method-linking/src/pkg2/D2I1.java
new file mode 100644
index 0000000..0b18758
--- /dev/null
+++ b/test/182-method-linking/src/pkg2/D2I1.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package pkg2;
+
+import pkg1.I1;
+
+public class D2I1 extends D2 implements I1 {
+}
diff --git a/test/182-method-linking/src/pkg2/D2I2.java b/test/182-method-linking/src/pkg2/D2I2.java
new file mode 100644
index 0000000..9e58f44
--- /dev/null
+++ b/test/182-method-linking/src/pkg2/D2I2.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package pkg2;
+
+public class D2I2 extends D2 implements I2 {
+}
diff --git a/test/182-method-linking/src/pkg2/DX.java b/test/182-method-linking/src/pkg2/DX.java
new file mode 100644
index 0000000..4927cda
--- /dev/null
+++ b/test/182-method-linking/src/pkg2/DX.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package pkg2;
+
+import pkg1.CX;
+
+public class DX extends CX {
+    /*package-private*/ void foo() {
+        System.out.println("pkg1.DX.foo");
+    }
+}
diff --git a/test/182-method-linking/src/pkg2/DXI1.java b/test/182-method-linking/src/pkg2/DXI1.java
new file mode 100644
index 0000000..cb4ca8a
--- /dev/null
+++ b/test/182-method-linking/src/pkg2/DXI1.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package pkg2;
+
+import pkg1.I1;
+
+public class DXI1 extends DX implements I1 {
+}
diff --git a/test/182-method-linking/src/pkg2/DXI2.java b/test/182-method-linking/src/pkg2/DXI2.java
new file mode 100644
index 0000000..de29a76
--- /dev/null
+++ b/test/182-method-linking/src/pkg2/DXI2.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package pkg2;
+
+public class DXI2 extends DX implements I2 {
+}
diff --git a/test/182-method-linking/src/pkg2/I2.java b/test/182-method-linking/src/pkg2/I2.java
new file mode 100644
index 0000000..abce043
--- /dev/null
+++ b/test/182-method-linking/src/pkg2/I2.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package pkg2;
+
+// This definition is used for compiling but the interface used at runtime is in src2/.
+// The commented out code below is enabled in src2/.
+public interface I2 {
+    static void callI2Foo(I2 i2) {
+        System.out.println("Calling pkg2.I2.foo on " + i2.getClass().getName());
+        // i2.foo();
+    };
+
+    // void foo();
+}
diff --git a/test/182-method-linking/src2/pkg1/I1.java b/test/182-method-linking/src2/pkg1/I1.java
new file mode 100644
index 0000000..14cac9c
--- /dev/null
+++ b/test/182-method-linking/src2/pkg1/I1.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package pkg1;
+
+// This is the interface class I1 used at runtime.
+public interface I1 {
+    static void callI1Foo(I1 i1) {
+        System.out.println("Calling pkg1.I1.foo on " + i1.getClass().getName());
+        i1.foo();
+    };
+
+    void foo();
+}
diff --git a/test/182-method-linking/src2/pkg2/BX.java b/test/182-method-linking/src2/pkg2/BX.java
new file mode 100644
index 0000000..7634563
--- /dev/null
+++ b/test/182-method-linking/src2/pkg2/BX.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package pkg2;
+
+import pkg1.A;
+
+// This is the class BX used at runtime.
+public class BX extends A {
+    public void foo() {
+        System.out.println("pkg2.BX.foo");
+    }
+}
diff --git a/test/182-method-linking/src2/pkg2/I2.java b/test/182-method-linking/src2/pkg2/I2.java
new file mode 100644
index 0000000..4e004c5
--- /dev/null
+++ b/test/182-method-linking/src2/pkg2/I2.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package pkg2;
+
+// This is the interface class I2 used at runtime.
+public interface I2 {
+    static void callI2Foo(I2 i2) {
+        System.out.println("Calling pkg2.I2.foo on " + i2.getClass().getName());
+        i2.foo();
+    };
+
+    void foo();
+}