Fix minor problems with interface verification and default methods.

Previously we would fail verification on some <clinit> methods when
default methods are enabled and they are not marked as public.

Previously we would also give verifier soft failures when using
interface statics.

Bug: 24618811

Change-Id: I735740b4058bfd71e67bc3fb99e6a8c0c4696b01
diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc
index e1d4160..2db79ab 100644
--- a/runtime/verifier/method_verifier.cc
+++ b/runtime/verifier/method_verifier.cc
@@ -665,20 +665,22 @@
       // Interfaces may always have static initializers for their fields. If we are running with
       // default methods enabled we also allow other public, static, non-final methods to have code.
       // Otherwise that is the only type of method allowed.
-      if (runtime->AreExperimentalFlagsEnabled(ExperimentalFlags::kDefaultMethods)) {
-        if (IsInstanceConstructor()) {
-          Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "interfaces may not have non-static constructor";
-          return false;
-        } else if (method_access_flags_ & kAccFinal) {
-          Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "interfaces may not have final methods";
-          return false;
-        } else if (!(method_access_flags_ & kAccPublic)) {
-          Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "interfaces may not have non-public members";
+      if (!(IsConstructor() && IsStatic())) {
+        if (runtime->AreExperimentalFlagsEnabled(ExperimentalFlags::kDefaultMethods)) {
+          if (IsInstanceConstructor()) {
+            Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "interfaces may not have non-static constructor";
+            return false;
+          } else if (method_access_flags_ & kAccFinal) {
+            Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "interfaces may not have final methods";
+            return false;
+          } else if (!(method_access_flags_ & kAccPublic)) {
+            Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "interfaces may not have non-public members";
+            return false;
+          }
+        } else {
+          Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "interface methods must be abstract";
           return false;
         }
-      } else if (!IsConstructor() || !IsStatic()) {
-        Fail(VERIFY_ERROR_BAD_CLASS_HARD) << "interface methods must be abstract";
-        return false;
       }
     }
 
@@ -3662,8 +3664,15 @@
                                       << PrettyMethod(res_method);
     return nullptr;
   }
-  // Check that interface methods match interface classes.
-  if (klass->IsInterface() && method_type != METHOD_INTERFACE) {
+  // Check that interface methods are static or match interface classes.
+  // We only allow statics if we don't have default methods enabled.
+  Runtime* runtime = Runtime::Current();
+  const bool default_methods_supported =
+      runtime == nullptr ||
+      runtime->AreExperimentalFlagsEnabled(ExperimentalFlags::kDefaultMethods);
+  if (klass->IsInterface() &&
+      method_type != METHOD_INTERFACE &&
+      (!default_methods_supported || method_type != METHOD_STATIC)) {
     Fail(VERIFY_ERROR_CLASS_CHANGE) << "non-interface method " << PrettyMethod(res_method)
                                     << " is in an interface class " << PrettyClass(klass);
     return nullptr;
diff --git a/test/962-iface-static/smali/Displayer.smali b/test/962-iface-static/smali/Displayer.smali
index 06bec16..ed4c013 100644
--- a/test/962-iface-static/smali/Displayer.smali
+++ b/test/962-iface-static/smali/Displayer.smali
@@ -27,7 +27,7 @@
 .class public LDisplayer;
 .super Ljava/lang/Object;
 
-.method public static <clinit>()V
+.method static constructor <clinit>()V
     .locals 3
     sget-object v1, Ljava/lang/System;->out:Ljava/io/PrintStream;
     const-string v0, "init"
diff --git a/test/962-iface-static/smali/iface.smali b/test/962-iface-static/smali/iface.smali
index 441aae6..5b9c03e 100644
--- a/test/962-iface-static/smali/iface.smali
+++ b/test/962-iface-static/smali/iface.smali
@@ -27,7 +27,7 @@
 
 .field public final static f:LDisplayer;
 
-.method public static <clinit>()V
+.method static constructor <clinit>()V
     .locals 3
     new-instance v1, LDisplayer;
     invoke-direct {v1}, LDisplayer;-><init>()V
diff --git a/test/964-default-iface-init-generated/util-src/generate_smali.py b/test/964-default-iface-init-generated/util-src/generate_smali.py
index be2d3ba..3c138ab 100755
--- a/test/964-default-iface-init-generated/util-src/generate_smali.py
+++ b/test/964-default-iface-init-generated/util-src/generate_smali.py
@@ -334,7 +334,7 @@
 #   public static final Displayer field = new Displayer("{tree}");
 .field public final static field:LDisplayer;
 
-.method public static constructor <clinit>()V
+.method static constructor <clinit>()V
     .locals 3
     const-string v2, "{tree}"
     new-instance v1, LDisplayer;