Add GetSourceFile and GetSourceDebugExt JVMTI functions

Also add associated capabilities.

Test: ./test.py --host -j40
Bug: 62821960

Change-Id: Icc534b2789287fc9f0daddb747c0c0fa81a7728b
diff --git a/runtime/openjdkjvmti/OpenjdkJvmTi.cc b/runtime/openjdkjvmti/OpenjdkJvmTi.cc
index 8daf6f7..0896210 100644
--- a/runtime/openjdkjvmti/OpenjdkJvmTi.cc
+++ b/runtime/openjdkjvmti/OpenjdkJvmTi.cc
@@ -686,12 +686,10 @@
     return ClassUtil::GetClassStatus(env, klass, status_ptr);
   }
 
-  static jvmtiError GetSourceFileName(jvmtiEnv* env,
-                                      jclass klass ATTRIBUTE_UNUSED,
-                                      char** source_name_ptr ATTRIBUTE_UNUSED) {
+  static jvmtiError GetSourceFileName(jvmtiEnv* env, jclass klass, char** source_name_ptr) {
     ENSURE_VALID_ENV(env);
     ENSURE_HAS_CAP(env, can_get_source_file_name);
-    return ERR(NOT_IMPLEMENTED);
+    return ClassUtil::GetSourceFileName(env, klass, source_name_ptr);
   }
 
   static jvmtiError GetClassModifiers(jvmtiEnv* env, jclass klass, jint* modifiers_ptr) {
@@ -766,11 +764,11 @@
   }
 
   static jvmtiError GetSourceDebugExtension(jvmtiEnv* env,
-                                            jclass klass ATTRIBUTE_UNUSED,
-                                            char** source_debug_extension_ptr ATTRIBUTE_UNUSED) {
+                                            jclass klass,
+                                            char** source_debug_extension_ptr) {
     ENSURE_VALID_ENV(env);
     ENSURE_HAS_CAP(env, can_get_source_debug_extension);
-    return ERR(NOT_IMPLEMENTED);
+    return ClassUtil::GetSourceDebugExtension(env, klass, source_debug_extension_ptr);
   }
 
   static jvmtiError RetransformClasses(jvmtiEnv* env, jint class_count, const jclass* classes) {
diff --git a/runtime/openjdkjvmti/art_jvmti.h b/runtime/openjdkjvmti/art_jvmti.h
index 8ba3527..b5f1219 100644
--- a/runtime/openjdkjvmti/art_jvmti.h
+++ b/runtime/openjdkjvmti/art_jvmti.h
@@ -218,9 +218,9 @@
     .can_pop_frame                                   = 0,
     .can_redefine_classes                            = 1,
     .can_signal_thread                               = 0,
-    .can_get_source_file_name                        = 0,
+    .can_get_source_file_name                        = 1,
     .can_get_line_numbers                            = 1,
-    .can_get_source_debug_extension                  = 0,
+    .can_get_source_debug_extension                  = 1,
     .can_access_local_variables                      = 0,
     .can_maintain_original_method_order              = 0,
     .can_generate_single_step_events                 = 0,
diff --git a/runtime/openjdkjvmti/ti_class.cc b/runtime/openjdkjvmti/ti_class.cc
index 3321814..0ac08d9 100644
--- a/runtime/openjdkjvmti/ti_class.cc
+++ b/runtime/openjdkjvmti/ti_class.cc
@@ -1017,4 +1017,61 @@
   return ERR(NONE);
 }
 
+jvmtiError ClassUtil::GetSourceFileName(jvmtiEnv* env, jclass jklass, char** source_name_ptr) {
+  art::ScopedObjectAccess soa(art::Thread::Current());
+  if (jklass == nullptr) {
+    return ERR(INVALID_CLASS);
+  }
+  art::ObjPtr<art::mirror::Object> jklass_obj = soa.Decode<art::mirror::Object>(jklass);
+  if (!jklass_obj->IsClass()) {
+    return ERR(INVALID_CLASS);
+  }
+  art::ObjPtr<art::mirror::Class> klass = jklass_obj->AsClass();
+  if (klass->IsPrimitive() || klass->IsArrayClass()) {
+    return ERR(ABSENT_INFORMATION);
+  }
+  JvmtiUniquePtr<char[]> source_copy;
+  const char* file_name = klass->GetSourceFile();
+  if (file_name == nullptr) {
+    return ERR(ABSENT_INFORMATION);
+  }
+  jvmtiError ret;
+  source_copy = CopyString(env, file_name, &ret);
+  if (source_copy == nullptr) {
+    return ret;
+  }
+  *source_name_ptr = source_copy.release();
+  return OK;
+}
+
+jvmtiError ClassUtil::GetSourceDebugExtension(jvmtiEnv* env,
+                                              jclass jklass,
+                                              char** source_debug_extension_ptr) {
+  art::ScopedObjectAccess soa(art::Thread::Current());
+  if (jklass == nullptr) {
+    return ERR(INVALID_CLASS);
+  }
+  art::ObjPtr<art::mirror::Object> jklass_obj = soa.Decode<art::mirror::Object>(jklass);
+  if (!jklass_obj->IsClass()) {
+    return ERR(INVALID_CLASS);
+  }
+  art::StackHandleScope<1> hs(art::Thread::Current());
+  art::Handle<art::mirror::Class> klass(hs.NewHandle(jklass_obj->AsClass()));
+  if (klass->IsPrimitive() || klass->IsArrayClass()) {
+    return ERR(ABSENT_INFORMATION);
+  }
+  JvmtiUniquePtr<char[]> ext_copy;
+  const char* data = art::annotations::GetSourceDebugExtension(klass);
+  if (data == nullptr) {
+    return ERR(ABSENT_INFORMATION);
+  }
+  jvmtiError ret;
+  ext_copy = CopyString(env, data, &ret);
+  if (ext_copy == nullptr) {
+    return ret;
+  }
+  *source_debug_extension_ptr = ext_copy.release();
+  return OK;
+}
+
 }  // namespace openjdkjvmti
diff --git a/runtime/openjdkjvmti/ti_class.h b/runtime/openjdkjvmti/ti_class.h
index aa2260f..7bb6b3e 100644
--- a/runtime/openjdkjvmti/ti_class.h
+++ b/runtime/openjdkjvmti/ti_class.h
@@ -82,6 +82,12 @@
                                            jclass klass,
                                            jint* minor_version_ptr,
                                            jint* major_version_ptr);
+
+  static jvmtiError GetSourceFileName(jvmtiEnv* env, jclass klass, char** source_name_ptr);
+
+  static jvmtiError GetSourceDebugExtension(jvmtiEnv* env,
+                                            jclass klass,
+                                            char** source_debug_extension_ptr);
 };
 
 }  // namespace openjdkjvmti