Fix verifier/linker IncompatibleClassChangeError with hidden API

The verifier and class linker will attempt to find a method with
the wrong type if it could not be found with the original type,
i.e an interface method on a regular class and vice versa.

This logic did not previously take hidden API restrictions into
account and would result in bogus error messages to the user or
debug crashes.

Bug: 64382372
Bug: 77464273
Test: art/test.py -r -t 674-hiddenapi
Change-Id: If8327a70dd73b90249da3d9e505f0c6f89838f8e
diff --git a/runtime/hidden_api.cc b/runtime/hidden_api.cc
index 0e72f27..aa34427 100644
--- a/runtime/hidden_api.cc
+++ b/runtime/hidden_api.cc
@@ -27,6 +27,9 @@
 
 static inline std::ostream& operator<<(std::ostream& os, AccessMethod value) {
   switch (value) {
+    case kNone:
+      LOG(FATAL) << "Internal access to hidden API should not be logged";
+      UNREACHABLE();
     case kReflection:
       os << "reflection";
       break;
@@ -116,6 +119,8 @@
 
 template<typename T>
 Action GetMemberActionImpl(T* member, Action action, AccessMethod access_method) {
+  DCHECK_NE(action, kAllow);
+
   // Get the signature, we need it later.
   MemberSignature member_signature(member);
 
@@ -135,10 +140,12 @@
     }
   }
 
-  // Print a log message with information about this class member access.
-  // We do this regardless of whether we block the access or not.
-  member_signature.WarnAboutAccess(access_method,
-      HiddenApiAccessFlags::DecodeFromRuntime(member->GetAccessFlags()));
+  if (access_method != kNone) {
+    // Print a log message with information about this class member access.
+    // We do this regardless of whether we block the access or not.
+    member_signature.WarnAboutAccess(access_method,
+        HiddenApiAccessFlags::DecodeFromRuntime(member->GetAccessFlags()));
+  }
 
   if (action == kDeny) {
     // Block access
@@ -148,16 +155,18 @@
   // Allow access to this member but print a warning.
   DCHECK(action == kAllowButWarn || action == kAllowButWarnAndToast);
 
-  // Depending on a runtime flag, we might move the member into whitelist and
-  // skip the warning the next time the member is accessed.
-  if (runtime->ShouldDedupeHiddenApiWarnings()) {
-    member->SetAccessFlags(HiddenApiAccessFlags::EncodeForRuntime(
-        member->GetAccessFlags(), HiddenApiAccessFlags::kWhitelist));
-  }
+  if (access_method != kNone) {
+    // Depending on a runtime flag, we might move the member into whitelist and
+    // skip the warning the next time the member is accessed.
+    if (runtime->ShouldDedupeHiddenApiWarnings()) {
+      member->SetAccessFlags(HiddenApiAccessFlags::EncodeForRuntime(
+          member->GetAccessFlags(), HiddenApiAccessFlags::kWhitelist));
+    }
 
-  // If this action requires a UI warning, set the appropriate flag.
-  if (action == kAllowButWarnAndToast || runtime->ShouldAlwaysSetHiddenApiWarningFlag()) {
-    runtime->SetPendingHiddenApiWarning(true);
+    // If this action requires a UI warning, set the appropriate flag.
+    if (action == kAllowButWarnAndToast || runtime->ShouldAlwaysSetHiddenApiWarningFlag()) {
+      runtime->SetPendingHiddenApiWarning(true);
+    }
   }
 
   return action;