1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker * Copyright (C) 2020 The Android Open Source Project
3*795d594fSAndroid Build Coastguard Worker *
4*795d594fSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*795d594fSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*795d594fSAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*795d594fSAndroid Build Coastguard Worker *
8*795d594fSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*795d594fSAndroid Build Coastguard Worker *
10*795d594fSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*795d594fSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*795d594fSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*795d594fSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*795d594fSAndroid Build Coastguard Worker * limitations under the License.
15*795d594fSAndroid Build Coastguard Worker */
16*795d594fSAndroid Build Coastguard Worker
17*795d594fSAndroid Build Coastguard Worker #include <jni.h>
18*795d594fSAndroid Build Coastguard Worker
19*795d594fSAndroid Build Coastguard Worker #include <iostream>
20*795d594fSAndroid Build Coastguard Worker
21*795d594fSAndroid Build Coastguard Worker #include "android-base/logging.h"
22*795d594fSAndroid Build Coastguard Worker
23*795d594fSAndroid Build Coastguard Worker struct ThreadArgs {
24*795d594fSAndroid Build Coastguard Worker JavaVM* jvm;
25*795d594fSAndroid Build Coastguard Worker jobject consumer;
26*795d594fSAndroid Build Coastguard Worker JavaVMAttachArgs* attach_args;
27*795d594fSAndroid Build Coastguard Worker bool set_in_java;
28*795d594fSAndroid Build Coastguard Worker };
29*795d594fSAndroid Build Coastguard Worker
30*795d594fSAndroid Build Coastguard Worker // The main method of the test thread. The ThreadArgs controls what this does.
ThreadMain(void * arg)31*795d594fSAndroid Build Coastguard Worker void* ThreadMain(void* arg) {
32*795d594fSAndroid Build Coastguard Worker ThreadArgs* args = reinterpret_cast<ThreadArgs*>(arg);
33*795d594fSAndroid Build Coastguard Worker JNIEnv* env = nullptr;
34*795d594fSAndroid Build Coastguard Worker pthread_t self = pthread_self();
35*795d594fSAndroid Build Coastguard Worker
36*795d594fSAndroid Build Coastguard Worker int err = pthread_setname_np(self, "native-thread");
37*795d594fSAndroid Build Coastguard Worker CHECK_EQ(err, 0);
38*795d594fSAndroid Build Coastguard Worker
39*795d594fSAndroid Build Coastguard Worker args->jvm->AttachCurrentThread(&env, args->attach_args);
40*795d594fSAndroid Build Coastguard Worker
41*795d594fSAndroid Build Coastguard Worker jclass thread_class = env->FindClass("java/lang/Thread");
42*795d594fSAndroid Build Coastguard Worker jclass consumer_class = env->FindClass("java/util/function/BiConsumer");
43*795d594fSAndroid Build Coastguard Worker jmethodID current_thread_method =
44*795d594fSAndroid Build Coastguard Worker env->GetStaticMethodID(thread_class, "currentThread", "()Ljava/lang/Thread;");
45*795d594fSAndroid Build Coastguard Worker jmethodID accept_method =
46*795d594fSAndroid Build Coastguard Worker env->GetMethodID(consumer_class, "accept", "(Ljava/lang/Object;Ljava/lang/Object;)V");
47*795d594fSAndroid Build Coastguard Worker jobject current_thread = env->CallStaticObjectMethod(thread_class, current_thread_method);
48*795d594fSAndroid Build Coastguard Worker if (args->set_in_java) {
49*795d594fSAndroid Build Coastguard Worker jmethodID set_name_method = env->GetMethodID(thread_class, "setName", "(Ljava/lang/String;)V");
50*795d594fSAndroid Build Coastguard Worker jobject str_name = env->NewStringUTF("native-thread-set-java");
51*795d594fSAndroid Build Coastguard Worker env->CallVoidMethod(current_thread, set_name_method, str_name);
52*795d594fSAndroid Build Coastguard Worker }
53*795d594fSAndroid Build Coastguard Worker
54*795d594fSAndroid Build Coastguard Worker char name_chars[1024];
55*795d594fSAndroid Build Coastguard Worker err = pthread_getname_np(self, name_chars, sizeof(name_chars));
56*795d594fSAndroid Build Coastguard Worker CHECK_EQ(err, 0);
57*795d594fSAndroid Build Coastguard Worker jobject str_name = env->NewStringUTF(name_chars);
58*795d594fSAndroid Build Coastguard Worker
59*795d594fSAndroid Build Coastguard Worker env->CallVoidMethod(args->consumer, accept_method, str_name, current_thread);
60*795d594fSAndroid Build Coastguard Worker
61*795d594fSAndroid Build Coastguard Worker args->jvm->DetachCurrentThread();
62*795d594fSAndroid Build Coastguard Worker
63*795d594fSAndroid Build Coastguard Worker return nullptr;
64*795d594fSAndroid Build Coastguard Worker }
65*795d594fSAndroid Build Coastguard Worker
Java_Main_runThreadTestWithName(JNIEnv * env,jclass,jobject consumer)66*795d594fSAndroid Build Coastguard Worker extern "C" JNIEXPORT void Java_Main_runThreadTestWithName(JNIEnv* env,
67*795d594fSAndroid Build Coastguard Worker jclass /*clazz*/,
68*795d594fSAndroid Build Coastguard Worker jobject consumer) {
69*795d594fSAndroid Build Coastguard Worker jobject global_consumer = env->NewGlobalRef(consumer);
70*795d594fSAndroid Build Coastguard Worker JavaVMAttachArgs args;
71*795d594fSAndroid Build Coastguard Worker args.group = nullptr;
72*795d594fSAndroid Build Coastguard Worker args.name = "java-native-thread";
73*795d594fSAndroid Build Coastguard Worker args.version = JNI_VERSION_1_6;
74*795d594fSAndroid Build Coastguard Worker ThreadArgs ta {
75*795d594fSAndroid Build Coastguard Worker .jvm = nullptr, .consumer = global_consumer, .attach_args = &args, .set_in_java = false
76*795d594fSAndroid Build Coastguard Worker };
77*795d594fSAndroid Build Coastguard Worker env->GetJavaVM(&ta.jvm);
78*795d594fSAndroid Build Coastguard Worker pthread_t child;
79*795d594fSAndroid Build Coastguard Worker pthread_create(&child, nullptr, ThreadMain, &ta);
80*795d594fSAndroid Build Coastguard Worker void* ret;
81*795d594fSAndroid Build Coastguard Worker pthread_join(child, &ret);
82*795d594fSAndroid Build Coastguard Worker env->DeleteGlobalRef(ta.consumer);
83*795d594fSAndroid Build Coastguard Worker }
84*795d594fSAndroid Build Coastguard Worker
Java_Main_runThreadTest(JNIEnv * env,jclass,jobject consumer)85*795d594fSAndroid Build Coastguard Worker extern "C" JNIEXPORT void Java_Main_runThreadTest(JNIEnv* env, jclass /*clazz*/, jobject consumer) {
86*795d594fSAndroid Build Coastguard Worker jobject global_consumer = env->NewGlobalRef(consumer);
87*795d594fSAndroid Build Coastguard Worker ThreadArgs ta {
88*795d594fSAndroid Build Coastguard Worker .jvm = nullptr, .consumer = global_consumer, .attach_args = nullptr, .set_in_java = false
89*795d594fSAndroid Build Coastguard Worker };
90*795d594fSAndroid Build Coastguard Worker env->GetJavaVM(&ta.jvm);
91*795d594fSAndroid Build Coastguard Worker pthread_t child;
92*795d594fSAndroid Build Coastguard Worker pthread_create(&child, nullptr, ThreadMain, &ta);
93*795d594fSAndroid Build Coastguard Worker void* ret;
94*795d594fSAndroid Build Coastguard Worker pthread_join(child, &ret);
95*795d594fSAndroid Build Coastguard Worker env->DeleteGlobalRef(ta.consumer);
96*795d594fSAndroid Build Coastguard Worker }
97*795d594fSAndroid Build Coastguard Worker
Java_Main_runThreadTestSetJava(JNIEnv * env,jclass,jobject consumer)98*795d594fSAndroid Build Coastguard Worker extern "C" JNIEXPORT void Java_Main_runThreadTestSetJava(JNIEnv* env,
99*795d594fSAndroid Build Coastguard Worker jclass /*clazz*/,
100*795d594fSAndroid Build Coastguard Worker jobject consumer) {
101*795d594fSAndroid Build Coastguard Worker jobject global_consumer = env->NewGlobalRef(consumer);
102*795d594fSAndroid Build Coastguard Worker ThreadArgs ta {
103*795d594fSAndroid Build Coastguard Worker .jvm = nullptr, .consumer = global_consumer, .attach_args = nullptr, .set_in_java = true
104*795d594fSAndroid Build Coastguard Worker };
105*795d594fSAndroid Build Coastguard Worker env->GetJavaVM(&ta.jvm);
106*795d594fSAndroid Build Coastguard Worker pthread_t child;
107*795d594fSAndroid Build Coastguard Worker pthread_create(&child, nullptr, ThreadMain, &ta);
108*795d594fSAndroid Build Coastguard Worker void* ret;
109*795d594fSAndroid Build Coastguard Worker pthread_join(child, &ret);
110*795d594fSAndroid Build Coastguard Worker env->DeleteGlobalRef(ta.consumer);
111*795d594fSAndroid Build Coastguard Worker }
112