Add capability checks to all functions.

Also ensure that we declare all capabilities we support.

Bug: 31684920
Bug: 31455788
Test: mma -j40 test-art-host
Change-Id: Ic3f251f451cf6dad9934109594652f23d228d0f4
diff --git a/runtime/openjdkjvmti/OpenjdkJvmTi.cc b/runtime/openjdkjvmti/OpenjdkJvmTi.cc
index 417d104..c0c301fa 100644
--- a/runtime/openjdkjvmti/OpenjdkJvmTi.cc
+++ b/runtime/openjdkjvmti/OpenjdkJvmTi.cc
@@ -138,6 +138,7 @@
   }
 
   static jvmtiError SuspendThread(jvmtiEnv* env, jthread thread) {
+    ENSURE_HAS_CAP(env, can_suspend);
     return ERR(NOT_IMPLEMENTED);
   }
 
@@ -145,10 +146,12 @@
                                       jint request_count,
                                       const jthread* request_list,
                                       jvmtiError* results) {
+    ENSURE_HAS_CAP(env, can_suspend);
     return ERR(NOT_IMPLEMENTED);
   }
 
   static jvmtiError ResumeThread(jvmtiEnv* env, jthread thread) {
+    ENSURE_HAS_CAP(env, can_suspend);
     return ERR(NOT_IMPLEMENTED);
   }
 
@@ -156,14 +159,17 @@
                                      jint request_count,
                                      const jthread* request_list,
                                      jvmtiError* results) {
+    ENSURE_HAS_CAP(env, can_suspend);
     return ERR(NOT_IMPLEMENTED);
   }
 
   static jvmtiError StopThread(jvmtiEnv* env, jthread thread, jobject exception) {
+    ENSURE_HAS_CAP(env, can_signal_thread);
     return ERR(NOT_IMPLEMENTED);
   }
 
   static jvmtiError InterruptThread(jvmtiEnv* env, jthread thread) {
+    ENSURE_HAS_CAP(env, can_signal_thread);
     return ERR(NOT_IMPLEMENTED);
   }
 
@@ -175,6 +181,7 @@
                                         jthread thread,
                                         jint* owned_monitor_count_ptr,
                                         jobject** owned_monitors_ptr) {
+    ENSURE_HAS_CAP(env, can_get_owned_monitor_info);
     return ERR(NOT_IMPLEMENTED);
   }
 
@@ -182,12 +189,14 @@
                                                   jthread thread,
                                                   jint* monitor_info_count_ptr,
                                                   jvmtiMonitorStackDepthInfo** monitor_info_ptr) {
+    ENSURE_HAS_CAP(env, can_get_owned_monitor_stack_depth_info);
     return ERR(NOT_IMPLEMENTED);
   }
 
   static jvmtiError GetCurrentContendedMonitor(jvmtiEnv* env,
                                                jthread thread,
                                                jobject* monitor_ptr) {
+    ENSURE_HAS_CAP(env, can_get_current_contended_monitor);
     return ERR(NOT_IMPLEMENTED);
   }
 
@@ -271,6 +280,7 @@
   }
 
   static jvmtiError PopFrame(jvmtiEnv* env, jthread thread) {
+    ENSURE_HAS_CAP(env, can_pop_frame);
     return ERR(NOT_IMPLEMENTED);
   }
 
