Reenable core platform API violation warnings, dedupe

Print a warning the first time a non-core platform API member is
accessed and add kAccCorePlatformApi to its access flags to not report
it next time. Only do this when policy is kJustWarn. This prevents
logspam.

Bug: 125701194
Bug: 119068555
Test: compiles, boots
Test: art/test.py -b -r -t 674
Change-Id: Ia7d6ba4f1f30fbea7bdea1670183c17f84ca1150
diff --git a/runtime/hidden_api.cc b/runtime/hidden_api.cc
index 68ed102..b458582 100644
--- a/runtime/hidden_api.cc
+++ b/runtime/hidden_api.cc
@@ -260,10 +260,10 @@
 }
 
 template<typename T>
-static ALWAYS_INLINE void MaybeWhitelistMember(Runtime* runtime, T* member)
+static ALWAYS_INLINE void MaybeUpdateAccessFlags(Runtime* runtime, T* member, uint32_t flag)
     REQUIRES_SHARED(Locks::mutator_lock_) {
   if (CanUpdateRuntimeFlags(member) && runtime->ShouldDedupeHiddenApiWarnings()) {
-    member->SetAccessFlags(member->GetAccessFlags() | kAccPublicApi);
+    member->SetAccessFlags(member->GetAccessFlags() | flag);
   }
 }
 
@@ -357,14 +357,27 @@
 }
 
 template<typename T>
-void MaybeReportCorePlatformApiViolation(T* member,
-                                         const AccessContext& caller_context,
-                                         AccessMethod access_method) {
+bool HandleCorePlatformApiViolation(T* member,
+                                    const AccessContext& caller_context,
+                                    AccessMethod access_method,
+                                    EnforcementPolicy policy) {
+  DCHECK(policy != EnforcementPolicy::kDisabled)
+      << "Should never enter this function when access checks are completely disabled";
+
   if (access_method != AccessMethod::kNone) {
-    MemberSignature sig(member);
-    LOG(ERROR) << "CorePlatformApi violation: " << Dumpable<MemberSignature>(sig)
-               << " from " << caller_context << " using " << access_method;
+    LOG(WARNING) << "Core platform API violation: "
+        << Dumpable<MemberSignature>(MemberSignature(member))
+        << " from " << caller_context << " using " << access_method;
+
+    // If policy is set to just warn, add kAccCorePlatformApi to access flags of
+    // `member` to avoid reporting the violation again next time.
+    if (policy == EnforcementPolicy::kJustWarn) {
+      MaybeUpdateAccessFlags(Runtime::Current(), member, kAccCorePlatformApi);
+    }
   }
+
+  // Deny access if enforcement is enabled.
+  return policy == EnforcementPolicy::kEnabled;
 }
 
 template<typename T>
@@ -388,7 +401,7 @@
     // Avoid re-examining the exemption list next time.
     // Note this results in no warning for the member, which seems like what one would expect.
     // Exemptions effectively adds new members to the whitelist.
-    MaybeWhitelistMember(runtime, member);
+    MaybeUpdateAccessFlags(runtime, member, kAccPublicApi);
     return false;
   }
 
@@ -418,7 +431,7 @@
     // If this access was not denied, move the member into whitelist and skip
     // the warning the next time the member is accessed.
     if (!deny_access) {
-      MaybeWhitelistMember(runtime, member);
+      MaybeUpdateAccessFlags(runtime, member, kAccPublicApi);
     }
   }
 
@@ -428,12 +441,14 @@
 // Need to instantiate these.
 template uint32_t GetDexFlags<ArtField>(ArtField* member);
 template uint32_t GetDexFlags<ArtMethod>(ArtMethod* member);
-template void MaybeReportCorePlatformApiViolation(ArtField* member,
-                                                  const AccessContext& caller_context,
-                                                  AccessMethod access_method);
-template void MaybeReportCorePlatformApiViolation(ArtMethod* member,
-                                                  const AccessContext& caller_context,
-                                                  AccessMethod access_method);
+template bool HandleCorePlatformApiViolation(ArtField* member,
+                                             const AccessContext& caller_context,
+                                             AccessMethod access_method,
+                                             EnforcementPolicy policy);
+template bool HandleCorePlatformApiViolation(ArtMethod* member,
+                                             const AccessContext& caller_context,
+                                             AccessMethod access_method,
+                                             EnforcementPolicy policy);
 template bool ShouldDenyAccessToMemberImpl<ArtField>(ArtField* member,
                                                      ApiList api_list,
                                                      AccessMethod access_method);
diff --git a/runtime/hidden_api.h b/runtime/hidden_api.h
index 0a40341..08a9fff 100644
--- a/runtime/hidden_api.h
+++ b/runtime/hidden_api.h
@@ -80,8 +80,7 @@
   ObjPtr<mirror::Class> GetClass() const { return klass_; }
   const DexFile* GetDexFile() const { return dex_file_; }
   Domain GetDomain() const { return domain_; }
-
-  bool IsUntrustedDomain() const { return domain_ == Domain::kApplication; }
+  bool IsApplicationDomain() const { return domain_ == Domain::kApplication; }
 
   // Returns true if this domain is always allowed to access the domain of `callee`.
   bool CanAlwaysAccess(const AccessContext& callee) const {
@@ -212,10 +211,13 @@
 template<typename T>
 uint32_t GetDexFlags(T* member) REQUIRES_SHARED(Locks::mutator_lock_);
 
+// Handler of detected core platform API violations. Returns true if access to
+// `member` should be denied.
 template<typename T>
-void MaybeReportCorePlatformApiViolation(T* member,
-                                         const AccessContext& caller_context,
-                                         AccessMethod access_method)
+bool HandleCorePlatformApiViolation(T* member,
+                                    const AccessContext& caller_context,
+                                    AccessMethod access_method,
+                                    EnforcementPolicy policy)
     REQUIRES_SHARED(Locks::mutator_lock_);
 
 template<typename T>
@@ -385,7 +387,7 @@
   const AccessContext callee_context(member->GetDeclaringClass());
 
   // Non-boot classpath callers should have exited early.
-  DCHECK(!callee_context.IsUntrustedDomain());
+  DCHECK(!callee_context.IsApplicationDomain());
 
   // Check if the caller is always allowed to access members in the callee context.
   if (caller_context.CanAlwaysAccess(callee_context)) {
@@ -396,7 +398,7 @@
   // not part of core platform API.
   switch (caller_context.GetDomain()) {
     case Domain::kApplication: {
-      DCHECK(!callee_context.IsUntrustedDomain());
+      DCHECK(!callee_context.IsApplicationDomain());
 
       // Exit early if access checks are completely disabled.
       EnforcementPolicy policy = Runtime::Current()->GetHiddenApiEnforcementPolicy();
@@ -435,10 +437,12 @@
       member = detail::GetInterfaceMemberIfProxy(member);
 
       // Access checks are not disabled, report the violation.
-      // detail::MaybeReportCorePlatformApiViolation(member, caller_context, access_method);
-
-      // Deny access if the policy is enabled.
-      return policy == EnforcementPolicy::kEnabled;
+      // This may also add kAccCorePlatformApi to the access flags of `member`
+      // so as to not warn again on next access.
+      return detail::HandleCorePlatformApiViolation(member,
+                                                    caller_context,
+                                                    access_method,
+                                                    policy);
     }
 
     case Domain::kCorePlatform: {