1*993b0882SAndroid Build Coastguard Worker /*
2*993b0882SAndroid Build Coastguard Worker * Copyright (C) 2018 The Android Open Source Project
3*993b0882SAndroid Build Coastguard Worker *
4*993b0882SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*993b0882SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*993b0882SAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*993b0882SAndroid Build Coastguard Worker *
8*993b0882SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*993b0882SAndroid Build Coastguard Worker *
10*993b0882SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*993b0882SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*993b0882SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*993b0882SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*993b0882SAndroid Build Coastguard Worker * limitations under the License.
15*993b0882SAndroid Build Coastguard Worker */
16*993b0882SAndroid Build Coastguard Worker
17*993b0882SAndroid Build Coastguard Worker // Utility class that provides similar calls like JNIEnv, but performs
18*993b0882SAndroid Build Coastguard Worker // additional checks on them, so that it's harder to use them incorrectly.
19*993b0882SAndroid Build Coastguard Worker
20*993b0882SAndroid Build Coastguard Worker #ifndef LIBTEXTCLASSIFIER_UTILS_JAVA_JNI_HELPER_H_
21*993b0882SAndroid Build Coastguard Worker #define LIBTEXTCLASSIFIER_UTILS_JAVA_JNI_HELPER_H_
22*993b0882SAndroid Build Coastguard Worker
23*993b0882SAndroid Build Coastguard Worker #include <jni.h>
24*993b0882SAndroid Build Coastguard Worker
25*993b0882SAndroid Build Coastguard Worker #include <string>
26*993b0882SAndroid Build Coastguard Worker
27*993b0882SAndroid Build Coastguard Worker #include "utils/base/status.h"
28*993b0882SAndroid Build Coastguard Worker #include "utils/base/statusor.h"
29*993b0882SAndroid Build Coastguard Worker #include "utils/java/jni-base.h"
30*993b0882SAndroid Build Coastguard Worker
31*993b0882SAndroid Build Coastguard Worker #define TC3_ENSURE_LOCAL_CAPACITY_OR_RETURN \
32*993b0882SAndroid Build Coastguard Worker if (!EnsureLocalCapacity(env, 1)) { \
33*993b0882SAndroid Build Coastguard Worker TC3_LOG(ERROR) << "EnsureLocalCapacity(1) failed."; \
34*993b0882SAndroid Build Coastguard Worker return {Status::UNKNOWN}; \
35*993b0882SAndroid Build Coastguard Worker }
36*993b0882SAndroid Build Coastguard Worker
37*993b0882SAndroid Build Coastguard Worker #define TC3_NO_EXCEPTION_OR_RETURN \
38*993b0882SAndroid Build Coastguard Worker if (JniExceptionCheckAndClear(env)) { \
39*993b0882SAndroid Build Coastguard Worker return {Status::UNKNOWN}; \
40*993b0882SAndroid Build Coastguard Worker }
41*993b0882SAndroid Build Coastguard Worker
42*993b0882SAndroid Build Coastguard Worker #define TC3_NOT_NULL_OR_RETURN \
43*993b0882SAndroid Build Coastguard Worker if (result == nullptr) { \
44*993b0882SAndroid Build Coastguard Worker return {Status::UNKNOWN}; \
45*993b0882SAndroid Build Coastguard Worker }
46*993b0882SAndroid Build Coastguard Worker
47*993b0882SAndroid Build Coastguard Worker #define TC3_DEFINE_VARIADIC_SCOPED_LOCAL_REF_ENV_METHOD( \
48*993b0882SAndroid Build Coastguard Worker METHOD_NAME, RETURN_TYPE, INPUT_TYPE, POST_CHECK) \
49*993b0882SAndroid Build Coastguard Worker template <typename T = RETURN_TYPE> \
50*993b0882SAndroid Build Coastguard Worker static StatusOr<ScopedLocalRef<T>> METHOD_NAME( \
51*993b0882SAndroid Build Coastguard Worker JNIEnv* env, INPUT_TYPE object, jmethodID method_id, ...) { \
52*993b0882SAndroid Build Coastguard Worker TC3_ENSURE_LOCAL_CAPACITY_OR_RETURN; \
53*993b0882SAndroid Build Coastguard Worker \
54*993b0882SAndroid Build Coastguard Worker va_list args; \
55*993b0882SAndroid Build Coastguard Worker va_start(args, method_id); \
56*993b0882SAndroid Build Coastguard Worker ScopedLocalRef<T> result( \
57*993b0882SAndroid Build Coastguard Worker reinterpret_cast<T>(env->METHOD_NAME##V(object, method_id, args)), \
58*993b0882SAndroid Build Coastguard Worker env); \
59*993b0882SAndroid Build Coastguard Worker POST_CHECK \
60*993b0882SAndroid Build Coastguard Worker va_end(args); \
61*993b0882SAndroid Build Coastguard Worker \
62*993b0882SAndroid Build Coastguard Worker TC3_NO_EXCEPTION_OR_RETURN; \
63*993b0882SAndroid Build Coastguard Worker return result; \
64*993b0882SAndroid Build Coastguard Worker }
65*993b0882SAndroid Build Coastguard Worker
66*993b0882SAndroid Build Coastguard Worker #define TC3_JNI_NO_CHECK \
67*993b0882SAndroid Build Coastguard Worker {}
68*993b0882SAndroid Build Coastguard Worker
69*993b0882SAndroid Build Coastguard Worker namespace libtextclassifier3 {
70*993b0882SAndroid Build Coastguard Worker
71*993b0882SAndroid Build Coastguard Worker class JniHelper {
72*993b0882SAndroid Build Coastguard Worker public:
73*993b0882SAndroid Build Coastguard Worker // Misc methods.
74*993b0882SAndroid Build Coastguard Worker static StatusOr<ScopedLocalRef<jclass>> FindClass(JNIEnv* env,
75*993b0882SAndroid Build Coastguard Worker const char* class_name);
76*993b0882SAndroid Build Coastguard Worker
77*993b0882SAndroid Build Coastguard Worker static StatusOr<ScopedLocalRef<jclass>> GetObjectClass(JNIEnv* env,
78*993b0882SAndroid Build Coastguard Worker jobject object);
79*993b0882SAndroid Build Coastguard Worker
80*993b0882SAndroid Build Coastguard Worker template <typename T = jobject>
81*993b0882SAndroid Build Coastguard Worker static StatusOr<ScopedLocalRef<T>> GetObjectArrayElement(JNIEnv* env,
82*993b0882SAndroid Build Coastguard Worker jobjectArray array,
83*993b0882SAndroid Build Coastguard Worker jsize index);
84*993b0882SAndroid Build Coastguard Worker static StatusOr<jmethodID> GetMethodID(JNIEnv* env, jclass clazz,
85*993b0882SAndroid Build Coastguard Worker const char* method_name,
86*993b0882SAndroid Build Coastguard Worker const char* signature);
87*993b0882SAndroid Build Coastguard Worker static StatusOr<jmethodID> GetStaticMethodID(JNIEnv* env, jclass clazz,
88*993b0882SAndroid Build Coastguard Worker const char* method_name,
89*993b0882SAndroid Build Coastguard Worker const char* signature);
90*993b0882SAndroid Build Coastguard Worker
91*993b0882SAndroid Build Coastguard Worker static StatusOr<jfieldID> GetFieldID(JNIEnv* env, jclass clazz,
92*993b0882SAndroid Build Coastguard Worker const char* field_name,
93*993b0882SAndroid Build Coastguard Worker const char* signature);
94*993b0882SAndroid Build Coastguard Worker static StatusOr<jfieldID> GetStaticFieldID(JNIEnv* env, jclass clazz,
95*993b0882SAndroid Build Coastguard Worker const char* field_name,
96*993b0882SAndroid Build Coastguard Worker const char* signature);
97*993b0882SAndroid Build Coastguard Worker
98*993b0882SAndroid Build Coastguard Worker static StatusOr<ScopedLocalRef<jobject>> GetStaticObjectField(
99*993b0882SAndroid Build Coastguard Worker JNIEnv* env, jclass class_name, jfieldID field_id);
100*993b0882SAndroid Build Coastguard Worker static StatusOr<jint> GetStaticIntField(JNIEnv* env, jclass class_name,
101*993b0882SAndroid Build Coastguard Worker jfieldID field_id);
102*993b0882SAndroid Build Coastguard Worker
103*993b0882SAndroid Build Coastguard Worker // New* methods.
104*993b0882SAndroid Build Coastguard Worker TC3_DEFINE_VARIADIC_SCOPED_LOCAL_REF_ENV_METHOD(NewObject, jobject, jclass,
105*993b0882SAndroid Build Coastguard Worker TC3_NOT_NULL_OR_RETURN);
106*993b0882SAndroid Build Coastguard Worker static StatusOr<ScopedLocalRef<jobjectArray>> NewObjectArray(
107*993b0882SAndroid Build Coastguard Worker JNIEnv* env, jsize length, jclass element_class,
108*993b0882SAndroid Build Coastguard Worker jobject initial_element = nullptr);
109*993b0882SAndroid Build Coastguard Worker static StatusOr<ScopedLocalRef<jbyteArray>> NewByteArray(JNIEnv* env,
110*993b0882SAndroid Build Coastguard Worker jsize length);
111*993b0882SAndroid Build Coastguard Worker static StatusOr<ScopedLocalRef<jintArray>> NewIntArray(JNIEnv* env,
112*993b0882SAndroid Build Coastguard Worker jsize length);
113*993b0882SAndroid Build Coastguard Worker static StatusOr<ScopedLocalRef<jstring>> NewStringUTF(JNIEnv* env,
114*993b0882SAndroid Build Coastguard Worker const char* bytes);
115*993b0882SAndroid Build Coastguard Worker static StatusOr<ScopedLocalRef<jfloatArray>> NewFloatArray(JNIEnv* env,
116*993b0882SAndroid Build Coastguard Worker jsize length);
117*993b0882SAndroid Build Coastguard Worker
118*993b0882SAndroid Build Coastguard Worker static StatusOr<jsize> GetArrayLength(JNIEnv* env, jarray array);
119*993b0882SAndroid Build Coastguard Worker
120*993b0882SAndroid Build Coastguard Worker static Status SetObjectArrayElement(JNIEnv* env, jobjectArray array,
121*993b0882SAndroid Build Coastguard Worker jsize index, jobject val);
122*993b0882SAndroid Build Coastguard Worker
123*993b0882SAndroid Build Coastguard Worker static Status GetByteArrayRegion(JNIEnv* env, jbyteArray array, jsize start,
124*993b0882SAndroid Build Coastguard Worker jsize len, jbyte* buf);
125*993b0882SAndroid Build Coastguard Worker
126*993b0882SAndroid Build Coastguard Worker static Status SetByteArrayRegion(JNIEnv* env, jbyteArray array, jsize start,
127*993b0882SAndroid Build Coastguard Worker jsize len, const jbyte* buf);
128*993b0882SAndroid Build Coastguard Worker
129*993b0882SAndroid Build Coastguard Worker static Status SetIntArrayRegion(JNIEnv* env, jintArray array, jsize start,
130*993b0882SAndroid Build Coastguard Worker jsize len, const jint* buf);
131*993b0882SAndroid Build Coastguard Worker
132*993b0882SAndroid Build Coastguard Worker static Status SetFloatArrayRegion(JNIEnv* env, jfloatArray array, jsize start,
133*993b0882SAndroid Build Coastguard Worker jsize len, const jfloat* buf);
134*993b0882SAndroid Build Coastguard Worker
135*993b0882SAndroid Build Coastguard Worker // Call* methods.
136*993b0882SAndroid Build Coastguard Worker TC3_DEFINE_VARIADIC_SCOPED_LOCAL_REF_ENV_METHOD(CallObjectMethod, jobject,
137*993b0882SAndroid Build Coastguard Worker jobject, TC3_JNI_NO_CHECK);
138*993b0882SAndroid Build Coastguard Worker TC3_DEFINE_VARIADIC_SCOPED_LOCAL_REF_ENV_METHOD(CallStaticObjectMethod,
139*993b0882SAndroid Build Coastguard Worker jobject, jclass,
140*993b0882SAndroid Build Coastguard Worker TC3_JNI_NO_CHECK);
141*993b0882SAndroid Build Coastguard Worker static Status CallVoidMethod(JNIEnv* env, jobject object, jmethodID method_id,
142*993b0882SAndroid Build Coastguard Worker ...);
143*993b0882SAndroid Build Coastguard Worker static StatusOr<bool> CallBooleanMethod(JNIEnv* env, jobject object,
144*993b0882SAndroid Build Coastguard Worker jmethodID method_id, ...);
145*993b0882SAndroid Build Coastguard Worker static StatusOr<int32> CallIntMethod(JNIEnv* env, jobject object,
146*993b0882SAndroid Build Coastguard Worker jmethodID method_id, ...);
147*993b0882SAndroid Build Coastguard Worker static StatusOr<int64> CallLongMethod(JNIEnv* env, jobject object,
148*993b0882SAndroid Build Coastguard Worker jmethodID method_id, ...);
149*993b0882SAndroid Build Coastguard Worker static StatusOr<float> CallFloatMethod(JNIEnv* env, jobject object,
150*993b0882SAndroid Build Coastguard Worker jmethodID method_id, ...);
151*993b0882SAndroid Build Coastguard Worker static StatusOr<double> CallDoubleMethod(JNIEnv* env, jobject object,
152*993b0882SAndroid Build Coastguard Worker jmethodID method_id, ...);
153*993b0882SAndroid Build Coastguard Worker
154*993b0882SAndroid Build Coastguard Worker template <class T>
155*993b0882SAndroid Build Coastguard Worker static StatusOr<T> CallStaticIntMethod(JNIEnv* env,
156*993b0882SAndroid Build Coastguard Worker bool print_exception_on_error,
157*993b0882SAndroid Build Coastguard Worker jclass clazz, jmethodID method_id,
158*993b0882SAndroid Build Coastguard Worker ...);
159*993b0882SAndroid Build Coastguard Worker };
160*993b0882SAndroid Build Coastguard Worker
161*993b0882SAndroid Build Coastguard Worker template <typename T>
GetObjectArrayElement(JNIEnv * env,jobjectArray array,jsize index)162*993b0882SAndroid Build Coastguard Worker StatusOr<ScopedLocalRef<T>> JniHelper::GetObjectArrayElement(JNIEnv* env,
163*993b0882SAndroid Build Coastguard Worker jobjectArray array,
164*993b0882SAndroid Build Coastguard Worker jsize index) {
165*993b0882SAndroid Build Coastguard Worker TC3_ENSURE_LOCAL_CAPACITY_OR_RETURN;
166*993b0882SAndroid Build Coastguard Worker ScopedLocalRef<T> result(
167*993b0882SAndroid Build Coastguard Worker reinterpret_cast<T>(env->GetObjectArrayElement(array, index)), env);
168*993b0882SAndroid Build Coastguard Worker
169*993b0882SAndroid Build Coastguard Worker TC3_NO_EXCEPTION_OR_RETURN;
170*993b0882SAndroid Build Coastguard Worker return result;
171*993b0882SAndroid Build Coastguard Worker }
172*993b0882SAndroid Build Coastguard Worker
173*993b0882SAndroid Build Coastguard Worker template <class T>
CallStaticIntMethod(JNIEnv * env,bool print_exception_on_error,jclass clazz,jmethodID method_id,...)174*993b0882SAndroid Build Coastguard Worker StatusOr<T> JniHelper::CallStaticIntMethod(JNIEnv* env,
175*993b0882SAndroid Build Coastguard Worker bool print_exception_on_error,
176*993b0882SAndroid Build Coastguard Worker jclass clazz, jmethodID method_id,
177*993b0882SAndroid Build Coastguard Worker ...) {
178*993b0882SAndroid Build Coastguard Worker va_list args;
179*993b0882SAndroid Build Coastguard Worker va_start(args, method_id);
180*993b0882SAndroid Build Coastguard Worker jint result = env->CallStaticIntMethodV(clazz, method_id, args);
181*993b0882SAndroid Build Coastguard Worker va_end(args);
182*993b0882SAndroid Build Coastguard Worker
183*993b0882SAndroid Build Coastguard Worker if (JniExceptionCheckAndClear(env, print_exception_on_error)) {
184*993b0882SAndroid Build Coastguard Worker return {Status::UNKNOWN};
185*993b0882SAndroid Build Coastguard Worker }
186*993b0882SAndroid Build Coastguard Worker
187*993b0882SAndroid Build Coastguard Worker return result;
188*993b0882SAndroid Build Coastguard Worker }
189*993b0882SAndroid Build Coastguard Worker
190*993b0882SAndroid Build Coastguard Worker // Converts Java byte[] object to std::string.
191*993b0882SAndroid Build Coastguard Worker StatusOr<std::string> JByteArrayToString(JNIEnv* env, jbyteArray array);
192*993b0882SAndroid Build Coastguard Worker
193*993b0882SAndroid Build Coastguard Worker // Converts Java String object to UTF8-encoded std::string.
194*993b0882SAndroid Build Coastguard Worker StatusOr<std::string> JStringToUtf8String(JNIEnv* env, jstring jstr);
195*993b0882SAndroid Build Coastguard Worker
196*993b0882SAndroid Build Coastguard Worker } // namespace libtextclassifier3
197*993b0882SAndroid Build Coastguard Worker
198*993b0882SAndroid Build Coastguard Worker #endif // LIBTEXTCLASSIFIER_UTILS_JAVA_JNI_HELPER_H_
199