diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index b196c098..7e08658b 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -45,7 +45,7 @@
-
+
@@ -69,11 +69,11 @@
android:name="android.permission.SET_TIME_ZONE"
tools:ignore="ProtectedPermissions" />
-
-
+
+
@@ -82,10 +82,9 @@
-
-
+
+
-
GetEnv((void**)env, JNI_VERSION_1_6);
+ if (get_env_result == JNI_EDETACHED)
+ {
+ if (vm->AttachCurrentThread(env, NULL) == JNI_OK) {
+ did_attach_thread = 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 did_attach_thread;
+}
+
+
// #include "client/linux/handler/exception_handler.h"
// #include "client/linux/handler/minidump_descriptor.h"
@@ -85,7 +107,7 @@ Java_com_xinyingpower_microphoto_MicroPhotoService_init(
// const string& appPath, const string& termId, const string& server, unsigned short port, const string& bindIp
CTermClient& service = CTermClient::GetService();
// CTerminalDevice* device = new CTerminalDevice(vm, pThis);
- CPhoneDevice* device = new CPhoneDevice();
+ CPhoneDevice* device = new CPhoneDevice(vm, pThis);
bool res = service.InitService(appPathStr, cmdidStr, ipStr, (unsigned short)port, "", device);
env->ReleaseStringUTFChars(appPath, appPathStr);
@@ -95,11 +117,16 @@ Java_com_xinyingpower_microphoto_MicroPhotoService_init(
return res ? JNI_TRUE : JNI_FALSE;
}
-
extern "C" JNIEXPORT jboolean JNICALL
Java_com_xinyingpower_microphoto_MicroPhotoService_takePhoto(
JNIEnv* env,
- jobject pThis, jint channel, jint preset, jstring path, jstring fileName) {
+ jobject pThis, jint channel, jint preset, jstring path, jstring fileName, jboolean sendToCma) {
+
+ CTerminal* pTerminal = CTermClient::GetService().GetTerminal();
+ if (pTerminal == NULL)
+ {
+ return JNI_FALSE;
+ }
if (channel < 1 || channel > 0xFF)
{
@@ -107,20 +134,47 @@ Java_com_xinyingpower_microphoto_MicroPhotoService_takePhoto(
}
unsigned char id = (unsigned char)channel - 1;
+ // env->ReleaseStringUTFChars(fileName, fileNameStr);
+ // env->ReleaseStringUTFChars(path, pathStr);
- Camera2Reader *camera = new Camera2Reader(id);
- const char *pathStr = env->GetStringUTFChars(path, 0);
- const char *fileNameStr = env->GetStringUTFChars(fileName, 0);
+ pTerminal->TakeAndSendPhoto(channel, preset, 0);
- camera->Open(pathStr, fileNameStr);
- env->ReleaseStringUTFChars(fileName, fileNameStr);
- env->ReleaseStringUTFChars(path, pathStr);
+ return JNI_TRUE;
+}
- camera->start();
+
+extern "C" JNIEXPORT jboolean JNICALL
+Java_com_xinyingpower_microphoto_MicroPhotoService_sendHeartbeat(
+ JNIEnv* env,
+ jobject pThis) {
+
+ CTerminal* pTerminal = CTermClient::GetService().GetTerminal();
+ if (pTerminal == NULL)
+ {
+ return JNI_FALSE;
+ }
+
+ pTerminal->SendHeartbeat();
return JNI_TRUE;
}
+
+extern "C" JNIEXPORT jboolean JNICALL
+Java_com_xinyingpower_microphoto_MicroPhotoService_fireTimeout(
+ JNIEnv* env,
+ jobject pThis, jlong uid) {
+
+ IDevice* dev = CTermClient::GetService().GetDevice();
+ if (dev == NULL)
+ {
+ return JNI_FALSE;
+ }
+
+ CPhoneDevice* phoneDevice = (CPhoneDevice *)dev;
+ return phoneDevice->FireTimer((IDevice::timer_uid_t)uid) ? JNI_TRUE : JNI_FALSE;
+}
+
extern "C" JNIEXPORT jboolean JNICALL
Java_com_xinyingpower_microphoto_MicroPhotoService_uninit(
JNIEnv* env,
@@ -142,3 +196,65 @@ Java_com_xinyingpower_microphoto_MicroPhotoService_getHeartbeatDuration(
return 60000;
}
+extern "C" JNIEXPORT jlongArray JNICALL
+Java_com_xinyingpower_microphoto_MicroPhotoService_getPhotoTimeData(
+ JNIEnv* env,
+ jobject pThis) {
+
+ CTerminal* pTerminal = CTermClient::GetService().GetTerminal();
+ 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)
+ {
+ val = ((unsigned long)channel << 40);
+ // preset
+ val |= ((unsigned long)((*it2) & 0xFF)) << 32;
+ // time
+ val |= (unsigned long)(((*it2) & 0xFFFFFF00) >> 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;
+}
diff --git a/app/src/main/cpp/PhoneDevice.cpp b/app/src/main/cpp/PhoneDevice.cpp
index 94c06f82..289f8600 100644
--- a/app/src/main/cpp/PhoneDevice.cpp
+++ b/app/src/main/cpp/PhoneDevice.cpp
@@ -19,6 +19,7 @@
#define LOG_TAG "CameraTestHelpers"
#include "PhoneDevice.h"
+#include "TermClient.h"
#include
@@ -26,36 +27,129 @@
#define ALOGW(...) __android_log_print(ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__)
#define ALOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
-CPhoneDevice::CPhoneDevice()
+extern bool GetJniEnv(JavaVM *vm, JNIEnv **env);
+
+CPhoneDevice::CPhoneDevice(JavaVM* vm, jobject service)
{
+ m_vm = vm;
+ JNIEnv* env = NULL;
+ bool attached = GetJniEnv(m_vm, &env);
+ m_javaService = env->NewGlobalRef(service);
+
+ jclass classService = env->GetObjectClass(m_javaService);
+ mRegisterTimerMid = env->GetMethodID(classService, "registerTimer", "(JI)Z");
+ mUnregisterTimerMid = env->GetMethodID(classService, "unregisterTimer", "(J)Z");
+
+ env->DeleteLocalRef(classService);
+
+ if (attached)
+ {
+ vm->DetachCurrentThread();
+ }
+
+ m_timerUidFeed = time(NULL);
}
CPhoneDevice::~CPhoneDevice()
{
-
+ JNIEnv* env = NULL;
+ bool attached = GetJniEnv(m_vm, &env);
+ env->DeleteGlobalRef(m_javaService);
+ if (attached)
+ {
+ m_vm->DetachCurrentThread();
+ }
+ m_javaService = NULL;
}
+void CPhoneDevice::SetListener(IListener* listener)
+{
+ m_listener = listener;
+}
IDevice::timer_uid_t CPhoneDevice::registerTimer(unsigned int timerType, unsigned int timeout)
{
+ IDevice::timer_uid_t uid = m_timerUidFeed.fetch_add(1);
+
+ ALOGI("NDK RegTimer: uid=%lld Type=%u timeout=%u", uid, timerType, timeout);
+
+ JNIEnv* env = NULL;
+ jboolean ret = JNI_FALSE;
+ bool attached = GetJniEnv(m_vm, &env);
+ if (attached)
+ {
+ ret = env->CallBooleanMethod(m_javaService, mRegisterTimerMid, (jlong)uid, (jint)timeout);
+ m_vm->DetachCurrentThread();
+ }
+ if (ret == JNI_TRUE)
+ {
+ unsigned long val = timerType;
+ mTimers.insert(mTimers.end(), std::pair(uid, val));
+ return uid;
+ }
return 0;
}
bool CPhoneDevice::unregisterTimer(IDevice::timer_uid_t uid)
{
- return true;
+ JNIEnv* env = NULL;
+ jboolean ret = JNI_FALSE;
+ bool attached = GetJniEnv(m_vm, &env);
+ if (attached)
+ {
+ ret = env->CallBooleanMethod(m_javaService, mUnregisterTimerMid, (jlong)uid);
+ m_vm->DetachCurrentThread();
+ }
+
+ if (ret == JNI_TRUE)
+ {
+ mTimers.erase(uid);
+ return true;
+ }
+ return false;
}
-bool CPhoneDevice::onTimeout(IDevice::timer_uid_t uid, unsigned int timerType, unsigned int times)
+bool CPhoneDevice::FireTimer(timer_uid_t uid)
{
+ std::map::iterator it = mTimers.find(uid);
+ if (it == mTimers.end())
+ {
+ return false;
+ }
+
+ unsigned long timerType = it->second & 0xFFFFFFFF;
+ unsigned long times = (it->second & 0xFFFFFFFF00000000) >> 32;
+ times++;
+
+ if (timerType != 100)
+ {
+ int aa = 0;
+ }
+ it->second = timerType | (times << 32);
+
+ if (m_listener == NULL)
+ {
+ return false;
+ }
+
+ m_listener->OnTimeout(uid, timerType, times);
+
return true;
}
+IDevice::timer_uid_t CPhoneDevice::RegisterHeartbeat(unsigned int timerType, unsigned int timeout)
+{
+ return registerTimer(timerType, timeout);
+}
-bool CPhoneDevice::TakePhoto(unsigned char channel, unsigned char preset, const string& path, bool photo)
+bool CPhoneDevice::TakePhoto(const IDevice::PHOTO_INFO& photoInfo, const string& path)
{
- int cameraId = (int)channel - 1;
+ LOGI("TAKE_PHOTO: CH=%u PR=%u\n", (unsigned int)photoInfo.channel, (unsigned int)photoInfo.preset);
+ mPhotoInfo = photoInfo;
+ mPath = path;
+
+ int cameraId = (int)photoInfo.channel - 1;
ACameraIdList *cameraIdList = NULL;
ACameraMetadata *cameraMetadata = NULL;
@@ -67,16 +161,19 @@ bool CPhoneDevice::TakePhoto(unsigned char channel, unsigned char preset, const
camera_status = ACameraManager_getCameraIdList(cameraManager, &cameraIdList);
if (camera_status != ACAMERA_OK) {
LOGI("Failed to get camera id list (reason: %d)\n", camera_status);
+ TakePhotoCb(false, photoInfo, path, 0);
return false;
}
if (cameraIdList->numCameras < 1 ) {
LOGI("No camera device detected.\n");
+ TakePhotoCb(false, photoInfo, path, 0);
return false;
}
if (cameraIdList->numCameras <= cameraId ) {
LOGI("No required camera device %d detected.\n", cameraId);
+ TakePhotoCb(false, photoInfo, path, 0);
return false;
}
@@ -125,6 +222,7 @@ bool CPhoneDevice::TakePhoto(unsigned char channel, unsigned char preset, const
if (status != AMEDIA_OK)
{
LOGI("AImageReader_new error\n");
+ TakePhotoCb(false, photoInfo, path, 0);
return false;
}
@@ -139,6 +237,7 @@ bool CPhoneDevice::TakePhoto(unsigned char channel, unsigned char preset, const
if (status != AMEDIA_OK)
{
LOGI("AImageReader_getWindow error\n");
+ TakePhotoCb(false, photoInfo, path, 0);
return false;
}
@@ -157,7 +256,6 @@ bool CPhoneDevice::TakePhoto(unsigned char channel, unsigned char preset, const
ACameraCaptureSession_capture(captureSession, NULL, 1, &captureRequest, NULL);
LOGI("Surface is prepared in here.\n");
-
return true;
}
@@ -175,31 +273,28 @@ ACameraCaptureSession_stateCallbacks* CPhoneDevice::GetSessionListener()
void CPhoneDevice::ImageCallback(AImageReader *reader)
{
- int32_t format;
AImage *image = nullptr;
media_status_t status = AImageReader_acquireNextImage(reader, &image);
- LOGI("ImageCallback\n");
if (status == AMEDIA_OK && image)
{
- LOGI("ImageCallback\n");
+ bool res = WriteFile(image);
AImage_delete(image);
+ // delete pThis;
+
+ TakePhotoCb(res, mPhotoInfo, mPath, time(NULL));
}
}
void CPhoneDevice::OnImageCallback(void *ctx, AImageReader *reader)
{
CPhoneDevice* pThis = reinterpret_cast(ctx);
- AImage *image = nullptr;
- media_status_t status = AImageReader_acquireNextImage(reader, &image);
- if (status == AMEDIA_OK && image)
+ if (pThis != NULL)
{
- WriteFile(pThis, image);
- AImage_delete(image);
-
- // delete pThis;
+ pThis->ImageCallback(reader);
}
}
-bool CPhoneDevice::WriteFile(CPhoneDevice* pThis, AImage *image)
+
+bool CPhoneDevice::WriteFile(AImage *image)
{
int planeCount = 0;
media_status_t status = AImage_getNumberOfPlanes(image, &planeCount);
@@ -215,7 +310,7 @@ bool CPhoneDevice::WriteFile(CPhoneDevice* pThis, AImage *image)
int len = 0;
AImage_getPlaneData(image, 0, &data, &len);
- std::string path = pThis->GetFileName();
+ std::string path = GetFileName();
bool res = false;
FILE *file = fopen(path.c_str(), "wb");
@@ -225,6 +320,8 @@ bool CPhoneDevice::WriteFile(CPhoneDevice* pThis, AImage *image)
fclose(file);
LOGE("Capture: %s", path.c_str());
+
+
res = true;
}
else
@@ -236,16 +333,87 @@ bool CPhoneDevice::WriteFile(CPhoneDevice* pThis, AImage *image)
return res;
}
+bool CPhoneDevice::WriteFile(CPhoneDevice* pThis, AImage *image)
+{
+ return pThis->WriteFile(image);
+}
+
std::string CPhoneDevice::GetFileName() const
{
return mPath;
}
+/*
+bool CPhoneDevice::SendBroadcastMessage(String16 action, int value)
+{
+ TM_INFO_LOG("sendBroadcastMessage(): Action: %s, Value: %d ", action.string(), value);
+ sp sm = defaultServiceManager();
+ sp am = sm->getService(String16("activity"));
+ if (am != NULL) {
+ Parcel data, reply;
+ data.writeInterfaceToken(String16("android.app.IActivityManager"));
+ data.writeStrongBinder(NULL);
+ // intent begin
+ data.writeString16(action); // action
+ data.writeInt32(0); // URI data type
+ data.writeString16(NULL, 0); // type
+ data.writeInt32(0); // flags
+ data.writeString16(NULL, 0); // package name
+ data.writeString16(NULL, 0); // component name
+ data.writeInt32(0); // source bound - size
+ data.writeInt32(0); // categories - size
+ data.writeInt32(0); // selector - size
+ data.writeInt32(0); // clipData - size
+ data.writeInt32(-2); // contentUserHint: -2 -> UserHandle.USER_CURRENT
+ data.writeInt32(-1); // bundle extras length
+ data.writeInt32(0x4C444E42); // 'B' 'N' 'D' 'L'
+ int oldPos = data.dataPosition();
+ data.writeInt32(1); // size
+ // data.writeInt32(0); // VAL_STRING, need to remove because of analyze common intent
+ data.writeString16(String16("type"));
+ data.writeInt32(1); // VAL_INTEGER
+ data.writeInt32(value);
+ int newPos = data.dataPosition();
+ data.setDataPosition(oldPos - 8);
+ data.writeInt32(newPos - oldPos); // refill bundle extras length
+ data.setDataPosition(newPos);
+ // intent end
+ data.writeString16(NULL, 0); // resolvedType
+ data.writeStrongBinder(NULL); // resultTo
+ data.writeInt32(0); // resultCode
+ data.writeString16(NULL, 0); // resultData
+ data.writeInt32(-1); // resultExtras
+ data.writeString16(NULL, 0); // permission
+ data.writeInt32(0); // appOp
+ data.writeInt32(-1); // option
+ data.writeInt32(1); // serialized: != 0 -> ordered
+ data.writeInt32(0); // sticky
+ data.writeInt32(-2); // userId: -2 -> UserHandle.USER_CURRENT
+
+ status_t ret = am->transact(IBinder::FIRST_CALL_TRANSACTION + 13, data,
+ &reply); // BROADCAST_INTENT_TRANSACTION
+ if (ret == NO_ERROR) {
+ int exceptionCode = reply.readExceptionCode();
+ if (exceptionCode) {
+ TM_INFO_LOG("sendBroadcastMessage(%s) caught exception %d\n",
+ action.string(), exceptionCode);
+ return false;
+ }
+ } else {
+ return false;
+ }
+ } else {
+ TM_INFO_LOG("getService() couldn't find activity service!\n");
+ return false;
+ }
+ return true;
+}
+ */
void CPhoneDevice::camera_device_on_disconnected(void *context, ACameraDevice *device)
{
LOGI("Camera(id: %s) is diconnected.\n", ACameraDevice_getId(device));
CPhoneDevice* pThis = (CPhoneDevice*)context;
- delete pThis;
+ // delete pThis;
}
void CPhoneDevice::camera_device_on_error(void *context, ACameraDevice *device, int error)
diff --git a/app/src/main/cpp/PhoneDevice.h b/app/src/main/cpp/PhoneDevice.h
index f0ef8c6d..78bab0e2 100644
--- a/app/src/main/cpp/PhoneDevice.h
+++ b/app/src/main/cpp/PhoneDevice.h
@@ -9,6 +9,9 @@
#include
#include
+#include