@@ -283,30 +293,37 @@
   }
 
   static jvmtiError NotifyFramePop(jvmtiEnv* env, jthread thread, jint depth) {
+    ENSURE_HAS_CAP(env, can_generate_frame_pop_events);
     return ERR(NOT_IMPLEMENTED);
   }
 
   static jvmtiError ForceEarlyReturnObject(jvmtiEnv* env, jthread thread, jobject value) {
+    ENSURE_HAS_CAP(env, can_force_early_return);
     return ERR(NOT_IMPLEMENTED);
   }
 
   static jvmtiError ForceEarlyReturnInt(jvmtiEnv* env, jthread thread, jint value) {
+    ENSURE_HAS_CAP(env, can_force_early_return);
     return ERR(NOT_IMPLEMENTED);
   }
 
   static jvmtiError ForceEarlyReturnLong(jvmtiEnv* env, jthread thread, jlong value) {
+    ENSURE_HAS_CAP(env, can_force_early_return);
     return ERR(NOT_IMPLEMENTED);
   }
 
   static jvmtiError ForceEarlyReturnFloat(jvmtiEnv* env, jthread thread, jfloat value) {
+    ENSURE_HAS_CAP(env, can_force_early_return);
     return ERR(NOT_IMPLEMENTED);
   }
 
   static jvmtiError ForceEarlyReturnDouble(jvmtiEnv* env, jthread thread, jdouble value) {
+    ENSURE_HAS_CAP(env, can_force_early_return);
     return ERR(NOT_IMPLEMENTED);
   }
 
   static jvmtiError ForceEarlyReturnVoid(jvmtiEnv* env, jthread thread) {
+    ENSURE_HAS_CAP(env, can_force_early_return);
     return ERR(NOT_IMPLEMENTED);
   }
 
@@ -316,6 +333,7 @@
                                      jobject initial_object,
                                      const jvmtiHeapCallbacks* callbacks,
                                      const void* user_data) {
+    ENSURE_HAS_CAP(env, can_tag_objects);
     HeapUtil heap_util(&gObjectTagTable);
     return heap_util.FollowReferences(env,
                                       heap_filter,
@@ -402,6 +420,7 @@
       jobject object,
       jvmtiObjectReferenceCallback object_reference_callback,
       const void* user_data) {
+    ENSURE_HAS_CAP(env, can_tag_objects);
     return ERR(NOT_IMPLEMENTED);
   }
 
@@ -410,6 +429,7 @@
                                                 jvmtiStackReferenceCallback stack_ref_callback,
                                                 jvmtiObjectReferenceCallback object_ref_callback,
                                                 const void* user_data) {
+    ENSURE_HAS_CAP(env, can_tag_objects);
     return ERR(NOT_IMPLEMENTED);
   }
 
@@ -417,6 +437,7 @@
                                     jvmtiHeapObjectFilter object_filter,
                                     jvmtiHeapObjectCallback heap_object_callback,
                                     const void* user_data) {
+    ENSURE_HAS_CAP(env, can_tag_objects);
     return ERR(NOT_IMPLEMENTED);
   }
 
@@ -425,6 +446,7 @@
                                                 jvmtiHeapObjectFilter object_filter,
                                                 jvmtiHeapObjectCallback heap_object_callback,
                                                 const void* user_data) {
+    ENSURE_HAS_CAP(env, can_tag_objects);
     return ERR(NOT_IMPLEMENTED);
   }
 
@@ -433,6 +455,7 @@
                                    jint depth,
                                    jint slot,
                                    jobject* value_ptr) {
+    ENSURE_HAS_CAP(env, can_access_local_variables);
     return ERR(NOT_IMPLEMENTED);
   }
 
@@ -440,6 +463,7 @@
                                      jthread thread,
                                      jint depth,
                                      jobject* value_ptr) {
+    ENSURE_HAS_CAP(env, can_access_local_variables);
     return ERR(NOT_IMPLEMENTED);
   }
 
@@ -448,6 +472,7 @@
                                 jint depth,
                                 jint slot,
                                 jint* value_ptr) {
+    ENSURE_HAS_CAP(env, can_access_local_variables);
     return ERR(NOT_IMPLEMENTED);
   }
 
@@ -456,6 +481,7 @@
                                  jint depth,
                                  jint slot,
                                  jlong* value_ptr) {
+    ENSURE_HAS_CAP(env, can_access_local_variables);
     return ERR(NOT_IMPLEMENTED);
   }
 
@@ -464,6 +490,7 @@
                                   jint depth,
                                   jint slot,
                                   jfloat* value_ptr) {
+    ENSURE_HAS_CAP(env, can_access_local_variables);
     return ERR(NOT_IMPLEMENTED);
   }
 
