Add PermittedSubclasses Class API

Bug: 231930852
Test: atest ClassTest
Test: art/test/testrunner/testrunner.py -t 1980-obsolete-object-cleared
Change-Id: Ic547a4525eab02f1b926ccc756963ee8d8568fa3
diff --git a/runtime/dex/dex_file_annotations.cc b/runtime/dex/dex_file_annotations.cc
index 39f0b87..3dd8ae1 100644
--- a/runtime/dex/dex_file_annotations.cc
+++ b/runtime/dex/dex_file_annotations.cc
@@ -841,6 +841,38 @@
   return annotation_value.value_.GetL();
 }
 
+template<typename T>
+static inline ObjPtr<mirror::ObjectArray<T>> GetAnnotationArrayValue(
+                                     Handle<mirror::Class> klass,
+                                     const char* annotation_name,
+                                     const char* value_name)
+            REQUIRES_SHARED(Locks::mutator_lock_) {
+  ClassData data(klass);
+  const AnnotationSetItem* annotation_set = FindAnnotationSetForClass(data);
+  if (annotation_set == nullptr) {
+    return nullptr;
+  }
+  const AnnotationItem* annotation_item =
+      SearchAnnotationSet(data.GetDexFile(), annotation_set, annotation_name,
+                          DexFile::kDexVisibilitySystem);
+  if (annotation_item == nullptr) {
+    return nullptr;
+  }
+  StackHandleScope<1> hs(Thread::Current());
+  Handle<mirror::Class> class_array_class =
+      hs.NewHandle(GetClassRoot<mirror::ObjectArray<T>>());
+  DCHECK(class_array_class != nullptr);
+  ObjPtr<mirror::Object> obj = GetAnnotationValue(data,
+                                                  annotation_item,
+                                                  value_name,
+                                                  class_array_class,
+                                                  DexFile::kDexAnnotationArray);
+  if (obj == nullptr) {
+    return nullptr;
+  }
+  return obj->AsObjectArray<T>();
+}
+
 static ObjPtr<mirror::ObjectArray<mirror::String>> GetSignatureValue(
     const ClassData& klass,
     const AnnotationSetItem* annotation_set)
