Clean up #includes in `hidden_api.h`.
Move one template function `ShouldDenyAccessToMember()` to
the .cc file and reduce the amount of code included by .h.
Test: m test-art-host-gtest
Test: testrunner.py --host --optimizing
Change-Id: Ic969902cd0fa3b57e11eb9d8a8413f4f71a6d28b
diff --git a/runtime/hidden_api.cc b/runtime/hidden_api.cc
index f42ed49..9e2ad92 100644
--- a/runtime/hidden_api.cc
+++ b/runtime/hidden_api.cc
@@ -590,5 +590,121 @@
AccessMethod access_method);
} // namespace detail
+template<typename T>
+bool ShouldDenyAccessToMember(T* member,
+ const std::function<AccessContext()>& fn_get_access_context,
+ AccessMethod access_method) {
+ DCHECK(member != nullptr);
+
+ // First check if we have an explicit sdk checker installed that should be used to
+ // verify access. If so, make the decision based on it.
+ //
+ // This is used during off-device AOT compilation which may want to generate verification
+ // metadata only for a specific list of public SDKs. Note that the check here is made
+ // based on descriptor equality and it's aim to further restrict a symbol that would
+ // otherwise be resolved.
+ //
+ // The check only applies to boot classpaths dex files.
+ Runtime* runtime = Runtime::Current();
+ if (UNLIKELY(runtime->IsAotCompiler())) {
+ if (member->GetDeclaringClass()->GetClassLoader() == nullptr &&
+ runtime->GetClassLinker()->DenyAccessBasedOnPublicSdk(member)) {
+ return true;
+ }
+ }
+
+ // Get the runtime flags encoded in member's access flags.
+ // Note: this works for proxy methods because they inherit access flags from their
+ // respective interface methods.
+ const uint32_t runtime_flags = GetRuntimeFlags(member);
+
+ // Exit early if member is public API. This flag is also set for non-boot class
+ // path fields/methods.
+ if ((runtime_flags & kAccPublicApi) != 0) {
+ return false;
+ }
+
+ // Determine which domain the caller and callee belong to.
+ // This can be *very* expensive. This is why ShouldDenyAccessToMember
+ // should not be called on every individual access.
+ const AccessContext caller_context = fn_get_access_context();
+ const AccessContext callee_context(member->GetDeclaringClass());
+
+ // Non-boot classpath callers should have exited early.
+ DCHECK(!callee_context.IsApplicationDomain());
+
+ // Check if the caller is always allowed to access members in the callee context.
+ if (caller_context.CanAlwaysAccess(callee_context)) {
+ return false;
+ }
+
+ // Check if this is platform accessing core platform. We may warn if `member` is
+ // not part of core platform API.
+ switch (caller_context.GetDomain()) {
+ case Domain::kApplication: {
+ DCHECK(!callee_context.IsApplicationDomain());
+
+ // Exit early if access checks are completely disabled.
+ EnforcementPolicy policy = runtime->GetHiddenApiEnforcementPolicy();
+ if (policy == EnforcementPolicy::kDisabled) {
+ return false;
+ }
+
+ // If this is a proxy method, look at the interface method instead.
+ member = detail::GetInterfaceMemberIfProxy(member);
+
+ // Decode hidden API access flags from the dex file.
+ // This is an O(N) operation scaling with the number of fields/methods
+ // in the class. Only do this on slow path and only do it once.
+ ApiList api_list(detail::GetDexFlags(member));
+ DCHECK(api_list.IsValid());
+
+ // Member is hidden and caller is not exempted. Enter slow path.
+ return detail::ShouldDenyAccessToMemberImpl(member, api_list, access_method);
+ }
+
+ case Domain::kPlatform: {
+ DCHECK(callee_context.GetDomain() == Domain::kCorePlatform);
+
+ // Member is part of core platform API. Accessing it is allowed.
+ if ((runtime_flags & kAccCorePlatformApi) != 0) {
+ return false;
+ }
+
+ // Allow access if access checks are disabled.
+ EnforcementPolicy policy = Runtime::Current()->GetCorePlatformApiEnforcementPolicy();
+ if (policy == EnforcementPolicy::kDisabled) {
+ return false;
+ }
+
+ // If this is a proxy method, look at the interface method instead.
+ member = detail::GetInterfaceMemberIfProxy(member);
+
+ // Access checks are not disabled, report the violation.
+ // 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: {
+ LOG(FATAL) << "CorePlatform domain should be allowed to access all domains";
+ UNREACHABLE();
+ }
+ }
+}
+
+// Need to instantiate these.
+template bool ShouldDenyAccessToMember<ArtField>(
+ ArtField* member,
+ const std::function<AccessContext()>& fn_get_access_context,
+ AccessMethod access_method);
+template bool ShouldDenyAccessToMember<ArtMethod>(
+ ArtMethod* member,
+ const std::function<AccessContext()>& fn_get_access_context,
+ AccessMethod access_method);
+
} // namespace hiddenapi
} // namespace art
diff --git a/runtime/hidden_api.h b/runtime/hidden_api.h
index 94ef0c5..11c058c 100644
--- a/runtime/hidden_api.h
+++ b/runtime/hidden_api.h
@@ -22,9 +22,11 @@
#include "base/hiddenapi_domain.h"
#include "base/hiddenapi_flags.h"
#include "base/locks.h"
+#include "dex/class_accessor.h"
#include "intrinsics_enum.h"
#include "jni/jni_internal.h"
-#include "mirror/class-inl.h"
+#include "mirror/class.h"
+#include "mirror/class_loader.h"
#include "reflection.h"
#include "runtime.h"
#include "well_known_classes.h"
@@ -395,111 +397,10 @@
// considered.
// This function might print warnings into the log if the member is hidden.
template<typename T>
-inline bool ShouldDenyAccessToMember(T* member,
- const std::function<AccessContext()>& fn_get_access_context,
- AccessMethod access_method)
- REQUIRES_SHARED(Locks::mutator_lock_) {
- DCHECK(member != nullptr);
-
- // First check if we have an explicit sdk checker installed that should be used to
- // verify access. If so, make the decision based on it.
- //
- // This is used during off-device AOT compilation which may want to generate verification
- // metadata only for a specific list of public SDKs. Note that the check here is made
- // based on descriptor equality and it's aim to further restrict a symbol that would
- // otherwise be resolved.
- //
- // The check only applies to boot classpaths dex files.
- Runtime* runtime = Runtime::Current();
- if (UNLIKELY(runtime->IsAotCompiler())) {
- if (member->GetDeclaringClass()->GetClassLoader() == nullptr &&
- runtime->GetClassLinker()->DenyAccessBasedOnPublicSdk(member)) {
- return true;
- }
- }
-
- // Get the runtime flags encoded in member's access flags.
- // Note: this works for proxy methods because they inherit access flags from their
- // respective interface methods.
- const uint32_t runtime_flags = GetRuntimeFlags(member);
-
- // Exit early if member is public API. This flag is also set for non-boot class
- // path fields/methods.
- if ((runtime_flags & kAccPublicApi) != 0) {
- return false;
- }
-
- // Determine which domain the caller and callee belong to.
- // This can be *very* expensive. This is why ShouldDenyAccessToMember
- // should not be called on every individual access.
- const AccessContext caller_context = fn_get_access_context();
- const AccessContext callee_context(member->GetDeclaringClass());
-
- // Non-boot classpath callers should have exited early.
- DCHECK(!callee_context.IsApplicationDomain());
-
- // Check if the caller is always allowed to access members in the callee context.
- if (caller_context.CanAlwaysAccess(callee_context)) {
- return false;
- }
-
- // Check if this is platform accessing core platform. We may warn if `member` is
- // not part of core platform API.
- switch (caller_context.GetDomain()) {
- case Domain::kApplication: {
- DCHECK(!callee_context.IsApplicationDomain());
-
- // Exit early if access checks are completely disabled.
- EnforcementPolicy policy = runtime->GetHiddenApiEnforcementPolicy();
- if (policy == EnforcementPolicy::kDisabled) {
- return false;
- }
-
- // If this is a proxy method, look at the interface method instead.
- member = detail::GetInterfaceMemberIfProxy(member);
-
- // Decode hidden API access flags from the dex file.
- // This is an O(N) operation scaling with the number of fields/methods
- // in the class. Only do this on slow path and only do it once.
- ApiList api_list(detail::GetDexFlags(member));
- DCHECK(api_list.IsValid());
-
- // Member is hidden and caller is not exempted. Enter slow path.
- return detail::ShouldDenyAccessToMemberImpl(member, api_list, access_method);
- }
-
- case Domain::kPlatform: {
- DCHECK(callee_context.GetDomain() == Domain::kCorePlatform);
-
- // Member is part of core platform API. Accessing it is allowed.
- if ((runtime_flags & kAccCorePlatformApi) != 0) {
- return false;
- }
-
- // Allow access if access checks are disabled.
- EnforcementPolicy policy = Runtime::Current()->GetCorePlatformApiEnforcementPolicy();
- if (policy == EnforcementPolicy::kDisabled) {
- return false;
- }
-
- // If this is a proxy method, look at the interface method instead.
- member = detail::GetInterfaceMemberIfProxy(member);
-
- // Access checks are not disabled, report the violation.
- // 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: {
- LOG(FATAL) << "CorePlatform domain should be allowed to access all domains";
- UNREACHABLE();
- }
- }
-}
+bool ShouldDenyAccessToMember(T* member,
+ const std::function<AccessContext()>& fn_get_access_context,
+ AccessMethod access_method)
+ REQUIRES_SHARED(Locks::mutator_lock_);
// Helper method for callers where access context can be determined beforehand.
// Wraps AccessContext in a lambda and passes it to the real ShouldDenyAccessToMember.