| /* |
| * Copyright (C) 2017 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #include "jni.h" |
| |
| #include "android-base/logging.h" |
| #include "android-base/macros.h" |
| #include "common.h" |
| #include "jni_helper.h" |
| #include "jvmti_helper.h" |
| #include "jvmti.h" |
| #include "scoped_primitive_array.h" |
| |
| namespace cts { |
| namespace jvmti { |
| namespace tagging { |
| |
| extern "C" JNIEXPORT void JNICALL Java_android_jvmti_cts_JvmtiTaggingTest_setTag( |
| JNIEnv* env, jclass klass ATTRIBUTE_UNUSED, jobject obj, jlong tag) { |
| jvmtiEnv* jvmti_env = GetJvmtiEnv(); |
| jvmtiError ret = jvmti_env->SetTag(obj, tag); |
| JvmtiErrorToException(env, jvmti_env, ret); |
| } |
| |
| extern "C" JNIEXPORT jlong JNICALL Java_android_jvmti_cts_JvmtiTaggingTest_getTag( |
| JNIEnv* env, jclass klass ATTRIBUTE_UNUSED, jobject obj) { |
| jvmtiEnv* jvmti_env = GetJvmtiEnv(); |
| jlong tag = 0; |
| jvmtiError ret = jvmti_env->GetTag(obj, &tag); |
| if (JvmtiErrorToException(env, jvmti_env, ret)) { |
| return 0; |
| } |
| return tag; |
| } |
| |
| extern "C" JNIEXPORT jobjectArray JNICALL Java_android_jvmti_cts_JvmtiTaggingTest_getTaggedObjects( |
| JNIEnv* env, |
| jclass klass ATTRIBUTE_UNUSED, |
| jlongArray searchTags, |
| jboolean returnObjects, |
| jboolean returnTags) { |
| jvmtiEnv* jvmti_env = GetJvmtiEnv(); |
| ScopedLongArrayRO scoped_array(env); |
| if (searchTags != nullptr) { |
| scoped_array.reset(searchTags); |
| } |
| const jlong* tag_ptr = scoped_array.get(); |
| if (tag_ptr == nullptr) { |
| // Can never pass null. |
| tag_ptr = reinterpret_cast<const jlong*>(1); |
| } |
| |
| jint result_count = -1; |
| jobject* result_object_array = nullptr; |
| jobject** result_object_array_ptr = returnObjects == JNI_TRUE ? &result_object_array : nullptr; |
| jlong* result_tag_array = nullptr; |
| jlong** result_tag_array_ptr = returnTags == JNI_TRUE ? &result_tag_array : nullptr; |
| |
| jvmtiError ret = jvmti_env->GetObjectsWithTags(scoped_array.size(), |
| tag_ptr, |
| &result_count, |
| result_object_array_ptr, |
| result_tag_array_ptr); |
| if (JvmtiErrorToException(env, jvmti_env, ret)) { |
| return nullptr; |
| } |
| |
| CHECK_GE(result_count, 0); |
| |
| jobjectArray resultObjectArray = nullptr; |
| if (returnObjects == JNI_TRUE) { |
| auto callback = [&](jint i) { |
| return result_object_array[i]; |
| }; |
| resultObjectArray = CreateObjectArray(env, result_count, "java/lang/Object", callback); |
| if (resultObjectArray == nullptr) { |
| return nullptr; |
| } |
| } |
| if (result_object_array != nullptr) { |
| CheckJvmtiError(jvmti_env, Deallocate(jvmti_env, result_object_array)); |
| } |
| |
| jlongArray resultTagArray = nullptr; |
| if (returnTags == JNI_TRUE) { |
| resultTagArray = env->NewLongArray(result_count); |
| if (resultTagArray == nullptr) { |
| return nullptr; |
| } |
| env->SetLongArrayRegion(resultTagArray, 0, result_count, result_tag_array); |
| } |
| if (result_tag_array != nullptr) { |
| CheckJvmtiError(jvmti_env, Deallocate(jvmti_env, result_tag_array)); |
| } |
| |
| jobject count_integer; |
| { |
| ScopedLocalRef<jclass> integer_class(env, env->FindClass("java/lang/Integer")); |
| jmethodID methodID = env->GetMethodID(integer_class.get(), "<init>", "(I)V"); |
| count_integer = env->NewObject(integer_class.get(), methodID, result_count); |
| if (count_integer == nullptr) { |
| return nullptr; |
| } |
| } |
| |
| auto callback = [&](jint i) -> jobject { |
| switch(i) { |
| case 0: |
| return resultObjectArray; |
| case 1: |
| return resultTagArray; |
| case 2: |
| return count_integer; |
| default: |
| LOG(FATAL) << "Unexpected"; |
| return nullptr; |
| } |
| }; |
| return CreateObjectArray(env, 3, "java/lang/Object", callback); |
| } |
| |
| } // namespace tagging |
| } // namespace jvmti |
| } // namespace cts |
| |