@@ -472,6 +499,7 @@
                                    jint depth,
                                    jint slot,
                                    jdouble* value_ptr) {
+    ENSURE_HAS_CAP(env, can_access_local_variables);
     return ERR(NOT_IMPLEMENTED);
   }
 
@@ -480,6 +508,7 @@
                                    jint depth,
                                    jint slot,
                                    jobject value) {
+    ENSURE_HAS_CAP(env, can_access_local_variables);
     return ERR(NOT_IMPLEMENTED);
   }
 
@@ -488,6 +517,7 @@
                                 jint depth,
                                 jint slot,
                                 jint value) {
+    ENSURE_HAS_CAP(env, can_access_local_variables);
     return ERR(NOT_IMPLEMENTED);
   }
 
@@ -496,6 +526,7 @@
                                  jint depth,
                                  jint slot,
                                  jlong value) {
+    ENSURE_HAS_CAP(env, can_access_local_variables);
     return ERR(NOT_IMPLEMENTED);
   }
 
@@ -504,6 +535,7 @@
                                   jint depth,
                                   jint slot,
                                   jfloat value) {
+    ENSURE_HAS_CAP(env, can_access_local_variables);
     return ERR(NOT_IMPLEMENTED);
   }
 
@@ -512,30 +544,37 @@
                                    jint depth,
                                    jint slot,
                                    jdouble value) {
+    ENSURE_HAS_CAP(env, can_access_local_variables);
     return ERR(NOT_IMPLEMENTED);
   }
 
   static jvmtiError SetBreakpoint(jvmtiEnv* env, jmethodID method, jlocation location) {
+    ENSURE_HAS_CAP(env, can_generate_breakpoint_events);
     return ERR(NOT_IMPLEMENTED);
   }
 
   static jvmtiError ClearBreakpoint(jvmtiEnv* env, jmethodID method, jlocation location) {
+    ENSURE_HAS_CAP(env, can_generate_breakpoint_events);
     return ERR(NOT_IMPLEMENTED);
   }
 
   static jvmtiError SetFieldAccessWatch(jvmtiEnv* env, jclass klass, jfieldID field) {
+    ENSURE_HAS_CAP(env, can_generate_field_access_events);
     return ERR(NOT_IMPLEMENTED);
   }
 
   static jvmtiError ClearFieldAccessWatch(jvmtiEnv* env, jclass klass, jfieldID field) {
+    ENSURE_HAS_CAP(env, can_generate_field_access_events);
     return ERR(NOT_IMPLEMENTED);
   }
 
   static jvmtiError SetFieldModificationWatch(jvmtiEnv* env, jclass klass, jfieldID field) {
+    ENSURE_HAS_CAP(env, can_generate_field_modification_events);
     return ERR(NOT_IMPLEMENTED);
   }
 
   static jvmtiError ClearFieldModificationWatch(jvmtiEnv* env, jclass klass, jfieldID field) {
+    ENSURE_HAS_CAP(env, can_generate_field_modification_events);
     return ERR(NOT_IMPLEMENTED);
   }
 
@@ -563,6 +602,7 @@
   }
 
   static jvmtiError GetSourceFileName(jvmtiEnv* env, jclass klass, char** source_name_ptr) {
+    ENSURE_HAS_CAP(env, can_get_source_file_name);
     return ERR(NOT_IMPLEMENTED);
   }
 
@@ -603,6 +643,7 @@
                                     jint* constant_pool_count_ptr,
                                     jint* constant_pool_byte_count_ptr,
                                     unsigned char** constant_pool_bytes_ptr) {
+    ENSURE_HAS_CAP(env, can_get_constant_pool);
     return ERR(NOT_IMPLEMENTED);
   }
 
