#include #include #include #include #include #include #include "common/serial_port.h" #include "jni_log.h" #include "common/net.h" #include "common/apptimer.h" #include "rtk_platform/parse_net.h" #include "native-lib.h" #include "test_common/Geometry.h" #include "rtk_platform/platform.h" #include "rtk_module/rtk.h" #include "mcu/mcu_if.h" #include "driver_test.h" #include "master/comm_if.h" #include "rtk_module/virtual_rtk.h" #include "defs.h" #define DEBUG(fmt, args...) LOGD(" <%s>: " fmt, __func__, ##args) static JavaVM *sg_jvm = NULL; static jobject sg_obj = NULL; const char *RTK_PLATFORM_IP = "47.93.80.84"; const int RTK_PLATFORM_PORT = 12125; const uint8_t phone[] = {0x20,0x19,0x10,0x15,0x00,0x00,0x00,0x01}; const char *VIRTUAL_RTK_IP = "192.168.16.100"; const int VIRTUAL_RTK_PORT = 9002; static pthread_mutex_t tts_mutex = PTHREAD_MUTEX_INITIALIZER; static int ttsSeq = 1; static std::map TTSCallBack; int DESEncrypt(const uint8_t *key, int key_length, const uint8_t *plaintext, int plaintext_length, uint8_t **ciphertext) { JNIEnv *env; bool ready_in_java_env = false; int ciphertext_length = 0; *ciphertext = NULL; LOGD("JNI_DESEncrypt"); if (sg_jvm->GetEnv((void **)&env, JNI_VERSION_1_6) != JNI_OK) { // Attach主线程 if (sg_jvm->AttachCurrentThread(&env, NULL) != JNI_OK) { LOGE("%s: AttachCurrentThread() failed", __FUNCTION__); return 0; } } else { ready_in_java_env = true; } jclass cls = env->GetObjectClass(sg_obj); jmethodID fun = env->GetMethodID(cls, "javaDESEncrypt", "([B[B)[B"); jbyteArray jni_key = env->NewByteArray(key_length); jbyteArray jni_plaintext = env->NewByteArray(plaintext_length); env->SetByteArrayRegion(jni_key, 0, key_length, (jbyte *) key); env->SetByteArrayRegion(jni_plaintext, 0, plaintext_length, (jbyte *) plaintext); jbyteArray jni_ciphertext = (jbyteArray) env->CallObjectMethod(sg_obj, fun, jni_plaintext, jni_key); if (jni_ciphertext != NULL) { ciphertext_length = env->GetArrayLength(jni_ciphertext); uint8_t *buffer = (uint8_t *)malloc(ciphertext_length); env->GetByteArrayRegion(jni_ciphertext, 0, ciphertext_length, (jbyte *) buffer); *ciphertext = buffer; } env->DeleteLocalRef(jni_key); env->DeleteLocalRef(jni_plaintext); env->DeleteLocalRef(cls); if (!ready_in_java_env) { //Detach主线程 if (sg_jvm->DetachCurrentThread() != JNI_OK) { LOGE("%s: DetachCurrentThread() failed", __FUNCTION__); } } return ciphertext_length; } void TextOsd(int type, const char *text) { /* JNIEnv *env; bool ready_in_java_env = false; if (sg_jvm->GetEnv((void **)&env, JNI_VERSION_1_6) != JNI_OK) { // Attach主线程 if (sg_jvm->AttachCurrentThread(&env, NULL) != JNI_OK) { LOGE("%s: AttachCurrentThread() failed", __FUNCTION__); return; } } else { ready_in_java_env = true; } jclass cls = env->GetObjectClass(sg_obj); jmethodID fun = env->GetMethodID(cls, "TextOsd", "(ILjava/lang/String;)V"); std::string cstext = text; env->CallVoidMethod(sg_obj, fun, type, env->NewStringUTF(cstext.c_str())); env->DeleteLocalRef(cls); if (!ready_in_java_env) { //Detach主线程 if (sg_jvm->DetachCurrentThread() != JNI_OK) { LOGE("%s: DetachCurrentThread() failed", __FUNCTION__); } }*/ } void DrawScreen(const Polygon *map, const Polygon *car) { JNIEnv *env; bool ready_in_java_env = false; if (sg_jvm->GetEnv((void **)&env, JNI_VERSION_1_6) != JNI_OK) { // Attach主线程 if (sg_jvm->AttachCurrentThread(&env, NULL) != JNI_OK) { LOGE("%s: AttachCurrentThread() failed", __FUNCTION__); return; } } else { ready_in_java_env = true; } jclass cls = env->GetObjectClass(sg_obj); jmethodID fun = env->GetMethodID(cls, "DrawMap", "([[D[[D)V"); jclass doubleArrCls = env->FindClass("[D"); jobjectArray retmap = env->NewObjectArray(map->num, doubleArrCls, NULL); jobjectArray retcar = env->NewObjectArray(car->num, doubleArrCls, NULL); for (int i = 0; i < map->num; ++i) { jdoubleArray doubleArr = env->NewDoubleArray(2); jdouble tmp[2] = {map->point[i].X, 0 - map->point[i].Y}; env->SetDoubleArrayRegion(doubleArr, 0, 2, tmp); env->SetObjectArrayElement(retmap, i, doubleArr); env->DeleteLocalRef(doubleArr); } for (int i = 0; i < car->num; ++i) { jdoubleArray doubleArr = env->NewDoubleArray(2); jdouble tmp[2] = {car->point[i].X, 0 - car->point[i].Y}; env->SetDoubleArrayRegion(doubleArr, 0, 2, tmp); env->SetObjectArrayElement(retcar, i, doubleArr); env->DeleteLocalRef(doubleArr); } env->CallVoidMethod(sg_obj, fun, retmap, retcar); env->DeleteLocalRef(retmap); env->DeleteLocalRef(retcar); env->DeleteLocalRef(cls); if (!ready_in_java_env) { //Detach主线程 if (sg_jvm->DetachCurrentThread() != JNI_OK) { LOGE("%s: DetachCurrentThread() failed", __FUNCTION__); } } } int SendMsgToMainProc(int cmd, const char *value) { JNIEnv *env; bool ready_in_java_env = false; int ret; if (sg_jvm->GetEnv((void **)&env, JNI_VERSION_1_6) != JNI_OK) { // Attach主线程 if (sg_jvm->AttachCurrentThread(&env, NULL) != JNI_OK) { LOGE("%s: AttachCurrentThread() failed", __FUNCTION__); return -3; } } else { ready_in_java_env = true; } jclass cls = env->GetObjectClass(sg_obj); jmethodID fun = env->GetMethodID(cls, "SendMsgToMainProc", "(ILjava/lang/String;)I"); ret = env->CallIntMethod(sg_obj, fun, cmd, value != NULL ? env->NewStringUTF(value) : NULL); env->DeleteLocalRef(cls); if (!ready_in_java_env) { //Detach主线程 if (sg_jvm->DetachCurrentThread() != JNI_OK) { LOGE("%s: DetachCurrentThread() failed", __FUNCTION__); } } return ret; } static int GetTtsSeq(void) { int seq = 0; pthread_mutex_lock(&tts_mutex); seq = ttsSeq++; pthread_mutex_unlock(&tts_mutex); return seq; } int PlayTTS(const char *string, void (*callback)(int)) { DEBUG("PlayTTS: %s", string); JNIEnv *env; bool ready_in_java_env = false; if (sg_jvm->GetEnv((void **)&env, JNI_VERSION_1_6) != JNI_OK) { // Attach主线程 if (sg_jvm->AttachCurrentThread(&env, NULL) != JNI_OK) { LOGE("%s: AttachCurrentThread() failed", __FUNCTION__); return -1; } } else { ready_in_java_env = true; } jclass cls = env->GetObjectClass(sg_obj); jmethodID fun = env->GetMethodID(cls, "TextSpeak", "(Ljava/lang/String;I)V"); int id = GetTtsSeq(); env->CallVoidMethod(sg_obj, fun, env->NewStringUTF(string), id); env->DeleteLocalRef(cls); if (!ready_in_java_env) { //Detach主线程 if (sg_jvm->DetachCurrentThread() != JNI_OK) { LOGE("%s: DetachCurrentThread() failed", __FUNCTION__); } } TTSCallBack.insert(pair(id, callback)); return id; } int PlayTTS(std::string &tts, void (*callback)(int)) { return PlayTTS(tts.c_str(), callback); } void PlayRing(void) { JNIEnv *env; bool ready_in_java_env = false; if (sg_jvm->GetEnv((void **)&env, JNI_VERSION_1_6) != JNI_OK) { // Attach主线程 if (sg_jvm->AttachCurrentThread(&env, NULL) != JNI_OK) { LOGE("%s: AttachCurrentThread() failed", __FUNCTION__); return; } } else { ready_in_java_env = true; } jclass cls = env->GetObjectClass(sg_obj); jmethodID fun = env->GetMethodID(cls, "PlayBreakRing", "()V"); env->CallVoidMethod(sg_obj, fun); env->DeleteLocalRef(cls); if (!ready_in_java_env) { //Detach主线程 if (sg_jvm->DetachCurrentThread() != JNI_OK) { LOGE("%s: DetachCurrentThread() failed", __FUNCTION__); } } } void SendToBluetooth(const uint8_t *data, int length) { JNIEnv *env; bool ready_in_java_env = false; if (sg_jvm->GetEnv((void **)&env, JNI_VERSION_1_6) != JNI_OK) { // Attach主线程 if (sg_jvm->AttachCurrentThread(&env, NULL) != JNI_OK) { LOGE("%s: AttachCurrentThread() failed", __FUNCTION__); return; } } else { ready_in_java_env = true; } jclass cls = env->GetObjectClass(sg_obj); jmethodID fun = env->GetMethodID(cls, "WriteBluetooth", "([B)V"); jbyteArray array = env->NewByteArray(length); env->SetByteArrayRegion(array, 0, length, (jbyte *) data); env->CallVoidMethod(sg_obj, fun, array); env->DeleteLocalRef(array); env->DeleteLocalRef(cls); if (!ready_in_java_env) { //Detach主线程 if (sg_jvm->DetachCurrentThread() != JNI_OK) { LOGE("%s: DetachCurrentThread() failed", __FUNCTION__); } } } void ConnectToBluetooth(const char *addr, const char *pin) { JNIEnv *env; bool ready_in_java_env = false; if (sg_jvm->GetEnv((void **)&env, JNI_VERSION_1_6) != JNI_OK) { // Attach主线程 if (sg_jvm->AttachCurrentThread(&env, NULL) != JNI_OK) { LOGE("%s: AttachCurrentThread() failed", __FUNCTION__); return; } } else { ready_in_java_env = true; } jclass cls = env->GetObjectClass(sg_obj); jmethodID fun = env->GetMethodID(cls, "ConnectBluetooth", "(Ljava/lang/String;Ljava/lang/String;)V"); env->CallVoidMethod(sg_obj, fun, env->NewStringUTF(addr), (pin == NULL) ? NULL : env->NewStringUTF(pin)); env->DeleteLocalRef(cls); if (!ready_in_java_env) { //Detach主线程 if (sg_jvm->DetachCurrentThread() != JNI_OK) { LOGE("%s: DetachCurrentThread() failed", __FUNCTION__); } } } void DisconnectBluetooth(void) { JNIEnv *env; bool ready_in_java_env = false; if (sg_jvm->GetEnv((void **)&env, JNI_VERSION_1_6) != JNI_OK) { // Attach主线程 if (sg_jvm->AttachCurrentThread(&env, NULL) != JNI_OK) { LOGE("%s: AttachCurrentThread() failed", __FUNCTION__); return; } } else { ready_in_java_env = true; } jclass cls = env->GetObjectClass(sg_obj); jmethodID fun = env->GetMethodID(cls, "DisconnectBluetooth", "()V"); env->CallVoidMethod(sg_obj, fun); env->DeleteLocalRef(cls); if (!ready_in_java_env) { //Detach主线程 if (sg_jvm->DetachCurrentThread() != JNI_OK) { LOGE("%s: DetachCurrentThread() failed", __FUNCTION__); } } } extern "C" JNIEXPORT void JNICALL Java_com_anyun_exam_lib_RemoteService_startNative(JNIEnv *env, jobject thiz, jboolean ayDevice) { // TODO: implement startNative() // 保存全局JVM以便在子线程中使用 DEBUG("启动Native"); env->GetJavaVM(&sg_jvm); // 不能直接赋值(g_obj = ojb) sg_obj = env->NewGlobalRef(thiz); srand(time(NULL)); AppTimer_Init(); ConfigMCU(ayDevice); DriverTestInit(); ConfigRTKModule(ayDevice); MA_Init(); InitPlatform(ayDevice, phone, RTK_PLATFORM_IP, RTK_PLATFORM_PORT); InitVirtualDevice(VIRTUAL_RTK_IP, VIRTUAL_RTK_PORT); pthread_mutex_init(&tts_mutex, NULL); MA_NdkStart(); } extern "C" JNIEXPORT void JNICALL Java_com_anyun_exam_lib_RemoteService_MainProcMsgEntry(JNIEnv *env, jobject thiz, jint cmd, jstring value) { // TODO: implement MainProcMsgEntry() union { int a; uint8_t b[sizeof(int)]; } c; c.a = cmd; if (value != NULL) { const char *str = env->GetStringUTFChars(value, 0); uint8_t *data = new uint8_t[4 + strlen(str) + 1]; data[0] = c.b[0]; data[1] = c.b[1]; data[2] = c.b[2]; data[3] = c.b[3]; strcpy((char *)data + 4, str); // MA_MainProcMsgEntry(cmd, str); PlatformStatusChanged(MASTER_COMM_EVT, data, 4 + strlen(str) + 1); env->ReleaseStringUTFChars(value, str); delete []data; } else { //MA_MainProcMsgEntry(cmd, NULL); PlatformStatusChanged(MASTER_COMM_EVT, c.b, sizeof(int)); } } extern "C" JNIEXPORT void JNICALL Java_com_anyun_exam_lib_RemoteService_MainProcBinMsgEntry(JNIEnv *env, jobject thiz, jint cmd, jbyteArray data, jint length) { // TODO: implement MainProcBinMsgEntry() jbyte *c_dat = env->GetByteArrayElements(data, NULL); int len = env->GetArrayLength(data); MA_MainProcBinMsgEntry(cmd, (uint8_t *)c_dat, len); env->ReleaseByteArrayElements(data, c_dat, NULL); } extern "C" JNIEXPORT void JNICALL Java_com_anyun_exam_lib_RemoteService_TextSpeakEnd(JNIEnv *env, jobject thiz, jint id) { // TODO: implement TextSpeakEnd() auto it = TTSCallBack.find(id); if (it != TTSCallBack.end()) { if (it->second != NULL) { tts_back_t tb; tb.seq = id; tb.callback = (void (*)(int)) it->second; PlatformStatusChanged(PLAY_TTS_DONE_EVT, (uint8_t *)&tb, sizeof(tb)); } TTSCallBack.erase(it); } } extern "C" JNIEXPORT void JNICALL Java_com_anyun_exam_lib_RemoteService_UpgradeMcu(JNIEnv *env, jobject thiz, jstring vercode, jbyteArray rom) { // TODO: implement UpgradeMcu() if (vercode != NULL && rom != NULL) { const char *str = env->GetStringUTFChars(vercode, 0); jbyte *c_dat = env->GetByteArrayElements(rom, NULL); int len = env->GetArrayLength(rom); LoadDefaultMcuRom(str, (uint8_t *)c_dat, len); env->ReleaseStringUTFChars(vercode, str); env->ReleaseByteArrayElements(rom, c_dat, NULL); } } extern "C" JNIEXPORT void JNICALL Java_com_anyun_exam_lib_RemoteService_BluetoothDataComeIn(JNIEnv *env, jobject thiz, jbyteArray data, jint length) { // TODO: implement BluetoothDataComeIn() jbyte *c_dat = env->GetByteArrayElements(data, NULL); PlatformStatusChanged(BLUETOOTH_DATA_EVT, (uint8_t *)c_dat, length); env->ReleaseByteArrayElements(data, c_dat, NULL); } extern "C" JNIEXPORT void JNICALL Java_com_anyun_exam_lib_RemoteService_BluetoothStatusChange(JNIEnv *env, jobject thiz, jint status) { // TODO: implement BluetoothStatusChange() uint8_t sta = status; PlatformStatusChanged(BLUETOOTH_STATUS_EVT, &sta, 1); } extern "C" JNIEXPORT void JNICALL Java_com_anyun_exam_lib_RemoteService_BluetoothConnected(JNIEnv *env, jobject thiz, jstring name, jstring addr) { // TODO: implement BluetoothConnected() if (name != NULL && addr != NULL) { const char *strname = env->GetStringUTFChars(name, 0); const char *straddr = env->GetStringUTFChars(addr, 0); uint8_t data[128]; strcpy((char *)data, strname); strcpy((char *)data + 64, straddr); env->ReleaseStringUTFChars(name, strname); env->ReleaseStringUTFChars(addr, straddr); PlatformStatusChanged(BLUETOOTH_STATUS_EVT, data, 128); } else if (addr != NULL) { const char *straddr = env->GetStringUTFChars(addr, 0); uint8_t data[64]; strcpy((char *)data, straddr); env->ReleaseStringUTFChars(addr, straddr); PlatformStatusChanged(BLUETOOTH_STATUS_EVT, data, 64); } else { uint8_t sta = 3; PlatformStatusChanged(BLUETOOTH_STATUS_EVT, &sta, 1); } }