1 /*
2 * Copyright (C) 2018 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "utils/java/jni-helper.h"
18
19 #include "utils/base/status_macros.h"
20
21 namespace libtextclassifier3 {
22
FindClass(JNIEnv * env,const char * class_name)23 StatusOr<ScopedLocalRef<jclass>> JniHelper::FindClass(JNIEnv* env,
24 const char* class_name) {
25 TC3_ENSURE_LOCAL_CAPACITY_OR_RETURN;
26 ScopedLocalRef<jclass> result(env->FindClass(class_name), env);
27 TC3_NO_EXCEPTION_OR_RETURN;
28 TC3_NOT_NULL_OR_RETURN;
29 return result;
30 }
31
GetObjectClass(JNIEnv * env,jobject object)32 StatusOr<ScopedLocalRef<jclass>> JniHelper::GetObjectClass(JNIEnv* env,
33 jobject object) {
34 TC3_ENSURE_LOCAL_CAPACITY_OR_RETURN;
35 ScopedLocalRef<jclass> result(env->GetObjectClass(object), env);
36 TC3_NO_EXCEPTION_OR_RETURN;
37 TC3_NOT_NULL_OR_RETURN;
38 return result;
39 }
40
GetMethodID(JNIEnv * env,jclass clazz,const char * method_name,const char * signature)41 StatusOr<jmethodID> JniHelper::GetMethodID(JNIEnv* env, jclass clazz,
42 const char* method_name,
43 const char* signature) {
44 jmethodID result = env->GetMethodID(clazz, method_name, signature);
45 TC3_NO_EXCEPTION_OR_RETURN;
46 TC3_NOT_NULL_OR_RETURN;
47 return result;
48 }
49
GetStaticMethodID(JNIEnv * env,jclass clazz,const char * method_name,const char * signature)50 StatusOr<jmethodID> JniHelper::GetStaticMethodID(JNIEnv* env, jclass clazz,
51 const char* method_name,
52 const char* signature) {
53 jmethodID result = env->GetStaticMethodID(clazz, method_name, signature);
54 TC3_NO_EXCEPTION_OR_RETURN;
55 TC3_NOT_NULL_OR_RETURN;
56 return result;
57 }
58
GetFieldID(JNIEnv * env,jclass clazz,const char * field_name,const char * signature)59 StatusOr<jfieldID> JniHelper::GetFieldID(JNIEnv* env, jclass clazz,
60 const char* field_name,
61 const char* signature) {
62 jfieldID result = env->GetFieldID(clazz, field_name, signature);
63 TC3_NO_EXCEPTION_OR_RETURN;
64 TC3_NOT_NULL_OR_RETURN;
65 return result;
66 }
67
GetStaticFieldID(JNIEnv * env,jclass clazz,const char * field_name,const char * signature)68 StatusOr<jfieldID> JniHelper::GetStaticFieldID(JNIEnv* env, jclass clazz,
69 const char* field_name,
70 const char* signature) {
71 jfieldID result = env->GetStaticFieldID(clazz, field_name, signature);
72 TC3_NO_EXCEPTION_OR_RETURN;
73 TC3_NOT_NULL_OR_RETURN;
74 return result;
75 }
76
GetStaticObjectField(JNIEnv * env,jclass class_name,jfieldID field_id)77 StatusOr<ScopedLocalRef<jobject>> JniHelper::GetStaticObjectField(
78 JNIEnv* env, jclass class_name, jfieldID field_id) {
79 TC3_ENSURE_LOCAL_CAPACITY_OR_RETURN;
80 ScopedLocalRef<jobject> result(
81 env->GetStaticObjectField(class_name, field_id), env);
82 TC3_NO_EXCEPTION_OR_RETURN;
83 TC3_NOT_NULL_OR_RETURN;
84 return result;
85 }
86
GetStaticIntField(JNIEnv * env,jclass class_name,jfieldID field_id)87 StatusOr<jint> JniHelper::GetStaticIntField(JNIEnv* env, jclass class_name,
88 jfieldID field_id) {
89 TC3_ENSURE_LOCAL_CAPACITY_OR_RETURN;
90 jint result = env->GetStaticIntField(class_name, field_id);
91 TC3_NO_EXCEPTION_OR_RETURN;
92 return result;
93 }
94
NewByteArray(JNIEnv * env,jsize length)95 StatusOr<ScopedLocalRef<jbyteArray>> JniHelper::NewByteArray(JNIEnv* env,
96 jsize length) {
97 TC3_ENSURE_LOCAL_CAPACITY_OR_RETURN;
98 ScopedLocalRef<jbyteArray> result(env->NewByteArray(length), env);
99 TC3_NO_EXCEPTION_OR_RETURN;
100 TC3_NOT_NULL_OR_RETURN;
101 return result;
102 }
103
CallVoidMethod(JNIEnv * env,jobject object,jmethodID method_id,...)104 Status JniHelper::CallVoidMethod(JNIEnv* env, jobject object,
105 jmethodID method_id, ...) {
106 va_list args;
107 va_start(args, method_id);
108 env->CallVoidMethodV(object, method_id, args);
109 va_end(args);
110
111 TC3_NO_EXCEPTION_OR_RETURN;
112 return Status::OK;
113 }
114
CallBooleanMethod(JNIEnv * env,jobject object,jmethodID method_id,...)115 StatusOr<bool> JniHelper::CallBooleanMethod(JNIEnv* env, jobject object,
116 jmethodID method_id, ...) {
117 va_list args;
118 va_start(args, method_id);
119 bool result = env->CallBooleanMethodV(object, method_id, args);
120 va_end(args);
121
122 TC3_NO_EXCEPTION_OR_RETURN;
123 return result;
124 }
125
CallIntMethod(JNIEnv * env,jobject object,jmethodID method_id,...)126 StatusOr<int32> JniHelper::CallIntMethod(JNIEnv* env, jobject object,
127 jmethodID method_id, ...) {
128 va_list args;
129 va_start(args, method_id);
130 jint result = env->CallIntMethodV(object, method_id, args);
131 va_end(args);
132
133 TC3_NO_EXCEPTION_OR_RETURN;
134 return result;
135 }
136
CallLongMethod(JNIEnv * env,jobject object,jmethodID method_id,...)137 StatusOr<int64> JniHelper::CallLongMethod(JNIEnv* env, jobject object,
138 jmethodID method_id, ...) {
139 va_list args;
140 va_start(args, method_id);
141 jlong result = env->CallLongMethodV(object, method_id, args);
142 va_end(args);
143
144 TC3_NO_EXCEPTION_OR_RETURN;
145 return result;
146 }
147
CallFloatMethod(JNIEnv * env,jobject object,jmethodID method_id,...)148 StatusOr<float> JniHelper::CallFloatMethod(JNIEnv* env, jobject object,
149 jmethodID method_id, ...) {
150 va_list args;
151 va_start(args, method_id);
152 jfloat result = env->CallFloatMethodV(object, method_id, args);
153 va_end(args);
154
155 TC3_NO_EXCEPTION_OR_RETURN;
156 return result;
157 }
158
CallDoubleMethod(JNIEnv * env,jobject object,jmethodID method_id,...)159 StatusOr<double> JniHelper::CallDoubleMethod(JNIEnv* env, jobject object,
160 jmethodID method_id, ...) {
161 va_list args;
162 va_start(args, method_id);
163 jdouble result = env->CallDoubleMethodV(object, method_id, args);
164 va_end(args);
165
166 TC3_NO_EXCEPTION_OR_RETURN;
167 return result;
168 }
169
NewIntArray(JNIEnv * env,jsize length)170 StatusOr<ScopedLocalRef<jintArray>> JniHelper::NewIntArray(JNIEnv* env,
171 jsize length) {
172 TC3_ENSURE_LOCAL_CAPACITY_OR_RETURN;
173 ScopedLocalRef<jintArray> result(env->NewIntArray(length), env);
174 TC3_NO_EXCEPTION_OR_RETURN;
175 TC3_NOT_NULL_OR_RETURN;
176 return result;
177 }
178
NewFloatArray(JNIEnv * env,jsize length)179 StatusOr<ScopedLocalRef<jfloatArray>> JniHelper::NewFloatArray(JNIEnv* env,
180 jsize length) {
181 TC3_ENSURE_LOCAL_CAPACITY_OR_RETURN;
182 ScopedLocalRef<jfloatArray> result(env->NewFloatArray(length), env);
183 TC3_NO_EXCEPTION_OR_RETURN;
184 TC3_NOT_NULL_OR_RETURN;
185 return result;
186 }
187
SetObjectArrayElement(JNIEnv * env,jobjectArray array,jsize index,jobject val)188 Status JniHelper::SetObjectArrayElement(JNIEnv* env, jobjectArray array,
189 jsize index, jobject val) {
190 TC3_ENSURE_LOCAL_CAPACITY_OR_RETURN;
191 env->SetObjectArrayElement(array, index, val);
192 TC3_NO_EXCEPTION_OR_RETURN;
193 return Status::OK;
194 }
195
GetArrayLength(JNIEnv * env,jarray array)196 StatusOr<jsize> JniHelper::GetArrayLength(JNIEnv* env, jarray array) {
197 TC3_ENSURE_LOCAL_CAPACITY_OR_RETURN;
198 jsize result = env->GetArrayLength(array);
199 TC3_NO_EXCEPTION_OR_RETURN;
200 return result;
201 }
202
GetByteArrayRegion(JNIEnv * env,jbyteArray array,jsize start,jsize len,jbyte * buf)203 Status JniHelper::GetByteArrayRegion(JNIEnv* env, jbyteArray array, jsize start,
204 jsize len, jbyte* buf) {
205 TC3_ENSURE_LOCAL_CAPACITY_OR_RETURN;
206 env->GetByteArrayRegion(array, start, len, buf);
207 TC3_NO_EXCEPTION_OR_RETURN;
208 return Status::OK;
209 }
210
SetByteArrayRegion(JNIEnv * env,jbyteArray array,jsize start,jsize len,const jbyte * buf)211 Status JniHelper::SetByteArrayRegion(JNIEnv* env, jbyteArray array, jsize start,
212 jsize len, const jbyte* buf) {
213 TC3_ENSURE_LOCAL_CAPACITY_OR_RETURN;
214 env->SetByteArrayRegion(array, start, len, buf);
215 TC3_NO_EXCEPTION_OR_RETURN;
216 return Status::OK;
217 }
218
SetIntArrayRegion(JNIEnv * env,jintArray array,jsize start,jsize len,const jint * buf)219 Status JniHelper::SetIntArrayRegion(JNIEnv* env, jintArray array, jsize start,
220 jsize len, const jint* buf) {
221 TC3_ENSURE_LOCAL_CAPACITY_OR_RETURN;
222 env->SetIntArrayRegion(array, start, len, buf);
223 TC3_NO_EXCEPTION_OR_RETURN;
224 return Status::OK;
225 }
226
SetFloatArrayRegion(JNIEnv * env,jfloatArray array,jsize start,jsize len,const jfloat * buf)227 Status JniHelper::SetFloatArrayRegion(JNIEnv* env, jfloatArray array,
228 jsize start, jsize len,
229 const jfloat* buf) {
230 TC3_ENSURE_LOCAL_CAPACITY_OR_RETURN;
231 env->SetFloatArrayRegion(array, start, len, buf);
232 TC3_NO_EXCEPTION_OR_RETURN;
233 return Status::OK;
234 }
235
NewObjectArray(JNIEnv * env,jsize length,jclass element_class,jobject initial_element)236 StatusOr<ScopedLocalRef<jobjectArray>> JniHelper::NewObjectArray(
237 JNIEnv* env, jsize length, jclass element_class, jobject initial_element) {
238 TC3_ENSURE_LOCAL_CAPACITY_OR_RETURN;
239 ScopedLocalRef<jobjectArray> result(
240 env->NewObjectArray(length, element_class, initial_element), env);
241 TC3_NO_EXCEPTION_OR_RETURN;
242 TC3_NOT_NULL_OR_RETURN;
243 return result;
244 }
245
NewStringUTF(JNIEnv * env,const char * bytes)246 StatusOr<ScopedLocalRef<jstring>> JniHelper::NewStringUTF(JNIEnv* env,
247 const char* bytes) {
248 TC3_ENSURE_LOCAL_CAPACITY_OR_RETURN;
249 ScopedLocalRef<jstring> result(env->NewStringUTF(bytes), env);
250 TC3_NO_EXCEPTION_OR_RETURN;
251 TC3_NOT_NULL_OR_RETURN;
252 return result;
253 }
254
JByteArrayToString(JNIEnv * env,jbyteArray array)255 StatusOr<std::string> JByteArrayToString(JNIEnv* env, jbyteArray array) {
256 std::string result;
257 TC3_ASSIGN_OR_RETURN(const int array_length,
258 JniHelper::GetArrayLength(env, array));
259 result.resize(array_length);
260 TC3_RETURN_IF_ERROR(JniHelper::GetByteArrayRegion(
261 env, array, 0, array_length,
262 reinterpret_cast<jbyte*>(const_cast<char*>(result.data()))));
263 return result;
264 }
265
JStringToUtf8String(JNIEnv * env,jstring jstr)266 StatusOr<std::string> JStringToUtf8String(JNIEnv* env, jstring jstr) {
267 if (jstr == nullptr) {
268 return "";
269 }
270
271 TC3_ASSIGN_OR_RETURN(ScopedLocalRef<jclass> string_class,
272 JniHelper::FindClass(env, "java/lang/String"));
273 TC3_ASSIGN_OR_RETURN(
274 jmethodID get_bytes_id,
275 JniHelper::GetMethodID(env, string_class.get(), "getBytes",
276 "(Ljava/lang/String;)[B"));
277
278 TC3_ASSIGN_OR_RETURN(ScopedLocalRef<jstring> encoding,
279 JniHelper::NewStringUTF(env, "UTF-8"));
280
281 TC3_ASSIGN_OR_RETURN(ScopedLocalRef<jbyteArray> array,
282 JniHelper::CallObjectMethod<jbyteArray>(
283 env, jstr, get_bytes_id, encoding.get()));
284
285 return JByteArrayToString(env, array.get());
286 }
287
288 } // namespace libtextclassifier3
289