@@ -629,10 +670,12 @@
   static jvmtiError GetSourceDebugExtension(jvmtiEnv* env,
                                             jclass klass,
                                             char** source_debug_extension_ptr) {
+    ENSURE_HAS_CAP(env, can_get_source_debug_extension);
     return ERR(NOT_IMPLEMENTED);
   }
 
   static jvmtiError RetransformClasses(jvmtiEnv* env, jint class_count, const jclass* classes) {
+    ENSURE_HAS_CAP(env, can_retransform_classes);
     std::string error_msg;
     jvmtiError res = Transformer::RetransformClasses(ArtJvmTiEnv::AsArtJvmTiEnv(env),
                                                      art::Runtime::Current(),
@@ -649,6 +692,7 @@
   static jvmtiError RedefineClasses(jvmtiEnv* env,
                                     jint class_count,
                                     const jvmtiClassDefinition* class_definitions) {
+    ENSURE_HAS_CAP(env, can_redefine_classes);
     std::string error_msg;
     jvmtiError res = Redefiner::RedefineClasses(ArtJvmTiEnv::AsArtJvmTiEnv(env),
                                                 art::Runtime::Current(),
@@ -673,6 +717,7 @@
   static jvmtiError GetObjectMonitorUsage(jvmtiEnv* env,
                                           jobject object,
                                           jvmtiMonitorUsage* info_ptr) {
+    ENSURE_HAS_CAP(env, can_get_monitor_info);
     return ERR(NOT_IMPLEMENTED);
   }
 
@@ -703,6 +748,7 @@
                                      jclass klass,
                                      jfieldID field,
                                      jboolean* is_synthetic_ptr) {
+    ENSURE_HAS_CAP(env, can_get_synthetic_attribute);
     return FieldUtil::IsFieldSynthetic(env, klass, field, is_synthetic_ptr);
   }
 
@@ -742,6 +788,7 @@
                                        jmethodID method,
                                        jint* entry_count_ptr,
                                        jvmtiLineNumberEntry** table_ptr) {
+    ENSURE_HAS_CAP(env, can_get_line_numbers);
     return MethodUtil::GetLineNumberTable(env, method, entry_count_ptr, table_ptr);
   }
 
@@ -756,6 +803,7 @@
                                           jmethodID method,
                                           jint* entry_count_ptr,
                                           jvmtiLocalVariableEntry** table_ptr) {
+    ENSURE_HAS_CAP(env, can_access_local_variables);
     return ERR(NOT_IMPLEMENTED);
   }
 
@@ -763,6 +811,7 @@
                                  jmethodID method,
                                  jint* bytecode_count_ptr,
                                  unsigned char** bytecodes_ptr) {
+    ENSURE_HAS_CAP(env, can_get_bytecodes);
     return ERR(NOT_IMPLEMENTED);
   }
 
@@ -771,6 +820,7 @@
   }
 
   static jvmtiError IsMethodSynthetic(jvmtiEnv* env, jmethodID method, jboolean* is_synthetic_ptr) {
+    ENSURE_HAS_CAP(env, can_get_synthetic_attribute);
     return MethodUtil::IsMethodSynthetic(env, method, is_synthetic_ptr);
   }
 
@@ -779,10 +829,12 @@
   }
 
   static jvmtiError SetNativeMethodPrefix(jvmtiEnv* env, const char* prefix) {
+    ENSURE_HAS_CAP(env, can_set_native_method_prefix);
     return ERR(NOT_IMPLEMENTED);
   }
 
   static jvmtiError SetNativeMethodPrefixes(jvmtiEnv* env, jint prefix_count, char** prefixes) {
+    ENSURE_HAS_CAP(env, can_set_native_method_prefix);
     return ERR(NOT_IMPLEMENTED);
   }
 
