subject-two/entry/src/main/cpp/sdk/api/jni/JNIApiBridge.cpp
2024-08-26 16:07:11 +08:00

406 lines
13 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#if defined(JUDGE_OS_ANDROID)
#include "JNIApiBridge.h"
JNIApiBridge::JNIApiBridge()
{
}
JNIApiBridge::~JNIApiBridge()
{
bool need = false;
JNIEnv* env = ifNeedAttachCurrentThread(need);
if(env != NULL)
{
methodDestory(env, m_cbLog);
methodDestory(env, m_cbReal);
methodDestory(env, m_cbPerform);
methodDestory(env, m_cbMap);
}
ifNeedDetachCurrentThread(need);
}
jint JNIApiBridge::JNI_OnLoad(JavaVM* jvm, void* reserved)
{
m_jvm = jvm;
return JNI_OK;
}
void JNIApiBridge::JNI_OnUnload(JavaVM* jvm, void* reserved)
{
if(m_jvm)
{
m_jvm->DestroyJavaVM();
}
}
//JNI_JUDGE_FUN_IMPL(jstring, examJudgeVersion, (JNIEnv* env, jobject thiz))
jstring JNI_JUDGE_FUN_IMPL(examJudgeVersion)(JNIEnv* env, jobject thiz)
{
logdebug("call JNI_examJudgeVersion");
const char* version = ExamService::examJudgeVersion();
return env->NewStringUTF(nullptr != version ? version : "");
}
jint JNI_JUDGE_FUN_IMPL(examJudgeSetLogCallback)(JNIEnv* env, jobject thiz, jint level)
{
logdebug("call JNI_examJudgeSetLogCallback");
ExamService::examJudgeSetLogCallback(level, NULL);
__DELETE__(m_cbLog); //防止重复注册要销毁
m_cbLog = methodCreate(env, thiz, JNI_FUN(examJudgeCallbackLog));
ErrorCode code = m_cbLog != NULL ? codeSuccess : errorJNISetCallback;
return (jint)QE(code);
}
jstring JNI_JUDGE_FUN_IMPL(examJudgeErrorInfo)(JNIEnv* env, jobject thiz, jint errorCode)
{
logdebug("call JNI_examJudgeErrorInfo");
const char* errinfo = ExamService::examJudgeErrorInfo(errorCode);
return env->NewStringUTF(nullptr != errinfo ? errinfo : "");
}
jint JNI_JUDGE_FUN_IMPL(examJudgeInit)(JNIEnv* env, jobject thiz, jstring data, jint len)
{
logdebug("call JNI_examJudgeInit");
//释放模式
//0 复制回内容并释放缓冲区
//JNI_COMMIT 复制回内容但不释放缓冲区
//JNI_ABORT 释放缓冲区但不复制回变化
//jint version = env->GetVersion();
const char* buf = env->GetStringUTFChars(data, NULL);
jsize size = env->GetStringUTFLength(data);
TASSERT(buf != nullptr && size == len, "");
int code = ExamService::examJudgeInit(buf, len);
env->ReleaseStringUTFChars(data, buf);
return (jint)QE((ErrorCode)code);
}
jint JNI_JUDGE_FUN_IMPL(examJudgeDestroy)(JNIEnv* env, jobject thiz)
{
logdebug("call JNI_examJudgeDestroy");
int code = ExamService::examJudgeDestroy();
return (jint)QE((ErrorCode)code);
}
jint JNI_JUDGE_FUN_IMPL(examJudgeBeginExam)(JNIEnv* env, jobject thiz, jstring data, jint len)
{
logdebug("call JNI_examJudgeBeginExam");
const char* buf = env->GetStringUTFChars(data, NULL);
jsize size = env->GetStringUTFLength(data);
TASSERT(buf != nullptr && size == len, "");
int code = ExamService::examJudgeBeginExam(buf, len);
env->ReleaseStringUTFChars(data, buf);
return (jint)QE((ErrorCode)code);
}
jint JNI_JUDGE_FUN_IMPL(examJudgeEndExam)(JNIEnv *env, jobject thiz)
{
logdebug("call JNI_examJudgeEndExam");
int code = ExamService::examJudgeEndExam();
return (jint)QE((ErrorCode)code);
}
jint JNI_JUDGE_FUN_IMPL(examJudgeRealExam)(JNIEnv* env, jobject thiz, jstring data, jint len)
{
logdebug("call JNI_examJudgeBeginExam");
const char* buf = env->GetStringUTFChars(data, NULL);
jsize size = env->GetStringUTFLength(data);
TASSERT(buf != nullptr && size == len, "");
int code = ExamService::examJudgeRealExam(buf, len);
env->ReleaseStringUTFChars(data, buf);
return (jint)QE((ErrorCode)code);
}
jint JNI_JUDGE_FUN_IMPL(examJudgeSetRealExamCallback)(JNIEnv* env, jobject thiz)
{
logdebug("call JNI_examJudgeSetRealExamCallback");
__DELETE__(m_cbReal); //防止重复注册要销毁
m_cbReal = methodCreate(env, thiz, JNI_FUN(examJudgeCallbackRealExam));
ErrorCode code = m_cbReal != NULL ? codeSuccess : errorJNISetCallback;
return (jint)QE(code);
}
jint JNI_JUDGE_FUN_IMPL(examJudgeSetPerformCallback)(JNIEnv* env, jobject thiz)
{
logdebug("call JNI_examJudgeSetPerformCallback");
__DELETE__(m_cbPerform); //防止重复注册要销毁
m_cbPerform = methodCreate(env, thiz, JNI_FUN(examJudgeCallbackPerform));
ErrorCode code = m_cbPerform != NULL ? codeSuccess : errorJNISetCallback;
return (jint)QE(code);
}
jint JNI_JUDGE_FUN_IMPL(examJudgeArtificialMark)(JNIEnv* env, jobject thiz, jint itemno, jstring serial, jint type)
{
logdebug("call JNI_examJudgeArtificialMark");
const char* markSerial = env->GetStringUTFChars(serial, NULL);
//jsize size = env->GetStringUTFLength(data);
//TASSERT(buf != nullptr && size == len, "");
int code = ExamService::examJudgeArtificialMark(itemno, markSerial, type);
env->ReleaseStringUTFChars(serial, markSerial);
return (jint)QE((ErrorCode)code);
}
jint JNI_JUDGE_FUN_IMPL(examJudgeArtificialItem)(JNIEnv* env, jobject thiz, jint itemno, jint type)
{
logdebug("call JNI_examJudgeArtificialItem");
int code = ExamService::examJudgeArtificialItem(itemno, type);
return (jint)QE((ErrorCode)code);
}
jint JNI_JUDGE_FUN_IMPL(examJudgeSoundEnd)(JNIEnv* env, jobject thiz, jint itemno, jstring code, jint type)
{
logdebug("call JNI_examJudgeSoundEnd");
const char* soundCode = env->GetStringUTFChars(code, NULL);
//jsize size = env->GetStringUTFLength(data);
//TASSERT(buf != nullptr && size == len, "");
int errCode = ExamService::examJudgeSoundEnd(itemno, soundCode, type);
env->ReleaseStringUTFChars(code, soundCode);
return (jint)QE((ErrorCode)errCode);
}
jstring JNI_JUDGE_FUN_IMPL(examJudgeTrackFile)(JNIEnv* env, jobject thiz)
{
logdebug("call JNI_examJudgeTrackFile");
const char* filename = ExamService::examJudgeTrackFile();
return env->NewStringUTF(nullptr != filename ? filename : "");
}
jint JNI_JUDGE_FUN_IMPL(examJudgeMapSetParam)(JNIEnv* env, jobject thiz, jint width, jint height)
{
logdebug("call JNI_examJudgeMapSetParam");
int code = ExamService::examJudgeMapSetParam(width, height);
return (jint)QE((ErrorCode)code);
}
jint JNI_JUDGE_FUN_IMPL(examJudgeMapSetScaling)(JNIEnv* env, jobject thiz, jint scaling)
{
logdebug("call JNI_examJudgeMapSetScaling");
int code = ExamService::examJudgeMapSetScaling(scaling);
return (jint)QE((ErrorCode)code);
}
jint JNI_JUDGE_FUN_IMPL(examJudgeMapSetDrawing)(JNIEnv* env, jobject thiz, jboolean drawing)
{
logdebug("call JNI_examJudgeMapSetScaling");
int code = ExamService::examJudgeMapSetDrawing((bool)drawing);
return (jint)QE((ErrorCode)code);
}
jbyteArray JNI_JUDGE_FUN_IMPL(examJudgeMapImage)(JNIEnv* env, jobject thiz)
{
logdebug("call JNI_examJudgeMapSetDrawing");
const char* data = ExamService::examJudgeMapImage();
int size = ExamService::examJudgeMapSize();
jbyteArray jbytes = env->NewByteArray(size);
env->SetByteArrayRegion(jbytes, 0, size, (jbyte*)data);//赋值到jbyteArray
// 删除局部引用
//env->DeleteLocalRef(jbytes); //???有问题这里怎么释放? 这里应该不需要
return jbytes;
}
jint JNI_JUDGE_FUN_IMPL(examJudgeMapImageSetCallback)(JNIEnv* env, jobject thiz)
{
logdebug("call JNI_examJudgeMapImageSetCallback");
__DELETE__(m_cbMap); //防止重复注册要销毁
m_cbMap = methodCreate(env, thiz, JNI_FUN(examJudgeCallbackMapImage));
ErrorCode code = m_cbMap != NULL ? codeSuccess : errorJNISetCallback;
return (jint)QE(code);
}
jdouble JNI_JUDGE_FUN_IMPL(examCalcGpsDistance)(JNIEnv* env, jobject thiz, jdouble jd1, jdouble wd1, jdouble jd2, jdouble wd2, jdouble h)
{
logdebug("call JNI_examCalcGpsDistance");
double distance = ExamService::examCalcGpsDistance(jd1, wd1, jd2, wd2, h);
return (jdouble)distance;
}
void JNIApiBridge::examJudgeCallbackLogToCaller(int level, const char* info, int len)
{
if(NULL == m_cbLog || level < LOG_LV_CLOSE || level > LOG_LV_ALL || NULL == info || len <= 0)
{
return;
}
JNI_JUDGE_CALLBACK_ENTER
jstring jstr = env->NewStringUTF(info);
//len = env->GetStringLength(jstr);
callMethodA(env, m_cbLog, jint(level), jstr, jint(len));
env->DeleteLocalRef(jstr);
JNI_JUDGE_CALLBACK_LEAVE
}
void JNIApiBridge::examJudgeCallbackRealExamToCaller(const char* data, int len)
{
if(NULL == m_cbReal || NULL == data || len <= 0)
{
return;
}
JNI_JUDGE_CALLBACK_ENTER
jstring jstr = env->NewStringUTF(data);
//len = env->GetStringLength(jstr);
callMethodA(env, m_cbReal, jstr, jint(len));
env->DeleteLocalRef(jstr);
JNI_JUDGE_CALLBACK_LEAVE
}
void JNIApiBridge::examJudgeCallbackPerformToCaller(const char* data, int len)
{
if(NULL == m_cbPerform || NULL == data || len <= 0)
{
return;
}
JNI_JUDGE_CALLBACK_ENTER
jstring jstr = env->NewStringUTF(data);
//len = env->GetStringLength(jstr);
callMethodA(env, m_cbPerform, jstr, jint(len));
env->DeleteLocalRef(jstr);
JNI_JUDGE_CALLBACK_LEAVE
}
void JNIApiBridge::examJudgeCallbackMapImageToCaller(const char* data, int len)
{
if(NULL == m_cbMap || NULL == data || len <= 0)
{
return;
}
JNI_JUDGE_CALLBACK_ENTER
jbyteArray jbytes = env->NewByteArray(len);
env->SetByteArrayRegion(jbytes, 0, len, (jbyte*)data); //赋值到jbyteArray
callMethodA(env, m_cbMap, jbytes, jint(len));
env->DeleteLocalRef(jbytes);
JNI_JUDGE_CALLBACK_LEAVE
}
jvalue JNIApiBridge::callMethodA(JNIEnv* env, JNIMethodID* method, ...)
{
jvalue rv;
va_list args;
va_start(args, method);
rv = callMethodV(env, method, args);
va_end(args);
return rv;
}
jvalue JNIApiBridge::callMethodV(JNIEnv* env, JNIMethodID* method, va_list args)
{
jboolean hasException = false;
jboolean* excep = &hasException;
jvalue rv = { 0 };
if(NULL == method || !method->valid())
{
return rv;
}
jint ret = env->EnsureLocalCapacity(2);
if(JNI_OK != ret)
{
jclass clazz = env->GetObjectClass(method->object);
jmethodID mid = method->method;
char retv = method->retv.front(); //获取返回值签名类型首字母
switch (retv) {
case 'V': JNI_JUDGE_CALL_METHOD(Void); break; // env->CallVoidMethodV(obj, mid, args);
case 'Z': rv.z = JNI_JUDGE_CALL_METHOD(Boolean); break;
case 'B': rv.b = JNI_JUDGE_CALL_METHOD(Byte); break;
case 'C': rv.c = JNI_JUDGE_CALL_METHOD(Char); break;
case 'S': rv.s = JNI_JUDGE_CALL_METHOD(Short); break;
case 'I': rv.i = JNI_JUDGE_CALL_METHOD(Int); break;
case 'J': rv.j = JNI_JUDGE_CALL_METHOD(Long); break;
case 'F': rv.f = JNI_JUDGE_CALL_METHOD(Float); break;
case 'D': rv.d = JNI_JUDGE_CALL_METHOD(Double); break;
case '[':
case 'L': rv.l = JNI_JUDGE_CALL_METHOD(Object); break;
default:
logerror("call method %s sign %s illegal.", method, method->sign.c_str());
env->FatalError("illegal return sign");
break;
}
env->DeleteLocalRef(clazz);
}
if(NULL != excep)
{
//但是当有挂起的异常时返回JNI_TRUE在没有挂起的异常的时候返回JNI_FALSE
*excep = env->ExceptionCheck();
if(JNI_TRUE == *excep)
{
jthrowable e = env->ExceptionOccurred();
jint code = env->Throw(e);
env->DeleteLocalRef(e);
env->ExceptionClear();
logerror("call method %s occurred exception %d.", method, code);
env->FatalError("call method occurred exception");
}
}
return rv;
}
JNIMethodID* JNIApiBridge::methodCreate(JNIEnv* env, jobject thiz, const char* name)
{
//jclass clazz = env->FindClass(JNI_JUDGE_CLASS_NAME);
JNISignID* sig = JNI_JUDGE_METGOD_SIGN(name);
TASSERT_NULL(sig != NULL, "");
jclass clazz = env->GetObjectClass(thiz);
jmethodID id = env->GetMethodID(clazz, name, sig->sign.c_str());
env->DeleteLocalRef(clazz);
return NEW JNIMethodID(*sig, env->NewGlobalRef(thiz), id);
}
void JNIApiBridge::methodDestory(JNIEnv* env, JNIMethodID* & method)
{
if(method->object != NULL)
{
env->DeleteGlobalRef(method->object);
}
__DELETE__(method);
}
JNIEnv* JNIApiBridge::ifNeedAttachCurrentThread(bool& need)
{
need = false;
JNIEnv* env = NULL;
jint ret = m_jvm->GetEnv(reinterpret_cast<void**>(&env), JNI_JUDGE_VERSION);
if(JNI_EDETACHED == ret)
{
JNI_JUDGE_LOG("JavaVM AttachCurrentThreadIfNeeded");
need = true;
ret = m_jvm->AttachCurrentThread(&env, nullptr);
if(JNI_OK != ret)
{
JNI_JUDGE_LOG("JavaVM AttachCurrentThread failed");
}
else
{
JNI_JUDGE_LOG("JavaVM AttachCurrentThread ok");
}
}
else
{
JNI_JUDGE_LOG("JavaVM AttachCurrentThreadIfNeeded Not");
}
return env;
}
void JNIApiBridge::ifNeedDetachCurrentThread(bool& need)
{
if(need)
{
m_jvm->DetachCurrentThread();
}
}
#endif // JUDGE_OS_ANDROID