#include <cstdlib>
#include <cerrno>
-#include <map>
-#include <utility>
-
-#include <android/looper.h>
-
#include <beyond/platform/beyond_platform.h>
#include <inference/beyond-inference_jni.h>
#define GET_BEYOND_INFERENCE(obj) (static_cast<beyond::Inference *>((obj)->GetBeyonDInstance()))
+#define JAVA_UTIL_ARRAYLIST_CLASS "java/util/ArrayList"
+#define JAVA_LANG_INTEGER_CLASS "java/lang/Integer"
+#define JAVA_CLASS_CONSTRUCTOR "<init>"
+
TensorJNI::TensorJNI(void)
{
}
int TensorJNI::getTensorsInfo(JNIEnv *env, const beyond_tensor_info *tensors_info, int num_tensors, jobject datatype_values, jobject dimensions_list)
{
- jclass list_class = env->FindClass("java/util/ArrayList");
- if (list_class == NULL) {
- ErrPrint("Fail to find java/util/List class.");
+ jclass list_class = env->FindClass(JAVA_UTIL_ARRAYLIST_CLASS);
+ if (list_class == nullptr) {
+ ErrPrint("Fail to find %s class.", JAVA_UTIL_ARRAYLIST_CLASS);
return -EFAULT;
}
- jmethodID list_constructor_id = env->GetMethodID(list_class, "<init>", "()V");
- if (list_constructor_id == NULL) {
+ jmethodID list_constructor_id = env->GetMethodID(list_class, JAVA_CLASS_CONSTRUCTOR, "()V");
+ if (list_constructor_id == nullptr) {
ErrPrint("Fail to find an <init> method.");
return -EFAULT;
}
jmethodID add_method_id = env->GetMethodID(list_class, "add", "(Ljava/lang/Object;)Z");
- if (add_method_id == NULL) {
+ if (add_method_id == nullptr) {
ErrPrint("Fail to find an add method.");
return -EFAULT;
}
- jclass integer_class = env->FindClass("java/lang/Integer");
- if (integer_class == NULL) {
- ErrPrint("Fail to find java/util/Integer class.");
+ jclass integer_class = env->FindClass(JAVA_LANG_INTEGER_CLASS);
+ if (integer_class == nullptr) {
+ ErrPrint("Fail to find %s class.", JAVA_LANG_INTEGER_CLASS);
return -EFAULT;
}
- jmethodID integer_constructor_id = env->GetMethodID(integer_class, "<init>", "(I)V");
- if (integer_constructor_id == NULL) {
+ jmethodID integer_constructor_id = env->GetMethodID(integer_class, JAVA_CLASS_CONSTRUCTOR, "(I)V");
+ if (integer_constructor_id == nullptr) {
ErrPrint("Fail to find an <init> method.");
return -EFAULT;
}
for (int i = 0; i < num_tensors; i++) {
int type_value = tensors_info[i].type;
jobject datatype_value = env->NewObject(integer_class, integer_constructor_id, type_value);
- if (datatype_value == NULL) {
+ if (datatype_value == nullptr) {
ErrPrint("Fail to create an Integer instance.");
return -EFAULT;
}
}
jobject list = env->NewObject(list_class, list_constructor_id);
- if (list == NULL) {
+ if (list == nullptr) {
ErrPrint("Fail to create an ArrayList instance.");
return -EFAULT;
}
int dimension_value = tensors_info[i].dims->data[j];
jobject dimension_object = env->NewObject(integer_class, integer_constructor_id,
dimension_value);
- if (dimension_object == NULL) {
+ if (dimension_object == nullptr) {
ErrPrint("Fail to create an Integer instance.");
return -EFAULT;
}
return 0;
}
-jlong TensorJNI::Java_com_samsung_beyond_TensorHandler_allocateTensors(JNIEnv *env, jobject thiz, jlong inference_handle, jobject datatype_values, jintArray data_sizes, jobject dimensions_list, jint num_tensors, jobjectArray buffer_array)
+jlong TensorJNI::Java_com_samsung_beyond_TensorHandler_allocateTensors(JNIEnv *env, jobject thiz, jlong inference_handle, jobjectArray tensor_info_array, jint num_tensors, jobjectArray buffer_array)
{
beyond_tensor_info *tensors_info = nullptr;
int ret = transformTensorsInfo(env, tensors_info, num_tensors,
- datatype_values, data_sizes,
- dimensions_list);
+ tensor_info_array);
if (ret < 0) {
ErrPrint("Fail to transform the information of tensors, ret = %d\n", ret);
return 0;
}
for (int i = 0; i < num_tensors; i++) {
jobject bytebuffer = env->NewDirectByteBuffer(tensors[i].data, tensors_info[i].size);
- if (bytebuffer == NULL) {
+ if (bytebuffer == nullptr) {
ErrPrint("Fail to NewDirectByteBuffer().");
GET_BEYOND_INFERENCE(inference_handle_)->FreeTensor(tensors, num_tensors);
tensors = nullptr;
+ for (int j = 0; j < i; j++) {
+ env->DeleteLocalRef(env->GetObjectArrayElement(buffer_array, i));
+ }
return 0;
}
env->SetObjectArrayElement(buffer_array, i, bytebuffer);
+ env->DeleteLocalRef(bytebuffer);
}
return reinterpret_cast<jlong>(tensors);
}
-int TensorJNI::transformTensorsInfo(JNIEnv *env, beyond_tensor_info *&tensors_info, int num_tensors, jobject datatype_values, jintArray data_sizes, jobject dimensions_list)
+int TensorJNI::transformTensorsInfo(JNIEnv *env, beyond_tensor_info *&tensors_info, int num_tensors, jobjectArray tensor_info_array)
{
- jclass list_class = env->FindClass("java/util/ArrayList");
- if (list_class == NULL) {
- ErrPrint("Fail to find java/util/List class.");
- return -EFAULT;
- }
- jmethodID get_method_id = env->GetMethodID(list_class, "get", "(I)Ljava/lang/Object;");
- if (get_method_id == NULL) {
- ErrPrint("Fail to find a get method.");
- return -EFAULT;
- }
- jmethodID size_method_id = env->GetMethodID(list_class, "size", "()I");
- if (size_method_id == NULL) {
- ErrPrint("Fail to find a size method.");
- return -EFAULT;
- }
-
- jclass integer_class = env->FindClass("java/lang/Integer");
- if (integer_class == NULL) {
- ErrPrint("Fail to find java/lang/Integer class.");
- return -EFAULT;
- }
- jmethodID intValue_method_id = env->GetMethodID(integer_class, "intValue", "()I");
- if (intValue_method_id == NULL) {
- ErrPrint("Fail to find an intValue method.");
- return -EFAULT;
- }
-
beyond_tensor_info *_info = static_cast<beyond_tensor_info *>(malloc(sizeof(beyond_tensor_info) * num_tensors));
if (_info == nullptr) {
ErrPrint("Fail to allocate beyond_tensor_infos.");
return -EFAULT;
}
- jint *datasize_values = env->GetIntArrayElements(data_sizes, 0);
- for (int i = 0; i < num_tensors; i++) {
- jobject integer_object = env->CallObjectMethod(datatype_values, get_method_id, i);
- if (integer_object == nullptr) {
- ErrPrint("Fail to get an integerObject.");
- freeTensorDimensions(_info, i);
- return -EFAULT;
- }
- jint type = env->CallIntMethod(integer_object, intValue_method_id);
- _info[i].type = static_cast<beyond_tensor_type>(type);
-
- _info[i].size = datasize_values[i];
- jobject dimension_list_object = env->CallObjectMethod(dimensions_list, get_method_id, i);
- if (dimension_list_object == nullptr) {
- ErrPrint("Fail to get a dimension_list_object.");
- freeTensorDimensions(_info, i);
- return -EFAULT;
- }
- jobject dimension_object = env->CallObjectMethod(dimension_list_object, get_method_id, i);
- if (dimension_object == nullptr) {
- ErrPrint("Fail to get a dimension_object.");
- freeTensorDimensions(_info, i);
- return -EFAULT;
- }
- jint dimension = env->CallIntMethod(dimension_object, intValue_method_id);
- jint rank = env->CallIntMethod(dimension_list_object, size_method_id);
- _info[i].dims = static_cast<beyond_tensor_info::dimensions *>(malloc(sizeof(beyond_tensor_info::dimensions) + sizeof(int) * rank));
- if (_info[i].dims == nullptr) {
- ErrPrint("Fail to allocate dimensions.");
- freeTensorDimensions(_info, i);
- return -EFAULT;
+ try {
+ jclass tensor_info_list_class = env->FindClass("com/samsung/android/beyond/inference/tensor/TensorInfo");
+ if (tensor_info_list_class == nullptr) {
+ ErrPrint("jclass \"com/samsung/android/beyond/inference/tensor/TensorInfo\" is null.");
+ JNIHelper::checkEnvException(env);
}
- _info[i].dims->size = rank;
- for (int j = 0; j < rank; j++) {
- _info[i].dims->data[j] = dimension;
+ jmethodID get_data_type_value_method_id = getJmethodId(env, tensor_info_list_class,
+ "getDataTypeValue", "()I");
+ jmethodID get_rank_method_id = getJmethodId(env, tensor_info_list_class, "getRank", "()I");
+ jmethodID get_dimensions_method_id = getJmethodId(env, tensor_info_list_class,
+ "getDimensions",
+ "()[I");
+ jmethodID get_data_byte_size_method_id = getJmethodId(env, tensor_info_list_class,
+ "getDataByteSize", "()I");
+
+ for (int i = 0; i < num_tensors; i++) {
+ jobject tensor_info_object = env->GetObjectArrayElement(tensor_info_array, i);
+ checkNull(env, tensor_info_object, "Fail to get a tensor_info_object.", _info, i);
+
+ jint type = env->CallIntMethod(tensor_info_object, get_data_type_value_method_id);
+ JNIHelper::checkEnvException(env);
+ _info[i].type = static_cast<beyond_tensor_type>(type);
+
+ jint data_byte_size = env->CallIntMethod(tensor_info_object, get_data_byte_size_method_id);
+ JNIHelper::checkEnvException(env);
+ _info[i].size = data_byte_size;
+
+ jintArray dimensions = (jintArray)(env->CallObjectMethod(tensor_info_object, get_dimensions_method_id));
+ JNIHelper::checkEnvException(env);
+ jint *dimension = env->GetIntArrayElements(dimensions, NULL);
+ JNIHelper::checkEnvException(env);
+ jint rank = env->CallIntMethod(tensor_info_object, get_rank_method_id);
+ JNIHelper::checkEnvException(env);
+ _info[i].dims = static_cast<beyond_tensor_info::dimensions *>(malloc(sizeof(beyond_tensor_info::dimensions) + sizeof(int) * rank));
+ if (_info[i].dims == nullptr) {
+ ErrPrint("Fail to allocate dimensions.");
+ env->ReleaseIntArrayElements(dimensions, dimension, 0);
+ env->DeleteLocalRef(tensor_info_object);
+ freeTensorDimensions(_info, i);
+ return -EFAULT;
+ }
+ _info[i].dims->size = rank;
+ for (int j = 0; j < rank; j++) {
+ _info[i].dims->data[j] = (int)(dimension[j]);
+ }
+
+ env->ReleaseIntArrayElements(dimensions, dimension, 0);
+ env->DeleteLocalRef(tensor_info_object);
}
+ env->DeleteLocalRef(tensor_info_list_class);
+ } catch (std::exception &e) {
+ return -EFAULT;
}
+
tensors_info = _info;
return 0;
}
+jmethodID TensorJNI::getJmethodId(JNIEnv *env, jclass clazz, const char *name, const char *signature)
+{
+ jmethodID ret = env->GetMethodID(clazz, name, signature);
+ if (ret == nullptr) {
+ ErrPrint("jmethod (%s, %s) is null.", name, signature);
+ JNIHelper::checkEnvException(env);
+ }
+
+ return ret;
+}
+
+void TensorJNI::checkNull(JNIEnv *env, jobject object, const char *error_message, beyond_tensor_info *_info, int index)
+{
+ if (object == nullptr) {
+ ErrPrint("%s", error_message);
+ freeTensorDimensions(_info, index);
+ JNIHelper::checkEnvException(env);
+ }
+}
+
void TensorJNI::freeTensorDimensions(beyond_tensor_info *&info, int &size)
{
if (info == nullptr || size == 0) {
for (int i = 0; i < num_tensors; i++) {
jobject byte_buffer = env->NewDirectByteBuffer(tensors[i].data, tensors[i].size);
- if (byte_buffer == NULL) {
+ if (byte_buffer == nullptr) {
ErrPrint("Fail to NewDirectByteBuffer().");
return 0;
}
static JNINativeMethod tensor_jni_methods[] = {
{ "getInputTensorsInfo", "(JLjava/util/List;Ljava/util/List;)Z", reinterpret_cast<void *>(Java_com_samsung_beyond_TensorHandler_getInputTensorsInfo) },
{ "getOutputTensorsInfo", "(JLjava/util/List;Ljava/util/List;)Z", reinterpret_cast<void *>(Java_com_samsung_beyond_TensorHandler_getOutputTensorsInfo) },
- { "allocateTensors", "(JLjava/util/List;[ILjava/util/List;I[Ljava/nio/ByteBuffer;)J", reinterpret_cast<void *>(Java_com_samsung_beyond_TensorHandler_allocateTensors) },
+ { "allocateTensors", "(J[Lcom/samsung/android/beyond/inference/tensor/TensorInfo;I[Ljava/nio/ByteBuffer;)J", reinterpret_cast<void *>(Java_com_samsung_beyond_TensorHandler_allocateTensors) },
{ "getOutput", "(J[Ljava/nio/ByteBuffer;I)J", reinterpret_cast<void *>(Java_com_samsung_beyond_TensorHandler_getOutput) },
{ "freeTensors", "(JJI)V", reinterpret_cast<void *>(Java_com_samsung_beyond_TensorHandler_freeTensors) },
};