You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
TermApp/app/src/main/cpp/MicroPhoto.cpp

668 lines
19 KiB
C++

#include <jni.h>
#include <string>
#include <thread>
2 years ago
#include <Factory.h>
#include <Client/Terminal.h>
#include "TerminalDevice.h"
#include "PhoneDevice.h"
#include "PhoneDevice2.h"
#include <sys/system_properties.h>
#include <android/multinetwork.h>
#ifdef USING_BREAK_PAD
#include "client/linux/handler/exception_handler.h"
#include "client/linux/handler/minidump_descriptor.h"
#endif
#include <android/native_window.h>
#include <android/native_window_jni.h>
#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
2 years ago
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);
}
2 years ago
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
{
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;
}
}
2 years ago
const char* className = "com/xypower/mpapp/MicroPhotoService";
jclass clazz = (env)->FindClass(className);
// if((env)->RegisterNatives(clazz, gMethods, 1)< 0) {
// return -1;
// }
env->DeleteLocalRef(clazz);
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;
}
2 years ago
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, jlong netHandle, jint signalLevel, jint versionCode) {
/*
google_breakpad::MinidumpDescriptor descriptor(".");
google_breakpad::ExceptionHandler eh(descriptor, NULL, NULL,
NULL, true, -1);
*/
1 year ago
if (netHandle != NETID_UNSET) {
net_handle_t nh = (net_handle_t)netHandle;
1 year ago
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);
2 years ago
bool udpOrTcp = (networkProtocol != 0); // 0: tcp
const char *appPathStr = env->GetStringUTFChars(appPath, 0);
const char *ipStr = env->GetStringUTFChars(ip, 0);
const char *cmdidStr = env->GetStringUTFChars(cmdid, 0);
JavaVM* vm = NULL;
jint ret = env->GetJavaVM(&vm);
// const string& appPath, const string& termId, const string& server, unsigned short port, const string& bindIp
2 years ago
// CTerminal* pTerminal = reinterpret_cast<CTerminal *>(handler);
// CTerminalDevice* device = new CTerminalDevice(vm, pThis);
// CPhoneDevice2* device = new CPhoneDevice2(vm, pThis);
2 years ago
2 years ago
CTerminal* pTerminal = NewTerminal(protocol);
2 years ago
CPhoneDevice* device = new CPhoneDevice(vm, pThis, appPathStr, NETID_UNSET, versionCode);
2 years ago
device->SetListener(pTerminal);
device->UpdateSignalLevel(signalLevel);
2 years ago
2 years ago
pTerminal->InitServerInfo(appPathStr, cmdidStr, ipStr, port, udpOrTcp);
// pTerminal->SetPacketSize(1 * 1024); // 1K
2 years ago
bool res = pTerminal->Startup(device);
env->ReleaseStringUTFChars(appPath, appPathStr);
env->ReleaseStringUTFChars(ip, ipStr);
env->ReleaseStringUTFChars(cmdid, cmdidStr);
if (!res)
{
delete pTerminal;
pTerminal = NULL;
}
2 years ago
return reinterpret_cast<jlong>(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;
}
2 years ago
CTerminal* pTerminal = reinterpret_cast<CTerminal *>(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);
th.detach();
// pTerminal->RequestCapture((unsigned int)channel, (unsigned int)preset, 0, (unsigned long)scheduleTime);
return JNI_TRUE;
}
extern "C" JNIEXPORT jboolean JNICALL
Java_com_xypower_mpapp_MicroPhotoService_sendHeartbeat(
JNIEnv* env,
2 years ago
jobject pThis,
jlong handler, jint signalLevel) {
2 years ago
CTerminal* pTerminal = reinterpret_cast<CTerminal *>(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, jlong ts) {
CTerminal* pTerminal = reinterpret_cast<CTerminal *>(handler);
IDevice* dev = pTerminal->GetDevice();
if (dev == NULL)
{
return;
}
CPhoneDevice* phoneDevice = (CPhoneDevice *)dev;
phoneDevice->UpdatePosition(lon, lat, ts);
}
extern "C" JNIEXPORT jboolean JNICALL
Java_com_xypower_mpapp_MicroPhotoService_uninit(
JNIEnv* env,
2 years ago
jobject pThis, jlong handler) {
CTerminal* pTerminal = reinterpret_cast<CTerminal *>(handler);
2 years ago
if (pTerminal == NULL)
{
return JNI_FALSE;
}
IDevice* dev = pTerminal->GetDevice();
if (dev != NULL)
{
((CPhoneDevice *)dev)->CloseCamera();
}
2 years ago
pTerminal->SignalExit();
2 years ago
pTerminal->Shutdown();
2 years ago
delete pTerminal;
return JNI_TRUE;
}
extern "C" JNIEXPORT jlong JNICALL
Java_com_xypower_mpapp_MicroPhotoService_getHeartbeatDuration(
JNIEnv* env,
2 years ago
jobject pThis, jlong handler) {
CTerminal* pTerminal = reinterpret_cast<CTerminal *>(handler);
if (pTerminal == NULL)
{
return DEFAULT_HEARTBEAT_DURATION;
}
return pTerminal->GetHeartbeatDuration();
}
extern "C" JNIEXPORT jlongArray JNICALL
Java_com_xypower_mpapp_MicroPhotoService_getPhotoTimeData2(
JNIEnv* env,
2 years ago
jobject pThis, jlong handler) {
2 years ago
CTerminal* pTerminal = reinterpret_cast<CTerminal *>(handler);
if (pTerminal == NULL)
{
return NULL;
}
map<unsigned char, vector<unsigned int>> photoTime;
if (!pTerminal->GetPhotoTime(photoTime) || photoTime.empty())
{
return NULL;
}
size_t numberOfData = photoTime.size() * photoTime.begin()->second.size();
if (numberOfData == 0)
{
return NULL;
}
vector<jlong> dataArray;
dataArray.reserve(numberOfData);
unsigned long val = 0;
jint channel = 0;
for (map<unsigned char, vector<unsigned int>>::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<unsigned int>::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<CTerminal *>(handler);
if (pTerminal == NULL)
{
return NULL;
}
unsigned int scheduleTime = 0;
time_t zeroPointTime = 0;
std::vector<std::pair<unsigned char, unsigned char> > channelsAndPresets;
if (!pTerminal->GetAndRefreshLatestScheduleTime(startTime, zeroPointTime, scheduleTime, channelsAndPresets))
{
return NULL;
}
if (channelsAndPresets.empty())
{
return NULL;
}
vector<jlong> 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<std::pair<unsigned char, unsigned char> >::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 jlongArray JNICALL
Java_com_xypower_mpapp_MicroPhotoService_getNextScheduleItem(
JNIEnv* env,
2 years ago
jobject pThis, jlong handler) {
2 years ago
CTerminal* pTerminal = reinterpret_cast<CTerminal *>(handler);
if (pTerminal == NULL)
{
return NULL;
}
map<unsigned char, vector<unsigned int>> photoTime;
if (!pTerminal->GetPhotoTime(photoTime) || photoTime.empty())
{
return NULL;
}
size_t numberOfData = photoTime.size() * photoTime.begin()->second.size();
if (numberOfData == 0)
{
return NULL;
}
vector<jlong> dataArray;
dataArray.reserve(numberOfData);
unsigned long val = 0;
jint channel = 0;
for (map<unsigned char, vector<unsigned int>>::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<unsigned int>::const_iterator it2 = it->second.cbegin(); it2 != it->second.cend(); ++it2)
{
// time
2 years ago
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_recordingFinished(
JNIEnv* env,
jobject pThis, jlong handler, jboolean result, jstring path, jlong videoId) {
CTerminal* pTerminal = reinterpret_cast<CTerminal *>(handler);
if (pTerminal == NULL)
{
return;
}
IDevice* dev = pTerminal->GetDevice();
if (dev != NULL)
{
const char *pathStr = env->GetStringUTFChars(path, 0);
// camera->Open(pathStr, fileNameStr);
unsigned long photoId = videoId;
((CPhoneDevice *)dev)->OnVideoReady(result != JNI_FALSE, pathStr, photoId);
env->ReleaseStringUTFChars(path, pathStr);
}
}
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);
}