@@ -855,7 +907,6 @@
                                              jthread event_thread,
                                              ...) {
     ENSURE_VALID_ENV(env);
-    // TODO: Check for capabilities.
     art::Thread* art_thread = nullptr;
     if (event_thread != nullptr) {
       // TODO: Need non-aborting call here, to return JVMTI_ERROR_INVALID_THREAD.
@@ -1053,18 +1104,22 @@
   }
 
   static jvmtiError GetCurrentThreadCpuTimerInfo(jvmtiEnv* env, jvmtiTimerInfo* info_ptr) {
+    ENSURE_HAS_CAP(env, can_get_current_thread_cpu_time);
     return ERR(NOT_IMPLEMENTED);
   }
 
   static jvmtiError GetCurrentThreadCpuTime(jvmtiEnv* env, jlong* nanos_ptr) {
+    ENSURE_HAS_CAP(env, can_get_current_thread_cpu_time);
     return ERR(NOT_IMPLEMENTED);
   }
 
   static jvmtiError GetThreadCpuTimerInfo(jvmtiEnv* env, jvmtiTimerInfo* info_ptr) {
+    ENSURE_HAS_CAP(env, can_get_thread_cpu_time);
     return ERR(NOT_IMPLEMENTED);
   }
 
   static jvmtiError GetThreadCpuTime(jvmtiEnv* env, jthread thread, jlong* nanos_ptr) {
+    ENSURE_HAS_CAP(env, can_get_thread_cpu_time);
     return ERR(NOT_IMPLEMENTED);
   }
 
diff --git a/runtime/openjdkjvmti/art_jvmti.h b/runtime/openjdkjvmti/art_jvmti.h
index 91353e2..106165c 100644
--- a/runtime/openjdkjvmti/art_jvmti.h
+++ b/runtime/openjdkjvmti/art_jvmti.h
@@ -146,7 +146,7 @@
     .can_generate_field_modification_events          = 0,
     .can_generate_field_access_events                = 0,
     .can_get_bytecodes                               = 0,
-    .can_get_synthetic_attribute                     = 0,
+    .can_get_synthetic_attribute                     = 1,
     .can_get_owned_monitor_info                      = 0,
     .can_get_current_contended_monitor               = 0,
     .can_get_monitor_info                            = 0,
@@ -154,7 +154,7 @@
     .can_redefine_classes                            = 1,
     .can_signal_thread                               = 0,
     .can_get_source_file_name                        = 0,
-    .can_get_line_numbers                            = 0,
+    .can_get_line_numbers                            = 1,
     .can_get_source_debug_extension                  = 0,
     .can_access_local_variables                      = 0,
     .can_maintain_original_method_order              = 0,
@@ -171,10 +171,10 @@
     .can_generate_all_class_hook_events              = 0,
     .can_generate_compiled_method_load_events        = 0,
     .can_generate_monitor_events                     = 0,
-    .can_generate_vm_object_alloc_events             = 0,
+    .can_generate_vm_object_alloc_events             = 1,
     .can_generate_native_method_bind_events          = 0,
-    .can_generate_garbage_collection_events          = 0,
-    .can_generate_object_free_events                 = 0,
+    .can_generate_garbage_collection_events          = 1,
+    .can_generate_object_free_events                 = 1,
     .can_force_early_return                          = 0,
     .can_get_owned_monitor_stack_depth_info          = 0,
     .can_get_constant_pool                           = 0,
diff --git a/runtime/openjdkjvmti/events.cc b/runtime/openjdkjvmti/events.cc
index 1da08a0..34492a9 100644
--- a/runtime/openjdkjvmti/events.cc
+++ b/runtime/openjdkjvmti/events.cc
@@ -302,6 +302,64 @@
   }
 }
 
