diff --git a/platform/android/java_class_wrapper.cpp b/platform/android/java_class_wrapper.cpp index c19196ae871..ba4ecef055d 100644 --- a/platform/android/java_class_wrapper.cpp +++ b/platform/android/java_class_wrapper.cpp @@ -132,6 +132,116 @@ bool JavaClass::_call_method(JavaObject *p_instance, const StringName &p_method, } } } break; + case ARG_ARRAY_BIT | ARG_TYPE_BOOLEAN: { + if (p_args[i]->get_type() == Variant::ARRAY) { + Array arr = *p_args[i]; + if (arr.is_typed() && arr.get_typed_builtin() != Variant::BOOL) { + arg_expected = Variant::ARRAY; + } + } else { + arg_expected = Variant::ARRAY; + } + } break; + case ARG_ARRAY_BIT | ARG_TYPE_BYTE: + case ARG_ARRAY_BIT | ARG_TYPE_CHAR: { + if (p_args[i]->get_type() != Variant::PACKED_BYTE_ARRAY) { + arg_expected = Variant::PACKED_BYTE_ARRAY; + } + } break; + case ARG_ARRAY_BIT | ARG_TYPE_SHORT: + case ARG_ARRAY_BIT | ARG_TYPE_INT: { + if (p_args[i]->get_type() == Variant::ARRAY) { + Array arr = *p_args[i]; + if (arr.is_typed() && arr.get_typed_builtin() != Variant::INT) { + arg_expected = Variant::ARRAY; + } + } else if (p_args[i]->get_type() != Variant::PACKED_INT32_ARRAY) { + arg_expected = Variant::ARRAY; + } + } break; + case ARG_ARRAY_BIT | ARG_TYPE_LONG: { + if (p_args[i]->get_type() == Variant::ARRAY) { + Array arr = *p_args[i]; + if (arr.is_typed() && arr.get_typed_builtin() != Variant::INT) { + arg_expected = Variant::ARRAY; + } + } else if (p_args[i]->get_type() != Variant::PACKED_INT64_ARRAY) { + arg_expected = Variant::ARRAY; + } + } break; + case ARG_ARRAY_BIT | ARG_TYPE_FLOAT: { + if (p_args[i]->get_type() == Variant::ARRAY) { + Array arr = *p_args[i]; + if (arr.is_typed() && arr.get_typed_builtin() != Variant::FLOAT) { + arg_expected = Variant::ARRAY; + } + } else if (p_args[i]->get_type() != Variant::PACKED_FLOAT32_ARRAY) { + arg_expected = Variant::ARRAY; + } + } break; + case ARG_ARRAY_BIT | ARG_TYPE_DOUBLE: { + if (p_args[i]->get_type() == Variant::ARRAY) { + Array arr = *p_args[i]; + if (arr.is_typed() && arr.get_typed_builtin() != Variant::FLOAT) { + arg_expected = Variant::ARRAY; + } + } else if (p_args[i]->get_type() != Variant::PACKED_FLOAT64_ARRAY) { + arg_expected = Variant::ARRAY; + } + } break; + case ARG_ARRAY_BIT | ARG_TYPE_STRING: + case ARG_ARRAY_BIT | ARG_TYPE_CHARSEQUENCE: { + if (p_args[i]->get_type() == Variant::ARRAY) { + Array arr = *p_args[i]; + if (arr.is_typed() && arr.get_typed_builtin() != Variant::STRING) { + arg_expected = Variant::ARRAY; + } + } else if (p_args[i]->get_type() != Variant::PACKED_STRING_ARRAY) { + arg_expected = Variant::ARRAY; + } + } break; + case ARG_ARRAY_BIT | ARG_TYPE_CALLABLE: { + if (p_args[i]->get_type() == Variant::ARRAY) { + Array arr = *p_args[i]; + if (arr.is_typed() && arr.get_typed_builtin() != Variant::CALLABLE) { + arg_expected = Variant::ARRAY; + } + } else { + arg_expected = Variant::ARRAY; + } + } break; + case ARG_ARRAY_BIT | ARG_TYPE_CLASS: { + if (p_args[i]->get_type() == Variant::ARRAY) { + Array arr = *p_args[i]; + if (arr.is_typed() && arr.get_typed_builtin() != Variant::OBJECT) { + arg_expected = Variant::ARRAY; + } else { + String cn = E.param_sigs[i].operator String(); + if (cn.begins_with("[L") && cn.ends_with(";")) { + cn = cn.substr(2, cn.length() - 3); + } + jclass c = env->FindClass(cn.utf8().get_data()); + if (c) { + for (int j = 0; j < arr.size(); j++) { + Ref jo = arr[j]; + if (jo.is_valid()) { + if (!env->IsInstanceOf(jo->instance, c)) { + arg_expected = Variant::ARRAY; + break; + } + } else { + arg_expected = Variant::ARRAY; + break; + } + } + } else { + arg_expected = Variant::ARRAY; + } + } + } else { + arg_expected = Variant::ARRAY; + } + } break; default: { if (p_args[i]->get_type() != Variant::ARRAY) { arg_expected = Variant::ARRAY; @@ -307,90 +417,171 @@ bool JavaClass::_call_method(JavaObject *p_instance, const StringName &p_method, } break; case ARG_ARRAY_BIT | ARG_TYPE_BYTE: { - Array arr = *p_args[i]; - jbyteArray a = env->NewByteArray(arr.size()); - for (int j = 0; j < arr.size(); j++) { - jbyte val = arr[j]; - env->SetByteArrayRegion(a, j, 1, &val); + jbyteArray a = nullptr; + + if (p_args[i]->get_type() == Variant::ARRAY) { + Array arr = *p_args[i]; + a = env->NewByteArray(arr.size()); + for (int j = 0; j < arr.size(); j++) { + jbyte val = arr[j]; + env->SetByteArrayRegion(a, j, 1, &val); + } + } else if (p_args[i]->get_type() == Variant::PACKED_BYTE_ARRAY) { + PackedByteArray arr = *p_args[i]; + a = env->NewByteArray(arr.size()); + env->SetByteArrayRegion(a, 0, arr.size(), (const jbyte *)arr.ptr()); } + argv[i].l = a; to_free.push_back(a); } break; case ARG_ARRAY_BIT | ARG_TYPE_CHAR: { - Array arr = *p_args[i]; - jcharArray a = env->NewCharArray(arr.size()); - for (int j = 0; j < arr.size(); j++) { - jchar val = arr[j]; - env->SetCharArrayRegion(a, j, 1, &val); + jcharArray a = nullptr; + + if (p_args[i]->get_type() == Variant::ARRAY) { + Array arr = *p_args[i]; + a = env->NewCharArray(arr.size()); + for (int j = 0; j < arr.size(); j++) { + jchar val = arr[j]; + env->SetCharArrayRegion(a, j, 1, &val); + } + } else if (p_args[i]->get_type() == Variant::PACKED_BYTE_ARRAY) { + PackedByteArray arr = *p_args[i]; + // The data is expected to be UTF-16 encoded, so the length is half the size of the byte array. + int size = arr.size() / 2; + a = env->NewCharArray(size); + env->SetCharArrayRegion(a, 0, size, (const jchar *)arr.ptr()); } + argv[i].l = a; to_free.push_back(a); } break; case ARG_ARRAY_BIT | ARG_TYPE_SHORT: { - Array arr = *p_args[i]; - jshortArray a = env->NewShortArray(arr.size()); - for (int j = 0; j < arr.size(); j++) { - jshort val = arr[j]; - env->SetShortArrayRegion(a, j, 1, &val); + jshortArray a = nullptr; + + if (p_args[i]->get_type() == Variant::ARRAY) { + Array arr = *p_args[i]; + a = env->NewShortArray(arr.size()); + for (int j = 0; j < arr.size(); j++) { + jshort val = arr[j]; + env->SetShortArrayRegion(a, j, 1, &val); + } + } else if (p_args[i]->get_type() == Variant::PACKED_INT32_ARRAY) { + PackedInt32Array arr = *p_args[i]; + a = env->NewShortArray(arr.size()); + for (int j = 0; j < arr.size(); j++) { + jshort val = arr[j]; + env->SetShortArrayRegion(a, j, 1, &val); + } } + argv[i].l = a; to_free.push_back(a); } break; case ARG_ARRAY_BIT | ARG_TYPE_INT: { - Array arr = *p_args[i]; - jintArray a = env->NewIntArray(arr.size()); - for (int j = 0; j < arr.size(); j++) { - jint val = arr[j]; - env->SetIntArrayRegion(a, j, 1, &val); + jintArray a = nullptr; + + if (p_args[i]->get_type() == Variant::ARRAY) { + Array arr = *p_args[i]; + a = env->NewIntArray(arr.size()); + for (int j = 0; j < arr.size(); j++) { + jint val = arr[j]; + env->SetIntArrayRegion(a, j, 1, &val); + } + } else if (p_args[i]->get_type() == Variant::PACKED_INT32_ARRAY) { + PackedInt32Array arr = *p_args[i]; + a = env->NewIntArray(arr.size()); + env->SetIntArrayRegion(a, 0, arr.size(), arr.ptr()); } + argv[i].l = a; to_free.push_back(a); } break; case ARG_ARRAY_BIT | ARG_TYPE_LONG: { - Array arr = *p_args[i]; - jlongArray a = env->NewLongArray(arr.size()); - for (int j = 0; j < arr.size(); j++) { - jlong val = (int64_t)arr[j]; - env->SetLongArrayRegion(a, j, 1, &val); + jlongArray a = nullptr; + + if (p_args[i]->get_type() == Variant::ARRAY) { + Array arr = *p_args[i]; + a = env->NewLongArray(arr.size()); + for (int j = 0; j < arr.size(); j++) { + jlong val = (int64_t)arr[j]; + env->SetLongArrayRegion(a, j, 1, &val); + } + } else if (p_args[i]->get_type() == Variant::PACKED_INT64_ARRAY) { + PackedInt64Array arr = *p_args[i]; + a = env->NewLongArray(arr.size()); + env->SetLongArrayRegion(a, 0, arr.size(), arr.ptr()); } + argv[i].l = a; to_free.push_back(a); } break; case ARG_ARRAY_BIT | ARG_TYPE_FLOAT: { - Array arr = *p_args[i]; - jfloatArray a = env->NewFloatArray(arr.size()); - for (int j = 0; j < arr.size(); j++) { - jfloat val = arr[j]; - env->SetFloatArrayRegion(a, j, 1, &val); + jfloatArray a = nullptr; + + if (p_args[i]->get_type() == Variant::ARRAY) { + Array arr = *p_args[i]; + a = env->NewFloatArray(arr.size()); + for (int j = 0; j < arr.size(); j++) { + jfloat val = arr[j]; + env->SetFloatArrayRegion(a, j, 1, &val); + } + } else if (p_args[i]->get_type() == Variant::PACKED_FLOAT32_ARRAY) { + PackedFloat32Array arr = *p_args[i]; + a = env->NewFloatArray(arr.size()); + env->SetFloatArrayRegion(a, 0, arr.size(), arr.ptr()); } + argv[i].l = a; to_free.push_back(a); } break; case ARG_ARRAY_BIT | ARG_TYPE_DOUBLE: { - Array arr = *p_args[i]; - jdoubleArray a = env->NewDoubleArray(arr.size()); - for (int j = 0; j < arr.size(); j++) { - jdouble val = arr[j]; - env->SetDoubleArrayRegion(a, j, 1, &val); + jdoubleArray a = nullptr; + + if (p_args[i]->get_type() == Variant::ARRAY) { + Array arr = *p_args[i]; + a = env->NewDoubleArray(arr.size()); + for (int j = 0; j < arr.size(); j++) { + jdouble val = arr[j]; + env->SetDoubleArrayRegion(a, j, 1, &val); + } + } else if (p_args[i]->get_type() == Variant::PACKED_FLOAT64_ARRAY) { + PackedFloat64Array arr = *p_args[i]; + a = env->NewDoubleArray(arr.size()); + env->SetDoubleArrayRegion(a, 0, arr.size(), arr.ptr()); } + argv[i].l = a; to_free.push_back(a); } break; case ARG_ARRAY_BIT | ARG_TYPE_STRING: case ARG_ARRAY_BIT | ARG_TYPE_CHARSEQUENCE: { - Array arr = *p_args[i]; - jobjectArray a = env->NewObjectArray(arr.size(), env->FindClass("java/lang/String"), nullptr); - for (int j = 0; j < arr.size(); j++) { - String s = arr[j]; - jstring jStr = env->NewStringUTF(s.utf8().get_data()); - env->SetObjectArrayElement(a, j, jStr); - to_free.push_back(jStr); + jobjectArray a = nullptr; + + if (p_args[i]->get_type() == Variant::ARRAY) { + Array arr = *p_args[i]; + a = env->NewObjectArray(arr.size(), env->FindClass("java/lang/String"), nullptr); + for (int j = 0; j < arr.size(); j++) { + String s = arr[j]; + jstring jStr = env->NewStringUTF(s.utf8().get_data()); + env->SetObjectArrayElement(a, j, jStr); + to_free.push_back(jStr); + } + } else if (p_args[i]->get_type() == Variant::PACKED_STRING_ARRAY) { + PackedStringArray arr = *p_args[i]; + a = env->NewObjectArray(arr.size(), env->FindClass("java/lang/String"), nullptr); + for (int j = 0; j < arr.size(); j++) { + String s = arr[j]; + jstring jStr = env->NewStringUTF(s.utf8().get_data()); + env->SetObjectArrayElement(a, j, jStr); + to_free.push_back(jStr); + } } argv[i].l = a; @@ -410,7 +601,22 @@ bool JavaClass::_call_method(JavaObject *p_instance, const StringName &p_method, to_free.push_back(jarr); } break; case ARG_ARRAY_BIT | ARG_TYPE_CLASS: { - argv[i].l = nullptr; + String cn = method->param_sigs[i].operator String(); + if (cn.begins_with("[L") && cn.ends_with(";")) { + cn = cn.substr(2, cn.length() - 3); + } + jclass c = env->FindClass(cn.utf8().get_data()); + if (c) { + Array arr = *p_args[i]; + jobjectArray jarr = env->NewObjectArray(arr.size(), c, nullptr); + for (int j = 0; j < arr.size(); j++) { + Ref jo = arr[j]; + env->SetObjectArrayElement(jarr, j, jo->instance); + } + + argv[i].l = jarr; + to_free.push_back(jarr); + } } break; } }