#include #include #include #include #include #include "TerminalDevice.h" #include "PhoneDevice.h" #include "PhoneDevice2.h" #include #include #include #include #include "ncnn/yolov5ncnn.h" #include #define NRSEC_PATH "/dev/spidev0.0" #ifdef USING_BREAK_PAD #include "client/linux/handler/exception_handler.h" #include "client/linux/handler/minidump_descriptor.h" #endif #include #include #include "Camera.h" #include "Camera2Reader.h" #include "GPIOControl.h" #ifdef USING_BREAK_PAD bool DumpCallback(const google_breakpad::MinidumpDescriptor& descriptor, void* context, bool succeeded) { LOGE("Dump path: %s\n", descriptor.path()); return succeeded; } #endif #ifdef USING_NRSEC #include #endif static jmethodID mRegisterTimerMid = 0; static jmethodID mRegisterHeartbeatMid = 0; static jmethodID mUnregisterTimerMid = 0; static jmethodID mUpdateTimeMid = 0; static jmethodID mRequestWakelockMid = 0; static jmethodID mReleaseWakelockMid = 0; static jmethodID mGetSystemInfoMid = 0; static jmethodID mRebootMid = 0; static jmethodID mEnableGpsMid = 0; static jmethodID mRequestPositionMid = 0; static jmethodID mWriteLogMid = 0; void posix_signal_handler(int sig, siginfo_t *siginfo, void *context) { (void)context; switch(sig) { case SIGSEGV: fputs("Caught SIGSEGV: Segmentation Fault\n", stderr); break; case SIGINT: fputs("Caught SIGINT: Interactive attention signal, (usually ctrl+c)\n", stderr); break; case SIGFPE: switch(siginfo->si_code) { case FPE_INTDIV: fputs("Caught SIGFPE: (integer divide by zero)\n", stderr); break; case FPE_INTOVF: fputs("Caught SIGFPE: (integer overflow)\n", stderr); break; case FPE_FLTDIV: fputs("Caught SIGFPE: (floating-point divide by zero)\n", stderr); break; case FPE_FLTOVF: fputs("Caught SIGFPE: (floating-point overflow)\n", stderr); break; case FPE_FLTUND: fputs("Caught SIGFPE: (floating-point underflow)\n", stderr); break; case FPE_FLTRES: fputs("Caught SIGFPE: (floating-point inexact result)\n", stderr); break; case FPE_FLTINV: fputs("Caught SIGFPE: (floating-point invalid operation)\n", stderr); break; case FPE_FLTSUB: fputs("Caught SIGFPE: (subscript out of range)\n", stderr); break; default: fputs("Caught SIGFPE: Arithmetic Exception\n", stderr); break; } case SIGILL: switch(siginfo->si_code) { case ILL_ILLOPC: fputs("Caught SIGILL: (illegal opcode)\n", stderr); break; case ILL_ILLOPN: fputs("Caught SIGILL: (illegal operand)\n", stderr); break; case ILL_ILLADR: fputs("Caught SIGILL: (illegal addressing mode)\n", stderr); break; case ILL_ILLTRP: fputs("Caught SIGILL: (illegal trap)\n", stderr); break; case ILL_PRVOPC: fputs("Caught SIGILL: (privileged opcode)\n", stderr); break; case ILL_PRVREG: fputs("Caught SIGILL: (privileged register)\n", stderr); break; case ILL_COPROC: fputs("Caught SIGILL: (coprocessor error)\n", stderr); break; case ILL_BADSTK: fputs("Caught SIGILL: (internal stack error)\n", stderr); break; default: fputs("Caught SIGILL: Illegal Instruction\n", stderr); break; } break; case SIGTERM: fputs("Caught SIGTERM: a termination request was sent to the program\n", stderr); break; case SIGABRT: fputs("Caught SIGABRT: usually caused by an abort() or assert()\n", stderr); break; default: break; } _Exit(1); } class Runner { public: static void RequestCapture(CTerminal* pTerminal, unsigned int channel, unsigned int preset, unsigned int type, unsigned long scheduleTime); }; void Runner::RequestCapture(CTerminal* pTerminal, unsigned int channel, unsigned int preset, unsigned int type, unsigned long scheduleTime) { pTerminal->RequestCapture(channel, preset, type, scheduleTime); } jint JNI_OnLoad(JavaVM* vm, void* reserved) { JNIEnv* env = NULL; jint result = -1; #if defined(JNI_VERSION_1_6) if (result==-1 && vm->GetEnv((void**)&env, JNI_VERSION_1_6) == JNI_OK) { result = JNI_VERSION_1_6; } #endif #if defined(JNI_VERSION_1_4) if (result==-1 && vm->GetEnv((void**)&env, JNI_VERSION_1_4) == JNI_OK) { result = JNI_VERSION_1_4; } #endif #if defined(JNI_VERSION_1_2) if (result==-1 && vm->GetEnv((void**)&env, JNI_VERSION_1_2) == JNI_OK) { result = JNI_VERSION_1_2; } #endif if(result == -1 || env == NULL) { return JNI_FALSE; } #ifdef USING_BREAK_PAD google_breakpad::MinidumpDescriptor descriptor("/sdcard/Android/data/com.xypower.mpapp/files/logs/"); google_breakpad::ExceptionHandler eh(descriptor, NULL, DumpCallback, NULL, true, -1); #endif #if 0 { struct sigaction sig_action = {}; sig_action.sa_sigaction = posix_signal_handler; sigemptyset(&sig_action.sa_mask); #ifdef __APPLE__ /* for some reason we backtrace() doesn't work on osx when we use an alternate stack */ sig_action.sa_flags = SA_SIGINFO; #else sig_action.sa_flags = SA_SIGINFO | SA_ONSTACK; #endif if (sigaction(SIGSEGV, &sig_action, NULL) != 0) { // err(1, "sigaction"); int aa = 0; } } const char* className = "com/xypower/mpapp/MicroPhotoService"; jclass clazz = (env)->FindClass(className); // if((env)->RegisterNatives(clazz, gMethods, 1)< 0) { // return -1; // } env->DeleteLocalRef(clazz); #endif return result; } bool GetJniEnv(JavaVM *vm, JNIEnv **env, bool& didAttachThread) { didAttachThread = false; *env = nullptr; // Check if the current thread is attached to the VM auto get_env_result = vm->GetEnv((void**)env, JNI_VERSION_1_6); if (get_env_result == JNI_EDETACHED) { get_env_result = vm->AttachCurrentThread(env, NULL); if (get_env_result == JNI_OK) { didAttachThread = true; } else { // Failed to attach thread. Throw an exception if you want to. } } else if (get_env_result == JNI_EVERSION) { // Unsupported JNI version. Throw an exception if you want to. } return get_env_result == JNI_OK; } extern "C" JNIEXPORT jboolean JNICALL Java_com_xypower_mpapp_MainActivity_takePhoto( JNIEnv* env, jobject pThis, jint channel, jint preset, jstring path, jstring fileName) { if (channel < 1 || channel > 0xFF) { return JNI_FALSE; } unsigned char id = (unsigned char)channel - 1; Camera2Reader *camera = new Camera2Reader(id); const char *pathStr = env->GetStringUTFChars(path, 0); const char *fileNameStr = env->GetStringUTFChars(fileName, 0); camera->Open(pathStr, fileNameStr); env->ReleaseStringUTFChars(fileName, fileNameStr); env->ReleaseStringUTFChars(path, pathStr); camera->start(); return JNI_TRUE; } extern "C" JNIEXPORT jlong JNICALL Java_com_xypower_mpapp_MicroPhotoService_init( JNIEnv* env, jobject pThis, jstring appPath, jstring ip, jint port, jstring cmdid, jint protocol, jint networkProtocol, jint encryptData, jlong netHandle, jint signalLevel, jint versionCode, jlong buildTime, jstring simcard, jstring tfCardPath, jstring nativeLibraryDir) { /* google_breakpad::MinidumpDescriptor descriptor("."); google_breakpad::ExceptionHandler eh(descriptor, NULL, NULL, NULL, true, -1); */ if (netHandle != NETID_UNSET) { net_handle_t nh = (net_handle_t)netHandle; android_setprocnetwork(nh); } char model[PROP_VALUE_MAX] = { 0 }; __system_property_get("ro.product.model", model); jclass classService = env->GetObjectClass(pThis); jfieldID fieldId = env->GetFieldID(classService, "mModelName", "Ljava/lang/String;"); env->DeleteLocalRef(classService); jstring modelName = env->NewStringUTF(model); env->SetObjectField(pThis, fieldId, modelName); bool udpOrTcp = (networkProtocol != 0); // 0: tcp const char *appPathStr = appPath == NULL ? NULL : env->GetStringUTFChars(appPath, 0); const char *ipStr = ip == NULL ? NULL : env->GetStringUTFChars(ip, 0); const char *cmdidStr = cmdid == NULL ? NULL : env->GetStringUTFChars(cmdid, 0); const char *simcardStr = simcard == NULL ? NULL : env->GetStringUTFChars(simcard, 0); const char *tfCardPathStr = tfCardPath == NULL ? NULL : env->GetStringUTFChars(tfCardPath, 0); const char *nativeLibraryDirStr = nativeLibraryDir == NULL ? NULL : env->GetStringUTFChars(nativeLibraryDir, 0); JavaVM* vm = NULL; jint ret = env->GetJavaVM(&vm); // const string& appPath, const string& termId, const string& server, unsigned short port, const string& bindIp // CTerminal* pTerminal = reinterpret_cast(handler); // CTerminalDevice* device = new CTerminalDevice(vm, pThis); // CPhoneDevice2* device = new CPhoneDevice2(vm, pThis); CTerminal* pTerminal = NewTerminal(protocol); CPhoneDevice* device = new CPhoneDevice(vm, pThis, MakeString(appPathStr), NETID_UNSET, versionCode, MakeString(nativeLibraryDirStr)); device->SetListener(pTerminal); device->UpdateSignalLevel(signalLevel); device->SetBuildTime(buildTime / 1000); device->UpdateSimcard(MakeString(simcardStr)); device->UpdateTfCardPath(MakeString(tfCardPathStr)); pTerminal->InitServerInfo(MakeString(appPathStr), MakeString(cmdidStr), MakeString(ipStr), port, udpOrTcp, encryptData); // pTerminal->SetPacketSize(1 * 1024); // 1K #if defined(USING_NRSEC) && !defined(USING_NRSEC_VPN) pTerminal->InitEncryptionInfo(simcardStr, "/dev/spidev0.0", ""); #endif bool res = pTerminal->Startup(device); if (appPathStr != NULL) env->ReleaseStringUTFChars(appPath, appPathStr); if (ipStr != NULL) env->ReleaseStringUTFChars(ip, ipStr); if (cmdidStr != NULL) env->ReleaseStringUTFChars(cmdid, cmdidStr); if (simcardStr != NULL) env->ReleaseStringUTFChars(simcard, simcardStr); if (tfCardPathStr != NULL) env->ReleaseStringUTFChars(tfCardPath, tfCardPathStr); if (nativeLibraryDirStr != NULL) env->ReleaseStringUTFChars(nativeLibraryDir, nativeLibraryDirStr); if (!res) { delete pTerminal; pTerminal = NULL; } return reinterpret_cast(pTerminal); } extern "C" JNIEXPORT jboolean JNICALL Java_com_xypower_mpapp_MicroPhotoService_notifyToTakePhoto( JNIEnv* env, jobject pThis, jlong handler, jint channel, jint preset, jlong scheduleTime, jboolean photoOrVideo) { if (channel < 1 || channel > 0xFF) { return JNI_FALSE; } CTerminal* pTerminal = reinterpret_cast(handler); if (pTerminal == NULL) { return JNI_FALSE; } unsigned char type = photoOrVideo ? 0 : 1; // std::thread th(&Runner::RequestCapture, pTerminal, (unsigned int)channel, (unsigned int)preset, type, (unsigned long)scheduleTime, 0, true); // th.detach(); pTerminal->RequestCapture((unsigned int)channel, (unsigned int)preset, type, (unsigned long)scheduleTime, 0, true); return JNI_TRUE; } extern "C" JNIEXPORT jlong JNICALL Java_com_xypower_mpapp_MicroPhotoService_takePhoto( JNIEnv* env, jclass cls, jint channel, jint preset, jboolean photoOrVideo, jstring configFilePath, jstring path) { if (channel < 1 || channel > 0xFF) { return 0; } JavaVM* vm = NULL; jint ret = env->GetJavaVM(&vm); std::string configFilePathStr = jstring2string(env, configFilePath); CFG_CHANNEL cfg; IDevice::PHOTO_INFO photoInfo(channel, preset); CTerminal::LoadChannelConfig(channel, configFilePathStr, cfg); CTerminal::ConvertChannelConfigToPhotoInfo(cfg, photoOrVideo != JNI_FALSE, photoInfo); CPhoneDevice* device = new CPhoneDevice(vm, NULL, "", NETID_UNSET, 0, std::string("")); // device->SetListener(pTerminal); if (photoInfo.usbCamera) { CPhoneDevice::TurnOnOtg(NULL); } CPhoneDevice::TurnOnCameraPower(NULL); std::vector osds; osds.resize(4); osds[1].alignment = IDevice::OSD_ALIGNMENT_TOP_RIGHT; osds[2].alignment = IDevice::OSD_ALIGNMENT_BOTTOM_RIGHT; osds[3].alignment = IDevice::OSD_ALIGNMENT_BOTTOM_LEFT; osds[0].text = cfg.osd.leftTop; osds[1].text = cfg.osd.rightTop; osds[2].text = cfg.osd.rightBottom; osds[3].text = cfg.osd.leftBottom; const char* pathStr = env->GetStringUTFChars(path, 0); device->TakePhoto(photoInfo, osds, MakeString(pathStr)); env->ReleaseStringUTFChars(path, pathStr); // device->TurnOffCameraPower(NULL); // if (photoInfo.usbCamera) //{ // device->TurnOffOtg(NULL); //} return reinterpret_cast(device); } extern "C" JNIEXPORT void JNICALL Java_com_xypower_mpapp_MicroPhotoService_releaseDeviceHandle( JNIEnv* env, jclass cls, jlong deviceHandle) { if (deviceHandle != 0) { CPhoneDevice* pDevice = reinterpret_cast(deviceHandle); delete pDevice; } } extern "C" JNIEXPORT jboolean JNICALL Java_com_xypower_mpapp_MicroPhotoService_sendHeartbeat( JNIEnv* env, jobject pThis, jlong handler, jint signalLevel) { CTerminal* pTerminal = reinterpret_cast(handler); if (pTerminal == NULL) { return JNI_FALSE; } CPhoneDevice* device = (CPhoneDevice*)pTerminal->GetDevice(); if (device != NULL) { device->UpdateSignalLevel(signalLevel); } pTerminal->SendHeartbeat(); return JNI_TRUE; } extern "C" JNIEXPORT void JNICALL Java_com_xypower_mpapp_MicroPhotoService_updatePosition( JNIEnv* env, jobject pThis, jlong handler, jdouble lon, jdouble lat, jdouble radius, jlong ts) { if (handler == 0) { return; } CTerminal* pTerminal = reinterpret_cast(handler); IDevice* dev = pTerminal->GetDevice(); if (dev == NULL) { return; } CPhoneDevice* phoneDevice = (CPhoneDevice *)dev; phoneDevice->UpdatePosition(lon, lat, radius, ts); } extern "C" JNIEXPORT jboolean JNICALL Java_com_xypower_mpapp_MicroPhotoService_uninit( JNIEnv* env, jobject pThis, jlong handler) { CTerminal* pTerminal = reinterpret_cast(handler); if (pTerminal == NULL) { return JNI_FALSE; } IDevice* dev = pTerminal->GetDevice(); if (dev != NULL) { ((CPhoneDevice *)dev)->CloseCamera(); } pTerminal->SignalExit(); pTerminal->Shutdown(); if (dev != NULL) { delete dev; } delete pTerminal; return JNI_TRUE; } extern "C" JNIEXPORT jlong JNICALL Java_com_xypower_mpapp_MicroPhotoService_getHeartbeatDuration( JNIEnv* env, jobject pThis, jlong handler) { CTerminal* pTerminal = reinterpret_cast(handler); if (pTerminal == NULL) { return DEFAULT_HEARTBEAT_DURATION; } return pTerminal->GetHeartbeatDuration(); } extern "C" JNIEXPORT jlongArray JNICALL Java_com_xypower_mpapp_MicroPhotoService_getPhotoTimeData2( JNIEnv* env, jobject pThis, jlong handler) { CTerminal* pTerminal = reinterpret_cast(handler); if (pTerminal == NULL) { return NULL; } map> photoTime; if (!pTerminal->GetPhotoTime(photoTime) || photoTime.empty()) { return NULL; } size_t numberOfData = photoTime.size() * photoTime.begin()->second.size(); if (numberOfData == 0) { return NULL; } vector dataArray; dataArray.reserve(numberOfData); unsigned long val = 0; jint channel = 0; for (map>::const_iterator it = photoTime.cbegin(); it != photoTime.cend(); ++it) { if (it->second.empty()) { continue; } channel = (jint)((unsigned short)it->first); // dataArray.push_back(channel); // val = (jint)it->second.size(); // dataArray.push_back(val); for (vector::const_iterator it2 = it->second.cbegin(); it2 != it->second.cend(); ++it2) { // time val = ((unsigned long)((*it2) & 0xFFFFFF00)) << 24; // channel val |= ((unsigned long)channel) << 16; // preset val |= ((unsigned long)((*it2) & 0xFF)) << 8; dataArray.push_back((jlong)val); } } std::sort(dataArray.begin(), dataArray.end()); jlongArray data = env->NewLongArray(dataArray.size()); if (data == NULL) { return NULL; } env->SetLongArrayRegion(data, 0, dataArray.size(), &dataArray[0]); return data; } extern "C" JNIEXPORT jlongArray JNICALL Java_com_xypower_mpapp_MicroPhotoService_getPhotoTimeData( JNIEnv* env, jobject pThis, jlong handler, jlong startTime) { CTerminal* pTerminal = reinterpret_cast(handler); if (pTerminal == NULL) { return NULL; } unsigned int scheduleTime = 0; time_t zeroPointTime = 0; std::vector > channelsAndPresets; if (!pTerminal->GetAndRefreshLatestScheduleTime(startTime, zeroPointTime, scheduleTime, channelsAndPresets)) { return NULL; } if (channelsAndPresets.empty()) { return NULL; } vector dataArray; dataArray.reserve(channelsAndPresets.size() + 3); dataArray.push_back((jlong)zeroPointTime); dataArray.push_back((jlong)scheduleTime); dataArray.push_back((jlong)channelsAndPresets.size()); unsigned long val = 0; for (std::vector >::const_iterator it = channelsAndPresets.cbegin(); it != channelsAndPresets.cend(); ++it) { val = (unsigned long)scheduleTime << 24; // channel val |= ((unsigned long)(it->first)) << 16; // preset val |= ((unsigned long)(it->second)) << 8; dataArray.push_back((jlong)val); } jlongArray data = env->NewLongArray(dataArray.size()); if (data == NULL) { return NULL; } env->SetLongArrayRegion(data, 0, dataArray.size(), &dataArray[0]); return data; } extern "C" JNIEXPORT jintArray JNICALL Java_com_xypower_mpapp_MicroPhotoService_recoganizePicture( JNIEnv* env, jclass cls, jstring paramPath, jstring binPath, jstring blobName8, jstring blobName16, jstring blobName32, jstring picPath) { const char* pParamPathStr = env->GetStringUTFChars(paramPath, 0); std::string paramPathStr = MakeString(pParamPathStr); env->ReleaseStringUTFChars(paramPath, pParamPathStr); const char* pBinPathStr = env->GetStringUTFChars(binPath, 0); std::string binPathStr = MakeString(pBinPathStr); env->ReleaseStringUTFChars(binPath, pBinPathStr); const char* pBlobName8Str = env->GetStringUTFChars(blobName8, 0); std::string blobName8Str = MakeString(pBlobName8Str); env->ReleaseStringUTFChars(blobName8, pBlobName8Str); const char* pBlobName16Str = env->GetStringUTFChars(blobName16, 0); std::string blobName16Str = MakeString(pBlobName16Str); env->ReleaseStringUTFChars(blobName16, pBlobName16Str); const char* pBlobName32Str = env->GetStringUTFChars(blobName32, 0); std::string blobName32Str = MakeString(pBlobName32Str); env->ReleaseStringUTFChars(blobName32, pBlobName32Str); const char* pPicPathStr = env->GetStringUTFChars(picPath, 0); std::string picPathStr = MakeString(pPicPathStr); env->ReleaseStringUTFChars(picPath, pPicPathStr); cv::Mat mat = cv::imread(picPathStr); if (mat.empty()) { return NULL; } std::vector dataArray; ncnn_init(); ncnn::Net net; bool res = YoloV5Ncnn_Init(net, paramPathStr, binPathStr); if (res) { std::vector objs; res = YoloV5NcnnDetect(net, mat, true, blobName8Str, blobName16Str, blobName32Str, objs); if (res && !objs.empty()) { for (std::vector::const_iterator it = objs.cbegin(); it != objs.cend(); ++it) { // float x; // float y; // float w; // float h; // int label; // float prob; dataArray.push_back(it->x); dataArray.push_back(it->y); dataArray.push_back(it->w); dataArray.push_back(it->h); dataArray.push_back(it->label); dataArray.push_back((int)(it->prob * 100.0f)); } } } // ncnn_uninit(); if (dataArray.empty()) { return NULL; } jintArray data = env->NewIntArray(dataArray.size()); if (data == NULL) { return NULL; } env->SetIntArrayRegion(data, 0, dataArray.size(), &dataArray[0]); return data; } /* extern "C" JNIEXPORT jlongArray JNICALL Java_com_xypower_mpapp_MicroPhotoService_getNextScheduleItem( JNIEnv* env, jobject pThis, jlong handler) { CTerminal* pTerminal = reinterpret_cast(handler); if (pTerminal == NULL) { return NULL; } map> photoTime; if (!pTerminal->GetPhotoTime(photoTime) || photoTime.empty()) { return NULL; } size_t numberOfData = photoTime.size() * photoTime.begin()->second.size(); if (numberOfData == 0) { return NULL; } vector dataArray; dataArray.reserve(numberOfData); unsigned long val = 0; jint channel = 0; for (map>::const_iterator it = photoTime.cbegin(); it != photoTime.cend(); ++it) { if (it->second.empty()) { continue; } channel = (jint)((unsigned short)it->first); // dataArray.push_back(channel); // val = (jint)it->second.size(); // dataArray.push_back(val); for (vector::const_iterator it2 = it->second.cbegin(); it2 != it->second.cend(); ++it2) { // time val = ((unsigned long)((*it2) & 0xFFFFFF00)) << 24; // channel val |= ((unsigned long)channel) << 16; // preset val |= ((unsigned long)((*it2) & 0xFF)) << 8; dataArray.push_back((jlong)val); } } std::sort(dataArray.begin(), dataArray.end()); jlongArray data = env->NewLongArray(dataArray.size()); if (data == NULL) { return NULL; } env->SetLongArrayRegion(data, 0, dataArray.size(), &dataArray[0]); return data; } */ extern "C" JNIEXPORT void JNICALL Java_com_xypower_mpapp_MicroPhotoService_captureFinished( JNIEnv* env, jobject pThis, jlong handler, jboolean photoOrVideo, jboolean result, jobject bitmap, jlong photoId) { CTerminal* pTerminal = reinterpret_cast(handler); if (pTerminal == NULL) { return; } IDevice* dev = pTerminal->GetDevice(); if (dev != NULL) { if (result == JNI_FALSE || bitmap == NULL) { cv::Mat mat; ((CPhoneDevice *)dev)->OnCaptureReady(photoOrVideo != JNI_FALSE, result != JNI_FALSE, mat, (unsigned long)photoId); return; } AndroidBitmapInfo info = { 0 }; int res = AndroidBitmap_getInfo(env, bitmap, &info); if (res < 0 || info.format != ANDROID_BITMAP_FORMAT_RGBA_8888) { } bool hardwareBitmap = (info.flags & ANDROID_BITMAP_FLAGS_IS_HARDWARE) != 0; void* pixels = NULL; AHardwareBuffer* hardwareBuffer = NULL; if (hardwareBitmap) { #if 0 res = AndroidBitmap_getHardwareBuffer(env, bitmap, &hardwareBuffer); int32_t fence = -1; res = AHardwareBuffer_lock(hardwareBuffer, AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN, fence, NULL, &pixels); cv::Mat mat(info.height, info.width, CV_8UC4, pixels); AHardwareBuffer_unlock(hardwareBuffer, &fence); cv::cvtColor(mat, mat, cv::COLOR_RGB2BGR); ((CPhoneDevice *)dev)->OnCaptureReady(photoOrVideo != JNI_FALSE, result != JNI_FALSE, mat, (unsigned long)photoId); #endif // 0 } else { res = AndroidBitmap_lockPixels(env, bitmap, &pixels); cv::Mat tmp(info.height, info.width, CV_8UC4, pixels); cv::Mat raw(info.height, info.width, CV_8UC4); // tmp.copyTo(mat); cv::cvtColor(tmp, raw, cv::COLOR_RGBA2BGR); cv::Mat mat; cv::fastNlMeansDenoisingColored(raw, mat, 13, 13, 7, 21); AndroidBitmap_unlockPixels(env, bitmap); ((CPhoneDevice *)dev)->OnCaptureReady(photoOrVideo != JNI_FALSE, result != JNI_FALSE, mat, (unsigned long)photoId); } } } extern "C" JNIEXPORT void JNICALL Java_com_xypower_mpapp_MicroPhotoService_burstCaptureFinished( JNIEnv* env, jobject pThis, jlong handler, jboolean result, jint numberOfCaptures, jstring pathsJoinedByTab, jboolean frontCamera, jint rotation, jlong photoId) { CTerminal* pTerminal = reinterpret_cast(handler); if (pTerminal == NULL) { return; } /// HDRPlus #ifdef USING_HDRPLUS #endif IDevice* dev = pTerminal->GetDevice(); if (dev != NULL) { if (result == JNI_FALSE) { cv::Mat mat; ((CPhoneDevice *)dev)->OnCaptureReady(true, false, mat, (unsigned long)photoId); return; } const char* pathsStr = env->GetStringUTFChars(pathsJoinedByTab, 0); ((CPhoneDevice *)dev)->ProcessRawCapture(result != JNI_FALSE, numberOfCaptures, MakeString(pathsStr), frontCamera != JNI_FALSE, rotation, photoId); env->ReleaseStringUTFChars(pathsJoinedByTab, pathsStr); } } extern "C" JNIEXPORT void JNICALL Java_com_xypower_mpapp_MicroPhotoService_recordingFinished( JNIEnv* env, jobject pThis, jlong handler, jboolean photoOrVideo, jboolean result, jstring path, jlong videoId) { CTerminal* pTerminal = reinterpret_cast(handler); if (pTerminal == NULL) { return; } IDevice* dev = pTerminal->GetDevice(); if (dev != NULL) { const char *pathStr = NULL; if (path != NULL) { pathStr = env->GetStringUTFChars(path, 0); } // camera->Open(pathStr, fileNameStr); unsigned long photoId = videoId; ((CPhoneDevice *)dev)->OnVideoReady(photoOrVideo != JNI_FALSE, result != JNI_FALSE, pathStr, photoId); if (path != NULL) { env->ReleaseStringUTFChars(path, pathStr); } } } extern "C" JNIEXPORT jboolean JNICALL Java_com_xypower_mpapp_MicroPhotoService_reloadConfigs( JNIEnv* env, jobject pThis, jlong handler) { CTerminal* pTerminal = reinterpret_cast(handler); if (pTerminal == NULL) { return JNI_FALSE; } bool res = pTerminal->LoadAppConfigs(); return res ? JNI_TRUE : JNI_FALSE; } extern "C" JNIEXPORT jboolean JNICALL Java_com_xypower_mpapp_MicroPhotoService_sendExternalPhoto( JNIEnv* env, jclass cls, jlong handler, jstring path) { CTerminal* pTerminal = reinterpret_cast(handler); if (pTerminal == NULL) { return JNI_FALSE; } if (env->GetStringUTFLength(path) <=0) { return JNI_FALSE; } const char *pathStr = env->GetStringUTFChars(path, 0); bool res = pTerminal->SendExternalPhoto(pathStr); env->ReleaseStringUTFChars(path, pathStr); return res ? JNI_TRUE : JNI_FALSE; } extern "C" JNIEXPORT void JNICALL Java_com_xypower_mpapp_MicroPhotoService_infoLog( JNIEnv* env, jclass cls, jstring msg) { if (env->GetStringUTFLength(msg) <=0) { return; } const char *msgStr = env->GetStringUTFChars(msg, 0); XYLOG(XYLOG_SEVERITY_INFO, msgStr); env->ReleaseStringUTFChars(msg, msgStr); } extern "C" JNIEXPORT void JNICALL Java_com_xypower_mpapp_MicroPhotoService_setOtgState( JNIEnv* env, jclass cls, jboolean enabled) { GpioControl::setOtgState(enabled != JNI_FALSE); } extern "C" JNIEXPORT void JNICALL Java_com_xypower_mpapp_MicroPhotoService_setCam3V3Enable( JNIEnv* env, jclass cls, jboolean enabled) { GpioControl::setCam3V3Enable(enabled != JNI_FALSE); } extern "C" JNIEXPORT jstring JNICALL Java_com_xypower_mpapp_MicroPhotoService_getSerialNumber( JNIEnv* env, jclass cls) { char value[PROP_VALUE_MAX] = { 0 }; __system_property_get("ro.serialno", value); return env->NewStringUTF(value); } extern "C" JNIEXPORT jboolean JNICALL Java_com_xypower_mpapp_MicroPhotoService_importPublicKeyFile( JNIEnv* env, jclass cls, jint index, jstring outputPath, jstring md5) { #ifdef USING_NRSEC if (env->GetStringUTFLength(outputPath) <=0) { return JNI_FALSE; } const char *outputPathStr = env->GetStringUTFChars(outputPath, 0); std::vector data; bool res = readFile(outputPathStr, data); env->ReleaseStringUTFChars(outputPath, outputPathStr); if (!res || data.empty()) { return JNI_FALSE; } const char *md5Str = env->GetStringUTFChars(md5, 0); GpioControl::setSpiPower(false); CPhoneDevice::TurnOnCameraPower(NULL); GpioControl::setSpiPower(true); NrsecPort nrsec; const char *path = NRSEC_PATH; res = nrsec.Open(path); if (res) { res = nrsec.SM2ImportPublicKey(index, &data[0]) == 0; nrsec.Close(); } GpioControl::setSpiPower(false); CPhoneDevice::TurnOffCameraPower(NULL); env->ReleaseStringUTFChars(md5, md5Str); return res ? JNI_TRUE : JNI_FALSE; #else return JNI_FALSE; #endif } extern "C" JNIEXPORT jboolean JNICALL Java_com_xypower_mpapp_MicroPhotoService_importPublicKey( JNIEnv* env, jclass cls, jint index, jbyteArray cert) { #ifdef USING_NRSEC int byteCertLen = env->GetArrayLength(cert); if (byteCertLen <= 0) { return JNI_FALSE; } GpioControl::setSpiPower(false); CPhoneDevice::TurnOnCameraPower(NULL); GpioControl::setSpiPower(true); NrsecPort nrsec; const char *path = NRSEC_PATH; bool res = nrsec.Open(path); if (res) { jbyte* byteCert = env->GetByteArrayElements(cert, 0); res = nrsec.SM2ImportPublicKey(index, (const uint8_t*)byteCert) == 0; nrsec.Close(); env->ReleaseByteArrayElements(cert, byteCert, JNI_ABORT); } GpioControl::setSpiPower(false); CPhoneDevice::TurnOffCameraPower(NULL); return res ? JNI_TRUE : JNI_FALSE; #else return JNI_FALSE; #endif } extern "C" JNIEXPORT jboolean JNICALL Java_com_xypower_mpapp_MicroPhotoService_importPrivateKey( JNIEnv* env, jclass cls, jint index, jbyteArray cert) { #ifdef USING_NRSEC int byteCertLen = env->GetArrayLength(cert); if (byteCertLen <= 0) { return JNI_FALSE; } GpioControl::setSpiPower(false); CPhoneDevice::TurnOnCameraPower(NULL); GpioControl::setSpiPower(true); NrsecPort nrsec; const char *path = NRSEC_PATH; bool res = nrsec.Open(path); if (res) { jbyte* byteCert = env->GetByteArrayElements(cert, 0); res = nrsec.SM2ImportPrivateKey(index, (const uint8_t*)byteCert) == 0; nrsec.Close(); env->ReleaseByteArrayElements(cert, byteCert, JNI_ABORT); } GpioControl::setSpiPower(false); CPhoneDevice::TurnOffCameraPower(NULL); return res ? JNI_TRUE : JNI_FALSE; #else return JNI_FALSE; #endif } extern "C" JNIEXPORT jint JNICALL Java_com_xypower_mpapp_MicroPhotoService_getGpioInt( JNIEnv* env, jclass cls, jint cmd) { return GpioControl::getInt(cmd); } extern "C" JNIEXPORT jboolean JNICALL Java_com_xypower_mpapp_MicroPhotoService_genKeys( JNIEnv* env, jclass cls, jint index) { #ifdef USING_NRSEC GpioControl::setSpiPower(false); CPhoneDevice::TurnOnCameraPower(NULL); GpioControl::setSpiPower(true); const char *path = NRSEC_PATH; NrsecPort nrsec; bool res = nrsec.Open(path); if (res) { res = nrsec.SM2keypair(index) == 0; nrsec.Close(); } GpioControl::setSpiPower(false); CPhoneDevice::TurnOffCameraPower(NULL); return res ? JNI_TRUE : JNI_FALSE; #else return JNI_FALSE; #endif } extern "C" JNIEXPORT jstring JNICALL Java_com_xypower_mpapp_MicroPhotoService_querySecVersion( JNIEnv* env, jclass cls) { std::string version; #ifdef USING_NRSEC GpioControl::setSpiPower(false); CPhoneDevice::TurnOnCameraPower(NULL); GpioControl::setSpiPower(true); const char *path = NRSEC_PATH; NrsecPort nrsec; bool res = nrsec.Open(path); if (res) { version = nrsec.Version(); nrsec.Close(); } GpioControl::setSpiPower(false); CPhoneDevice::TurnOffCameraPower(NULL); #endif return env->NewStringUTF(version.c_str()); } extern "C" JNIEXPORT jboolean JNICALL Java_com_xypower_mpapp_MicroPhotoService_genCertRequest( JNIEnv* env, jclass cls, jint index, jint type, jstring subject, jstring outputPath) { #ifdef USING_NRSEC if (env->GetStringUTFLength(subject) <=0 || env->GetStringUTFLength(outputPath) <=0) { return JNI_FALSE; } const char *path = NRSEC_PATH; GpioControl::setSpiPower(false); CPhoneDevice::TurnOnCameraPower(NULL); GpioControl::setSpiPower(true); uint8_t output[1024] = { 0 }; uint16_t len = 0; NrsecPort nrsec; bool res = nrsec.Open(path); if (res) { const char* subjectStr = env->GetStringUTFChars(subject, 0); res = nrsec.SM2cert(type, index, MakeString(subjectStr), output, &len) == 0; nrsec.Close(); env->ReleaseStringUTFChars(subject, subjectStr); } GpioControl::setSpiPower(false); CPhoneDevice::TurnOffCameraPower(NULL); if (res) { const char* outputPathStr = env->GetStringUTFChars(outputPath, 0); res = writeFile(outputPathStr, output, len); env->ReleaseStringUTFChars(outputPath, outputPathStr); } return res ? JNI_TRUE : JNI_FALSE; #else return JNI_FALSE; #endif } extern "C" JNIEXPORT jboolean JNICALL Java_com_xypower_mpapp_MicroPhotoService_importPrivateKeyFile( JNIEnv* env, jclass cls, jint index, jstring keyFilePath, jstring md5) { #ifdef USING_NRSEC if (env->GetStringUTFLength(keyFilePath) <= 0) { return JNI_FALSE; } bool res = false; std::vector data; const char *keyFilePathStr = env->GetStringUTFChars(keyFilePath, 0); res = readFile(keyFilePathStr, data); env->ReleaseStringUTFChars(keyFilePath, keyFilePathStr); if (!res || data.empty()) { return JNI_FALSE; } const char *path = NRSEC_PATH; GpioControl::setSpiPower(false); CPhoneDevice::TurnOnCameraPower(NULL); GpioControl::setSpiPower(true); NrsecPort nrsec; res = nrsec.Open(path); if (res) { res = nrsec.SM2ImportPrivateKey(index, &data[0]) == 0; nrsec.Close(); } GpioControl::setSpiPower(false); CPhoneDevice::TurnOffCameraPower(NULL); // const char *md5Str = env->GetStringUTFChars(md5, 0); // env->ReleaseStringUTFChars(md5, md5Str); return res ? JNI_TRUE : JNI_FALSE; #else return JNI_FALSE; #endif } extern "C" JNIEXPORT jboolean JNICALL Java_com_xypower_mpapp_MicroPhotoService_exportPublicKeyFile( JNIEnv* env, jclass cls, jint index, jstring outputPath) { #ifdef USING_NRSEC if (env->GetStringUTFLength(outputPath) <= 0) { return JNI_FALSE; } const char *path = NRSEC_PATH; uint8_t len = 0; std::vector data(64, 0); GpioControl::setSpiPower(false); CPhoneDevice::TurnOnCameraPower(NULL); GpioControl::setSpiPower(true); NrsecPort nrsec; bool res = nrsec.Open(path); if (res) { res = nrsec.SM2ExportPublicKey(index, &data[0], &len) == 0; nrsec.Close(); } GpioControl::setSpiPower(false); CPhoneDevice::TurnOffCameraPower(NULL); if (res) { const char* outputPathStr = env->GetStringUTFChars(outputPath, 0); res = writeFile(outputPathStr, &data[0], len); env->ReleaseStringUTFChars(outputPath, outputPathStr); } return res ? JNI_TRUE : JNI_FALSE; #else return JNI_FALSE; #endif } extern "C" JNIEXPORT jboolean JNICALL Java_com_xypower_mpapp_MicroPhotoService_exportPrivateFile( JNIEnv* env, jclass cls, jint index, jstring outputPath) { #ifdef USING_NRSEC if (env->GetStringUTFLength(outputPath) <= 0) { return JNI_FALSE; } const char *path = NRSEC_PATH; GpioControl::setSpiPower(false); CPhoneDevice::TurnOnCameraPower(NULL); GpioControl::setSpiPower(true); NrsecPort nrsec; if (!nrsec.Open(path)) { return JNI_FALSE; } bool res = false; std::vector data(64, 0); uint8_t len = 0; res = nrsec.SM2ExportPrivateKey(index, &data[0], &len) == 0; nrsec.Close(); GpioControl::setSpiPower(false); CPhoneDevice::TurnOffCameraPower(NULL); if (res) { const char *outputPathStr = env->GetStringUTFChars(outputPath, 0); res = writeFile(outputPathStr, &data[0], len); env->ReleaseStringUTFChars(outputPath, outputPathStr); } return res ? JNI_TRUE : JNI_FALSE; #else return JNI_FALSE; #endif }