+// Checks to see if the env has the capabilities associated with the given event.
+static bool HasAssociatedCapability(ArtJvmTiEnv* env,
+                                    ArtJvmtiEvent event) {
+  jvmtiCapabilities caps = env->capabilities;
+  switch (event) {
+    case ArtJvmtiEvent::kBreakpoint:
+      return caps.can_generate_breakpoint_events == 1;
+
+    case ArtJvmtiEvent::kCompiledMethodLoad:
+    case ArtJvmtiEvent::kCompiledMethodUnload:
+      return caps.can_generate_compiled_method_load_events == 1;
+
+    case ArtJvmtiEvent::kException:
+    case ArtJvmtiEvent::kExceptionCatch:
+      return caps.can_generate_exception_events == 1;
+
+    case ArtJvmtiEvent::kFieldAccess:
+      return caps.can_generate_field_access_events == 1;
+
+    case ArtJvmtiEvent::kFieldModification:
+      return caps.can_generate_field_modification_events == 1;
+
+    case ArtJvmtiEvent::kFramePop:
+      return caps.can_generate_frame_pop_events == 1;
+
+    case ArtJvmtiEvent::kGarbageCollectionStart:
+    case ArtJvmtiEvent::kGarbageCollectionFinish:
+      return caps.can_generate_garbage_collection_events == 1;
+
+    case ArtJvmtiEvent::kMethodEntry:
+      return caps.can_generate_method_entry_events == 1;
+
+    case ArtJvmtiEvent::kMethodExit:
+      return caps.can_generate_method_exit_events == 1;
+
+    case ArtJvmtiEvent::kMonitorContendedEnter:
+    case ArtJvmtiEvent::kMonitorContendedEntered:
+    case ArtJvmtiEvent::kMonitorWait:
+    case ArtJvmtiEvent::kMonitorWaited:
+      return caps.can_generate_monitor_events == 1;
+
+    case ArtJvmtiEvent::kNativeMethodBind:
+      return caps.can_generate_native_method_bind_events == 1;
+
+    case ArtJvmtiEvent::kObjectFree:
+      return caps.can_generate_object_free_events == 1;
+
+    case ArtJvmtiEvent::kSingleStep:
+      return caps.can_generate_single_step_events == 1;
+
+    case ArtJvmtiEvent::kVmObjectAlloc:
+      return caps.can_generate_vm_object_alloc_events == 1;
+
+    default:
+      return true;
+  }
+}
+
 jvmtiError EventHandler::SetEvent(ArtJvmTiEnv* env,
                                   art::Thread* thread,
                                   ArtJvmtiEvent event,
@@ -318,8 +376,6 @@
     }
   }
 
-  // TODO: Capability check.
-
   if (mode != JVMTI_ENABLE && mode != JVMTI_DISABLE) {
     return ERR(ILLEGAL_ARGUMENT);
   }
@@ -328,6 +384,10 @@
     return ERR(INVALID_EVENT_TYPE);
   }
 
+  if (!HasAssociatedCapability(env, event)) {
+    return ERR(MUST_POSSESS_CAPABILITY);
+  }
+
   bool old_state = global_mask.Test(event);
 
   if (mode == JVMTI_ENABLE) {
diff --git a/test/ti-agent/common_helper.cc b/test/ti-agent/common_helper.cc
index 330f7e1..76a7e72 100644
--- a/test/ti-agent/common_helper.cc
+++ b/test/ti-agent/common_helper.cc
@@ -301,11 +301,36 @@
   }
 }
 
-// TODO Write something useful.
 extern "C" JNIEXPORT void JNICALL Java_Main_doCommonClassRetransformation(JNIEnv* env,
                                                                           jclass,
                                                                           jobjectArray targets) {
-  DoClassRetransformation(jvmti_env, env, targets);
+  jvmtiCapabilities caps;
+  jvmtiError caps_err = jvmti_env->GetCapabilities(&caps);
+  if (caps_err != JVMTI_ERROR_NONE) {
+    env->ThrowNew(env->FindClass("java/lang/Exception"),
+                  "Unable to get current jvmtiEnv capabilities");
+    return;
+  }
+
+  // Allocate a new environment if we don't have the can_retransform_classes capability needed to
+  // call the RetransformClasses function.
+  jvmtiEnv* real_env = nullptr;
+  if (caps.can_retransform_classes != 1) {
+    JavaVM* vm = nullptr;
+    if (env->GetJavaVM(&vm) != 0 ||
+        vm->GetEnv(reinterpret_cast<void**>(&real_env), JVMTI_VERSION_1_0) != 0) {
+      env->ThrowNew(env->FindClass("java/lang/Exception"),
+                    "Unable to create temporary jvmtiEnv for RetransformClasses call.");
+      return;
+    }
+    SetAllCapabilities(real_env);
+  } else {
+    real_env = jvmti_env;
+  }
+  DoClassRetransformation(real_env, env, targets);
+  if (caps.can_retransform_classes != 1) {
+    real_env->DisposeEnvironment();
+  }
 }
 
 // Get all capabilities except those related to retransformation.