@@ -1478,28 +1510,9 @@
 }
 
 ObjPtr<mirror::ObjectArray<mirror::Class>> GetDeclaredClasses(Handle<mirror::Class> klass) {
-  ClassData data(klass);
-  const AnnotationSetItem* annotation_set = FindAnnotationSetForClass(data);
-  if (annotation_set == nullptr) {
-    return nullptr;
-  }
-  const AnnotationItem* annotation_item =
-      SearchAnnotationSet(data.GetDexFile(), annotation_set, "Ldalvik/annotation/MemberClasses;",
-                          DexFile::kDexVisibilitySystem);
-  if (annotation_item == nullptr) {
-    return nullptr;
-  }
-  StackHandleScope<1> hs(Thread::Current());
-  Handle<mirror::Class> class_array_class =
-      hs.NewHandle(GetClassRoot<mirror::ObjectArray<mirror::Class>>());
-  DCHECK(class_array_class != nullptr);
-  ObjPtr<mirror::Object> obj =
-      GetAnnotationValue(data, annotation_item, "value", class_array_class,
-                         DexFile::kDexAnnotationArray);
-  if (obj == nullptr) {
-    return nullptr;
-  }
-  return obj->AsObjectArray<mirror::Class>();
+  return GetAnnotationArrayValue<mirror::Class>(klass,
+                                                "Ldalvik/annotation/MemberClasses;",
+                                                "value");
 }
 
 ObjPtr<mirror::Class> GetDeclaringClass(Handle<mirror::Class> klass) {
@@ -1743,30 +1756,15 @@
 }
 
 ObjPtr<mirror::ObjectArray<mirror::Class>> GetNestMembers(Handle<mirror::Class> klass) {
-  ClassData data(klass);
-  const AnnotationSetItem* annotation_set = FindAnnotationSetForClass(data);
-  if (annotation_set == nullptr) {
-    return nullptr;
-  }
-  const AnnotationItem* annotation_item =
-      SearchAnnotationSet(data.GetDexFile(), annotation_set, "Ldalvik/annotation/NestMembers;",
-                          DexFile::kDexVisibilitySystem);
-  if (annotation_item == nullptr) {
-    return nullptr;
-  }
-  StackHandleScope<1> hs(Thread::Current());
-  Handle<mirror::Class> class_array_class =
-      hs.NewHandle(GetClassRoot<mirror::ObjectArray<mirror::Class>>());
-  DCHECK(class_array_class != nullptr);
-  ObjPtr<mirror::Object> obj = GetAnnotationValue(data,
-                                                  annotation_item,
-                                                  "classes",
-                                                  class_array_class,
-                                                  DexFile::kDexAnnotationArray);
-  if (obj == nullptr) {
-    return nullptr;
-  }
-  return obj->AsObjectArray<mirror::Class>();
+  return GetAnnotationArrayValue<mirror::Class>(klass,
+                                                "Ldalvik/annotation/NestMembers;",
+                                                "classes");
+}
+
+ObjPtr<mirror::ObjectArray<mirror::Class>> GetPermittedSubclasses(Handle<mirror::Class> klass) {
+  return GetAnnotationArrayValue<mirror::Class>(klass,
+                                                "Ldalvik/annotation/PermittedSubclasses;",
+                                                "value");
 }
 
 bool IsClassAnnotationPresent(Handle<mirror::Class> klass, Handle<mirror::Class> annotation_class) {
diff --git a/runtime/dex/dex_file_annotations.h b/runtime/dex/dex_file_annotations.h
index 6b3c03d..75951a7 100644
--- a/runtime/dex/dex_file_annotations.h
+++ b/runtime/dex/dex_file_annotations.h
@@ -140,6 +140,8 @@
     REQUIRES_SHARED(Locks::mutator_lock_);
 ObjPtr<mirror::ObjectArray<mirror::Class>> GetNestMembers(Handle<mirror::Class> klass)
     REQUIRES_SHARED(Locks::mutator_lock_);
+ObjPtr<mirror::ObjectArray<mirror::Class>> GetPermittedSubclasses(Handle<mirror::Class> klass)
+    REQUIRES_SHARED(Locks::mutator_lock_);
 bool IsClassAnnotationPresent(Handle<mirror::Class> klass,
                               Handle<mirror::Class> annotation_class)
     REQUIRES_SHARED(Locks::mutator_lock_);
diff --git a/runtime/mirror/class.h b/runtime/mirror/class.h
index 77c06a8..48fced4 100644
--- a/runtime/mirror/class.h
+++ b/runtime/mirror/class.h
@@ -553,7 +553,7 @@
   // The size of java.lang.Class.class.
   static uint32_t ClassClassSize(PointerSize pointer_size) {
     // The number of vtable entries in java.lang.Class.
-    uint32_t vtable_entries = Object::kVTableLength + 70;
+    uint32_t vtable_entries = Object::kVTableLength + 72;
     return ComputeClassSize(true, vtable_entries, 0, 0, 4, 1, 0, pointer_size);
   }
 
diff --git a/runtime/native/java_lang_Class.cc b/runtime/native/java_lang_Class.cc
index 937099c..6434e63 100644
--- a/runtime/native/java_lang_Class.cc
+++ b/runtime/native/java_lang_Class.cc
@@ -787,6 +787,23 @@
   return soa.AddLocalReference<jobjectArray>(classes);
 }
 
+static jobjectArray Class_getPermittedSubclassesFromAnnotation(JNIEnv* env, jobject javaThis) {
+  ScopedFastNativeObjectAccess soa(env);
+  StackHandleScope<1> hs(soa.Self());
+  Handle<mirror::Class> klass(hs.NewHandle(DecodeClass(soa, javaThis)));
+  if (klass->IsObsoleteObject()) {
+    ThrowRuntimeException("Obsolete Object!");
+    return nullptr;
+  }
+  if (klass->IsProxyClass() || klass->GetDexCache() == nullptr) {
+    return nullptr;
+  }
+  ObjPtr<mirror::ObjectArray<mirror::Class>> classes = annotations::GetPermittedSubclasses(klass);
+  if (classes == nullptr) {
+    return nullptr;
+  }
+  return soa.AddLocalReference<jobjectArray>(classes);
+}
 
 static jobject Class_ensureExtDataPresent(JNIEnv* env, jobject javaThis) {
   ScopedFastNativeObjectAccess soa(env);
@@ -917,6 +934,7 @@
   FAST_NATIVE_METHOD(Class, getNameNative, "()Ljava/lang/String;"),
   FAST_NATIVE_METHOD(Class, getNestHostFromAnnotation, "()Ljava/lang/Class;"),
   FAST_NATIVE_METHOD(Class, getNestMembersFromAnnotation, "()[Ljava/lang/Class;"),
+  FAST_NATIVE_METHOD(Class, getPermittedSubclassesFromAnnotation, "()[Ljava/lang/Class;"),
   FAST_NATIVE_METHOD(Class, getPublicDeclaredFields, "()[Ljava/lang/reflect/Field;"),
   FAST_NATIVE_METHOD(Class, getSignatureAnnotation, "()[Ljava/lang/String;"),
   FAST_NATIVE_METHOD(Class, isAnonymousClass, "()Z"),