Harden hidden api checks.

Also walk past j.l.r in stackwalk for Hidden API. This is a fix for an
asan test failure (691-hiddenapi-proxy) introduced in https://r.android.com/1208005.
Instead of always walking past j.l.r during the stackwalk, this CL adds an
exception for j.l.r.Proxy.

Bug: 142365358
Test: art/test/testrunner/testrunner.py --target --64 -t674-hiddenapi
Test: art/test/testrunner/run_build_test_target.py -j110 art-asan
Change-Id: I98dd46d7070dd2dd4318398d2a5d2ae4ece94015
diff --git a/runtime/native/java_lang_Class.cc b/runtime/native/java_lang_Class.cc
index da87713..2c537c6 100644
--- a/runtime/native/java_lang_Class.cc
+++ b/runtime/native/java_lang_Class.cc
@@ -39,6 +39,7 @@
 #include "mirror/object-inl.h"
 #include "mirror/object_array-alloc-inl.h"
 #include "mirror/object_array-inl.h"
+#include "mirror/proxy.h"
 #include "mirror/string-alloc-inl.h"
 #include "mirror/string-inl.h"
 #include "native_util.h"
@@ -55,12 +56,17 @@
 
 namespace art {
 
+// Should be the same as dalvik.system.VMRuntime.PREVENT_META_REFLECTION_BLACKLIST_ACCESS.
+// Corresponds to a bug id.
+static constexpr uint64_t kPreventMetaReflectionBlacklistAccess = 142365358;
+
 // Walks the stack, finds the caller of this reflective call and returns
 // a hiddenapi AccessContext formed from its declaring class.
 static hiddenapi::AccessContext GetReflectionCaller(Thread* self)
     REQUIRES_SHARED(Locks::mutator_lock_) {
-  // Walk the stack and find the first frame not from java.lang.Class and not
-  // from java.lang.invoke. This is very expensive. Save this till the last.
+  // Walk the stack and find the first frame not from java.lang.Class,
+  // java.lang.invoke or java.lang.reflect. This is very expensive.
+  // Save this till the last.
   struct FirstExternalCallerVisitor : public StackVisitor {
     explicit FirstExternalCallerVisitor(Thread* thread)
         : StackVisitor(thread, nullptr, StackVisitor::StackWalkKind::kIncludeInlinedFrames),
@@ -93,6 +99,16 @@
             && !m->IsClassInitializer()) {
           return true;
         }
+        // Check for classes in the java.lang.reflect package, except for java.lang.reflect.Proxy.
+        // java.lang.reflect.Proxy does its own hidden api checks (https://r.android.com/915496),
+        // and walking over this frame would cause a null pointer dereference
+        // (e.g. in 691-hiddenapi-proxy).
+        ObjPtr<mirror::Class> proxy_class = GetClassRoot<mirror::Proxy>();
+        if (declaring_class->IsInSamePackage(proxy_class) && declaring_class != proxy_class) {
+          if (Runtime::Current()->isChangeEnabled(kPreventMetaReflectionBlacklistAccess)) {
+            return true;
+          }
+        }
       }
 
       caller = m;