修复定时拍照bug

serial
Matthew 2 years ago
parent eacbd1cd48
commit 2a3476786b

@ -2,8 +2,8 @@ plugins {
id 'com.android.application' id 'com.android.application'
} }
def AppVersionName = "1.0.4" def AppVersionName = "1.0.5"
def AppVersionCode = ((1 * 100 + 1) * 100 + 0) * 10 + 4 def AppVersionCode = ((1 * 100 + 1) * 100 + 0) * 10 + 5
android { android {
namespace 'com.xinyingpower.microphoto' namespace 'com.xinyingpower.microphoto'

@ -32,8 +32,8 @@
<uses-permission android:name="android.permission.DEVICE_POWER" tools:ignore="ProtectedPermissions" /> <uses-permission android:name="android.permission.DEVICE_POWER" tools:ignore="ProtectedPermissions" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" /> <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.MODIFY_PHONE_STATE" <uses-permission android:name="android.permission.MODIFY_PHONE_STATE" tools:ignore="ProtectedPermissions" />
tools:ignore="ProtectedPermissions" /> <uses-permission android:name="android.permission.START_ACTIVITIES_FROM_BACKGROUND" tools:ignore="ProtectedPermissions" />
<uses-feature android:name="android.hardware.camera" /> <uses-feature android:name="android.hardware.camera" />
<application <application

@ -21,10 +21,7 @@
#include "Camera.h" #include "Camera.h"
#include <android/log.h> #include <android/log.h>
#include <AndroidHelper.h>
#define ALOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
#define ALOGW(...) __android_log_print(ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__)
#define ALOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
CCamera::CCamera() CCamera::CCamera()
{ {

@ -16,18 +16,17 @@
#include "Camera.h" #include "Camera.h"
#include "Camera2Reader.h" #include "Camera2Reader.h"
bool GetJniEnv(JavaVM *vm, JNIEnv **env, bool& didAttachThread)
bool GetJniEnv(JavaVM *vm, JNIEnv **env)
{ {
bool did_attach_thread = false; didAttachThread = false;
*env = nullptr; *env = nullptr;
// Check if the current thread is attached to the VM // Check if the current thread is attached to the VM
auto get_env_result = vm->GetEnv((void**)env, JNI_VERSION_1_6); auto get_env_result = vm->GetEnv((void**)env, JNI_VERSION_1_6);
if (get_env_result == JNI_EDETACHED) if (get_env_result == JNI_EDETACHED)
{ {
if (vm->AttachCurrentThread(env, NULL) == JNI_OK) { get_env_result = vm->AttachCurrentThread(env, NULL);
did_attach_thread = true; if (get_env_result == JNI_OK) {
didAttachThread = true;
} else { } else {
// Failed to attach thread. Throw an exception if you want to. // Failed to attach thread. Throw an exception if you want to.
} }
@ -36,10 +35,9 @@ bool GetJniEnv(JavaVM *vm, JNIEnv **env)
// Unsupported JNI version. Throw an exception if you want to. // Unsupported JNI version. Throw an exception if you want to.
} }
return did_attach_thread; return get_env_result == JNI_OK;
} }
// #include "client/linux/handler/exception_handler.h" // #include "client/linux/handler/exception_handler.h"
// #include "client/linux/handler/minidump_descriptor.h" // #include "client/linux/handler/minidump_descriptor.h"
@ -92,7 +90,7 @@ Java_com_xinyingpower_microphoto_MainActivity_takePhoto(
extern "C" JNIEXPORT jlong JNICALL extern "C" JNIEXPORT jlong JNICALL
Java_com_xinyingpower_microphoto_MicroPhotoService_init( Java_com_xinyingpower_microphoto_MicroPhotoService_init(
JNIEnv* env, JNIEnv* env,
jobject pThis, jstring appPath, jstring ip, jint port, jstring cmdid) { jobject pThis, jstring appPath, jstring ip, jint port, jstring cmdid, jint protocol) {
/* /*
google_breakpad::MinidumpDescriptor descriptor("."); google_breakpad::MinidumpDescriptor descriptor(".");
@ -125,6 +123,12 @@ Java_com_xinyingpower_microphoto_MicroPhotoService_init(
env->ReleaseStringUTFChars(ip, ipStr); env->ReleaseStringUTFChars(ip, ipStr);
env->ReleaseStringUTFChars(cmdid, cmdidStr); env->ReleaseStringUTFChars(cmdid, cmdidStr);
if (!res)
{
delete pTerminal;
pTerminal = NULL;
}
return reinterpret_cast<jlong>(pTerminal); return reinterpret_cast<jlong>(pTerminal);
} }
@ -170,7 +174,7 @@ Java_com_xinyingpower_microphoto_MicroPhotoService_sendHeartbeat(
extern "C" JNIEXPORT jboolean JNICALL extern "C" JNIEXPORT jboolean JNICALL
Java_com_xinyingpower_microphoto_MicroPhotoService_fireTimeout( Java_com_xinyingpower_microphoto_MicroPhotoService_fireTimeout(
JNIEnv* env, JNIEnv* env,
jobject pThis, jlong handler, jlong uid) { jobject pThis, jlong handler, jlong uid, jlong times) {
CTerminal* pTerminal = reinterpret_cast<CTerminal *>(handler); CTerminal* pTerminal = reinterpret_cast<CTerminal *>(handler);
IDevice* dev = pTerminal->GetDevice(); IDevice* dev = pTerminal->GetDevice();
@ -180,7 +184,7 @@ Java_com_xinyingpower_microphoto_MicroPhotoService_fireTimeout(
} }
CPhoneDevice* phoneDevice = (CPhoneDevice *)dev; CPhoneDevice* phoneDevice = (CPhoneDevice *)dev;
return phoneDevice->FireTimer((IDevice::timer_uid_t)uid) ? JNI_TRUE : JNI_FALSE; return phoneDevice->FireTimer((IDevice::timer_uid_t)uid, static_cast<unsigned long>(times)) ? JNI_TRUE : JNI_FALSE;
} }
extern "C" JNIEXPORT jboolean JNICALL extern "C" JNIEXPORT jboolean JNICALL

@ -17,7 +17,7 @@
*/ */
#define LOG_TAG "CameraTestHelpers" #define LOG_TAG "CameraTestHelpers"
#include <AndroidHelper.h>
#include "PhoneDevice.h" #include "PhoneDevice.h"
#include <opencv2/opencv.hpp> #include <opencv2/opencv.hpp>
@ -33,15 +33,8 @@
#include <android/log.h> #include <android/log.h>
#include <sys/system_properties.h> #include <sys/system_properties.h>
#define ALOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
#define ALOGW(...) __android_log_print(ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__)
#define ALOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
#define ASSERT(cond, fmt, ...) \
if (!(cond)) { \
__android_log_assert(#cond, LOG_TAG, fmt, ##__VA_ARGS__); \
}
extern bool GetJniEnv(JavaVM *vm, JNIEnv **env); extern bool GetJniEnv(JavaVM *vm, JNIEnv **env, bool& didAttachThread);
#define WAKELOCK_NAME "NDK_WK_" #define WAKELOCK_NAME "NDK_WK_"
// This value is 2 ^ 18 - 1, and is used to clamp the RGB values before their // This value is 2 ^ 18 - 1, and is used to clamp the RGB values before their
@ -166,14 +159,20 @@ CPhoneDevice::CPhoneDevice(JavaVM* vm, jobject service)
m_listener = NULL; m_listener = NULL;
mHeartbeatStartTime = 0; mHeartbeatStartTime = 0;
mHeartbeatDuration = 0; mHeartbeatDuration = 0;
m_javaService = NULL;
m_vm = vm; m_vm = vm;
JNIEnv* env = NULL; JNIEnv* env = NULL;
bool attached = GetJniEnv(m_vm, &env); bool didAttachThread = false;
bool res = GetJniEnv(m_vm, &env, didAttachThread);
if (!res)
{
ALOGE("Failed to get JNI Env");
}
m_javaService = env->NewGlobalRef(service); m_javaService = env->NewGlobalRef(service);
jclass classService = env->GetObjectClass(m_javaService); jclass classService = env->GetObjectClass(m_javaService);
mRegisterTimerMid = env->GetMethodID(classService, "registerTimer", "(JI)Z"); mRegisterTimerMid = env->GetMethodID(classService, "registerTimer", "(JIJ)Z");
mRegisterHeartbeatMid = env->GetMethodID(classService, "registerHeartbeatTimer", "(I)V"); mRegisterHeartbeatMid = env->GetMethodID(classService, "registerHeartbeatTimer", "(I)V");
mUnregisterTimerMid = env->GetMethodID(classService, "unregisterTimer", "(J)Z"); mUnregisterTimerMid = env->GetMethodID(classService, "unregisterTimer", "(J)Z");
mUpdateTimeMid = env->GetMethodID(classService, "updateTime", "(J)Z"); mUpdateTimeMid = env->GetMethodID(classService, "updateTime", "(J)Z");
@ -183,7 +182,7 @@ CPhoneDevice::CPhoneDevice(JavaVM* vm, jobject service)
env->DeleteLocalRef(classService); env->DeleteLocalRef(classService);
if (attached) if (didAttachThread)
{ {
vm->DetachCurrentThread(); vm->DetachCurrentThread();
} }
@ -195,9 +194,14 @@ CPhoneDevice::CPhoneDevice(JavaVM* vm, jobject service)
CPhoneDevice::~CPhoneDevice() CPhoneDevice::~CPhoneDevice()
{ {
JNIEnv* env = NULL; JNIEnv* env = NULL;
bool attached = GetJniEnv(m_vm, &env); bool didAttachThread = false;
bool res = GetJniEnv(m_vm, &env, didAttachThread);
if (!res)
{
ALOGE("Failed to get JNI Env");
}
env->DeleteGlobalRef(m_javaService); env->DeleteGlobalRef(m_javaService);
if (attached) if (didAttachThread)
{ {
m_vm->DetachCurrentThread(); m_vm->DetachCurrentThread();
} }
@ -213,11 +217,16 @@ bool CPhoneDevice::UpdateTime(time_t ts)
{ {
JNIEnv* env = NULL; JNIEnv* env = NULL;
jboolean ret = JNI_FALSE; jboolean ret = JNI_FALSE;
bool attached = GetJniEnv(m_vm, &env); bool didAttachThread = false;
if (attached) bool res = GetJniEnv(m_vm, &env, didAttachThread);
if (!res)
{ {
ALOGE("Failed to get JNI Env");
}
jlong timeInMillis = ((jlong)ts) * 1000; jlong timeInMillis = ((jlong)ts) * 1000;
ret = env->CallBooleanMethod(m_javaService, mUpdateTimeMid, timeInMillis); ret = env->CallBooleanMethod(m_javaService, mUpdateTimeMid, timeInMillis);
if (didAttachThread)
{
m_vm->DetachCurrentThread(); m_vm->DetachCurrentThread();
} }
@ -266,18 +275,23 @@ bool CPhoneDevice::Reboot()
return false; return false;
} }
IDevice::timer_uid_t CPhoneDevice::RegisterTimer(unsigned int timerType, unsigned int timeout) IDevice::timer_uid_t CPhoneDevice::RegisterTimer(unsigned int timerType, unsigned int timeout, unsigned long times/* = 0*/)
{ {
IDevice::timer_uid_t uid = m_timerUidFeed.fetch_add(1); IDevice::timer_uid_t uid = m_timerUidFeed.fetch_add(1);
ALOGI("NDK RegTimer: uid=%lld Type=%u timeout=%u", uid, timerType, timeout); ALOGI("NDK RegTimer: uid=%lld Type=%u timeout=%u", uid, timerType, timeout);
JNIEnv* env = NULL; JNIEnv* env = NULL;
jboolean ret = JNI_FALSE; bool didAttachThread = false;
bool attached = GetJniEnv(m_vm, &env); bool res = GetJniEnv(m_vm, &env, didAttachThread);
if (attached) if (!res)
{
ALOGE("Failed to get JNI Env");
return 0;
}
jboolean ret = env->CallBooleanMethod(m_javaService, mRegisterTimerMid, (jlong)uid, (jint)timeout, (jlong)times);
if (didAttachThread)
{ {
ret = env->CallBooleanMethod(m_javaService, mRegisterTimerMid, (jlong)uid, (jint)timeout);
m_vm->DetachCurrentThread(); m_vm->DetachCurrentThread();
} }
@ -292,12 +306,18 @@ IDevice::timer_uid_t CPhoneDevice::RegisterTimer(unsigned int timerType, unsigne
bool CPhoneDevice::UnregisterTimer(IDevice::timer_uid_t uid) bool CPhoneDevice::UnregisterTimer(IDevice::timer_uid_t uid)
{ {
JNIEnv* env = NULL;
jboolean ret = JNI_FALSE; jboolean ret = JNI_FALSE;
bool attached = GetJniEnv(m_vm, &env); JNIEnv* env = NULL;
if (attached) bool didAttachThread = false;
bool res = GetJniEnv(m_vm, &env, didAttachThread);
if (!res)
{ {
ALOGE("Failed to get JNI Env");
return false;
}
ret = env->CallBooleanMethod(m_javaService, mUnregisterTimerMid, (jlong)uid); ret = env->CallBooleanMethod(m_javaService, mUnregisterTimerMid, (jlong)uid);
if (didAttachThread)
{
m_vm->DetachCurrentThread(); m_vm->DetachCurrentThread();
} }
@ -315,11 +335,17 @@ unsigned long CPhoneDevice::RequestWakelock(unsigned long timeout)
std::string name = WAKELOCK_NAME; std::string name = WAKELOCK_NAME;
name += to_string(wakelockId); name += to_string(wakelockId);
JNIEnv* env = NULL; ALOGI("RequestWakelock=%lld",wakelockId);
jboolean ret = JNI_FALSE; jboolean ret = JNI_FALSE;
bool attached = GetJniEnv(m_vm, &env); JNIEnv* env = NULL;
if (attached) bool didAttachThread = false;
bool res = GetJniEnv(m_vm, &env, didAttachThread);
if (!res)
{ {
ALOGE("Failed to get JNI Env");
return 0;
}
jstring jname = env->NewStringUTF(name.c_str()); jstring jname = env->NewStringUTF(name.c_str());
jlong jtimeout = (jlong)timeout; jlong jtimeout = (jlong)timeout;
@ -327,37 +353,43 @@ unsigned long CPhoneDevice::RequestWakelock(unsigned long timeout)
// env->ReleaseStringUTFChars(jname, name.c_str()); // env->ReleaseStringUTFChars(jname, name.c_str());
env->DeleteLocalRef(jname); env->DeleteLocalRef(jname);
if (didAttachThread)
{
m_vm->DetachCurrentThread(); m_vm->DetachCurrentThread();
} }
// return (ret == JNI_TRUE);
return wakelockId; return wakelockId;
} }
bool CPhoneDevice::ReleaseWakelock(unsigned long wakelock) bool CPhoneDevice::ReleaseWakelock(unsigned long wakelock)
{ {
ALOGI("ReleaseWakelock=%lld", wakelock);
std::string name = WAKELOCK_NAME; std::string name = WAKELOCK_NAME;
name += to_string(wakelock); name += to_string(wakelock);
JNIEnv* env = NULL;
jboolean ret = JNI_FALSE; jboolean ret = JNI_FALSE;
bool attached = GetJniEnv(m_vm, &env); JNIEnv* env = NULL;
if (attached) bool didAttachThread = false;
bool res = GetJniEnv(m_vm, &env, didAttachThread);
if (!res)
{ {
ALOGE("Failed to get JNI Env");
return false;
}
jstring jname = env->NewStringUTF(name.c_str()); jstring jname = env->NewStringUTF(name.c_str());
env->CallVoidMethod(m_javaService, mReleaseWakelockMid, jname); env->CallVoidMethod(m_javaService, mReleaseWakelockMid, jname);
env->DeleteLocalRef(jname); env->DeleteLocalRef(jname);
// env->ReleaseStringUTFChars(jname, name.c_str()); // env->ReleaseStringUTFChars(jname, name.c_str());
if (didAttachThread)
{
m_vm->DetachCurrentThread(); m_vm->DetachCurrentThread();
} }
return true; return true;
} }
bool CPhoneDevice::FireTimer(timer_uid_t uid) bool CPhoneDevice::FireTimer(timer_uid_t uid, unsigned long times)
{ {
std::map<IDevice::timer_uid_t, unsigned long>::iterator it = mTimers.find(uid); std::map<IDevice::timer_uid_t, unsigned long>::iterator it = mTimers.find(uid);
if (it == mTimers.end()) if (it == mTimers.end())
@ -366,21 +398,21 @@ bool CPhoneDevice::FireTimer(timer_uid_t uid)
} }
unsigned long timerType = it->second & 0xFFFFFFFF; unsigned long timerType = it->second & 0xFFFFFFFF;
unsigned long times = (it->second & 0xFFFFFFFF00000000) >> 32; unsigned long ntimes = (it->second & 0xFFFFFFFF00000000) >> 32;
times++; ntimes++;
if (timerType != 100) if (timerType != 100)
{ {
int aa = 0; int aa = 0;
} }
it->second = timerType | (times << 32); it->second = timerType | (ntimes << 32);
if (m_listener == NULL) if (m_listener == NULL)
{ {
return false; return false;
} }
m_listener->OnTimeout(uid, timerType, times); m_listener->OnTimeout(uid, timerType, ntimes);
return true; return true;
} }
@ -392,10 +424,16 @@ IDevice::timer_uid_t CPhoneDevice::RegisterHeartbeat(unsigned int timerType, uns
IDevice::timer_uid_t uid = m_timerUidFeed.fetch_add(1); IDevice::timer_uid_t uid = m_timerUidFeed.fetch_add(1);
JNIEnv* env = NULL;
jboolean ret = JNI_FALSE; jboolean ret = JNI_FALSE;
bool attached = GetJniEnv(m_vm, &env); JNIEnv* env = NULL;
if (attached) bool didAttachThread = false;
bool res = GetJniEnv(m_vm, &env, didAttachThread);
if (!res)
{
ALOGE("Failed to get JNI Env");
return 0;
}
if (didAttachThread)
{ {
env->CallVoidMethod(m_javaService, mRegisterHeartbeatMid, (jint)timeout); env->CallVoidMethod(m_javaService, mRegisterHeartbeatMid, (jint)timeout);
m_vm->DetachCurrentThread(); m_vm->DetachCurrentThread();
@ -412,7 +450,7 @@ bool CPhoneDevice::TakePhoto(const IDevice::PHOTO_INFO& photoInfo, const vector<
mCamera = NULL; mCamera = NULL;
} }
LOGI("TAKE_PHOTO: CH=%u PR=%u\n", (unsigned int)photoInfo.channel, (unsigned int)photoInfo.preset); ALOGI("TAKE_PHOTO: CH=%u PR=%u\n", (unsigned int)photoInfo.channel, (unsigned int)photoInfo.preset);
mPhotoInfo = photoInfo; mPhotoInfo = photoInfo;
mPath = path; mPath = path;
mOsds = osds; mOsds = osds;
@ -467,7 +505,6 @@ bool CPhoneDevice::OnImageReady(const cv::Mat& mat) const
compression_params.push_back(cv::IMWRITE_JPEG_QUALITY); compression_params.push_back(cv::IMWRITE_JPEG_QUALITY);
compression_params.push_back(mPhotoInfo.quality); compression_params.push_back(mPhotoInfo.quality);
ALOGI("Will write photo: %s", mPath.c_str());
if (!std::filesystem::exists(std::filesystem::path(mPath))) if (!std::filesystem::exists(std::filesystem::path(mPath)))
{ {
bool res = cv::imwrite(mPath.c_str(), mat, compression_params); bool res = cv::imwrite(mPath.c_str(), mat, compression_params);
@ -475,6 +512,10 @@ bool CPhoneDevice::OnImageReady(const cv::Mat& mat) const
{ {
ALOGE("Failed to write photo: %s", mPath.c_str()); ALOGE("Failed to write photo: %s", mPath.c_str());
} }
else
{
ALOGI("Succeeded to write photo: %s", mPath.c_str());
}
TakePhotoCb(res, mPhotoInfo, mPath, time(NULL)); TakePhotoCb(res, mPhotoInfo, mPath, time(NULL));
return res; return res;
} }

@ -18,11 +18,6 @@
#include <camera/NdkCameraDevice.h> #include <camera/NdkCameraDevice.h>
#include <camera/NdkCameraMetadataTags.h> #include <camera/NdkCameraMetadataTags.h>
#include <media/NdkImageReader.h> #include <media/NdkImageReader.h>
#include <android/log.h>
// #define LOG_TAG "native-camera2-jni"
#define PD_LOG_TAG "PhoneDev"
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,PD_LOG_TAG,__VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,PD_LOG_TAG,__VA_ARGS__)
#include <Client/Device.h> #include <Client/Device.h>
#include <string> #include <string>
@ -43,12 +38,12 @@ public:
virtual timer_uid_t RegisterHeartbeat(unsigned int timerType, unsigned int timeout); virtual timer_uid_t RegisterHeartbeat(unsigned int timerType, unsigned int timeout);
virtual bool TakePhoto(const IDevice::PHOTO_INFO& photoInfo, const vector<OSD_INFO>& osds, const string& path); virtual bool TakePhoto(const IDevice::PHOTO_INFO& photoInfo, const vector<OSD_INFO>& osds, const string& path);
virtual bool CloseCamera(); virtual bool CloseCamera();
virtual timer_uid_t RegisterTimer(unsigned int timerType, unsigned int timeout); virtual timer_uid_t RegisterTimer(unsigned int timerType, unsigned int timeout, unsigned long times = 0);
virtual bool UnregisterTimer(timer_uid_t uid); virtual bool UnregisterTimer(timer_uid_t uid);
virtual unsigned long RequestWakelock(unsigned long timeout); virtual unsigned long RequestWakelock(unsigned long timeout);
virtual bool ReleaseWakelock(unsigned long wakelock); virtual bool ReleaseWakelock(unsigned long wakelock);
virtual bool FireTimer(timer_uid_t uid); virtual bool FireTimer(timer_uid_t uid, unsigned long times);
bool GetNextScheduleItem(uint32_t tsBasedZero, uint32_t scheduleTime, vector<uint32_t>& items); bool GetNextScheduleItem(uint32_t tsBasedZero, uint32_t scheduleTime, vector<uint32_t>& items);

@ -32,15 +32,9 @@
#include <android/log.h> #include <android/log.h>
#define ALOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__) #include <AndroidHelper.h>
#define ALOGW(...) __android_log_print(ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__)
#define ALOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
#define ASSERT(cond, fmt, ...) \
if (!(cond)) { \
__android_log_assert(#cond, LOG_TAG, fmt, ##__VA_ARGS__); \
}
extern bool GetJniEnv(JavaVM *vm, JNIEnv **env); extern bool GetJniEnv(JavaVM *vm, JNIEnv **env, bool& didAttachThread);
// This value is 2 ^ 18 - 1, and is used to clamp the RGB values before their // This value is 2 ^ 18 - 1, and is used to clamp the RGB values before their
@ -79,7 +73,12 @@ CPhoneDevice2::CPhoneDevice2(JavaVM* vm, jobject service)
{ {
m_vm = vm; m_vm = vm;
JNIEnv* env = NULL; JNIEnv* env = NULL;
bool attached = GetJniEnv(m_vm, &env); bool attached = false;
bool res = GetJniEnv(m_vm, &env, attached);
if (!res)
{
ALOGE("Failed to get JNI Env");
}
m_javaService = env->NewGlobalRef(service); m_javaService = env->NewGlobalRef(service);
jclass classService = env->GetObjectClass(m_javaService); jclass classService = env->GetObjectClass(m_javaService);
@ -102,7 +101,12 @@ CPhoneDevice2::CPhoneDevice2(JavaVM* vm, jobject service)
CPhoneDevice2::~CPhoneDevice2() CPhoneDevice2::~CPhoneDevice2()
{ {
JNIEnv* env = NULL; JNIEnv* env = NULL;
bool attached = GetJniEnv(m_vm, &env); bool attached = false;
bool res = GetJniEnv(m_vm, &env, attached);
if (!res)
{
ALOGE("Failed to get JNI Env");
}
env->DeleteGlobalRef(m_javaService); env->DeleteGlobalRef(m_javaService);
if (attached) if (attached)
{ {
@ -120,11 +124,17 @@ bool CPhoneDevice2::UpdateTime(time_t ts)
{ {
JNIEnv* env = NULL; JNIEnv* env = NULL;
jboolean ret = JNI_FALSE; jboolean ret = JNI_FALSE;
bool attached = GetJniEnv(m_vm, &env); bool attached = false;
if (attached) bool res = GetJniEnv(m_vm, &env, attached);
if (!res)
{ {
ALOGE("Failed to get JNI Env");
return false;
}
jlong timeInMillis = ((jlong)ts) * 1000; jlong timeInMillis = ((jlong)ts) * 1000;
ret = env->CallBooleanMethod(m_javaService, mUpdateTimeMid, timeInMillis); ret = env->CallBooleanMethod(m_javaService, mUpdateTimeMid, timeInMillis);
if (attached)
{
m_vm->DetachCurrentThread(); m_vm->DetachCurrentThread();
} }
@ -144,10 +154,17 @@ IDevice::timer_uid_t CPhoneDevice2::RegisterTimer(unsigned int timerType, unsign
JNIEnv* env = NULL; JNIEnv* env = NULL;
jboolean ret = JNI_FALSE; jboolean ret = JNI_FALSE;
bool attached = GetJniEnv(m_vm, &env); bool attached = false;
if (attached) bool res = GetJniEnv(m_vm, &env, attached);
if (!res)
{ {
ALOGE("Failed to get JNI Env");
return 0;
}
ret = env->CallBooleanMethod(m_javaService, mRegisterTimerMid, (jlong)uid, (jint)timeout); ret = env->CallBooleanMethod(m_javaService, mRegisterTimerMid, (jlong)uid, (jint)timeout);
if (attached)
{
m_vm->DetachCurrentThread(); m_vm->DetachCurrentThread();
} }
@ -164,10 +181,16 @@ bool CPhoneDevice2::UnregisterTimer(IDevice::timer_uid_t uid)
{ {
JNIEnv* env = NULL; JNIEnv* env = NULL;
jboolean ret = JNI_FALSE; jboolean ret = JNI_FALSE;
bool attached = GetJniEnv(m_vm, &env); bool attached = false;
if (attached) bool res = GetJniEnv(m_vm, &env, attached);
if (!res)
{ {
ALOGE("Failed to get JNI Env");
return false;
}
ret = env->CallBooleanMethod(m_javaService, mUnregisterTimerMid, (jlong)uid); ret = env->CallBooleanMethod(m_javaService, mUnregisterTimerMid, (jlong)uid);
if (attached)
{
m_vm->DetachCurrentThread(); m_vm->DetachCurrentThread();
} }
@ -213,10 +236,16 @@ IDevice::timer_uid_t CPhoneDevice2::RegisterHeartbeat(unsigned int timerType, un
JNIEnv* env = NULL; JNIEnv* env = NULL;
jboolean ret = JNI_FALSE; jboolean ret = JNI_FALSE;
bool attached = GetJniEnv(m_vm, &env); bool attached = false;
if (attached) bool res = GetJniEnv(m_vm, &env, attached);
if (!res)
{ {
ALOGE("Failed to get JNI Env");
return 0;
}
env->CallVoidMethod(m_javaService, mRegisterHeartbeatMid, (jint)timeout); env->CallVoidMethod(m_javaService, mRegisterHeartbeatMid, (jint)timeout);
if (attached)
{
m_vm->DetachCurrentThread(); m_vm->DetachCurrentThread();
} }
@ -225,15 +254,15 @@ IDevice::timer_uid_t CPhoneDevice2::RegisterHeartbeat(unsigned int timerType, un
bool CPhoneDevice2::TakePhoto(const IDevice::PHOTO_INFO& photoInfo, const vector<OSD_INFO>& osds, const string& path) bool CPhoneDevice2::TakePhoto(const IDevice::PHOTO_INFO& photoInfo, const vector<OSD_INFO>& osds, const string& path)
{ {
LOGI("TAKE_PHOTO: CH=%u PR=%u\n", (unsigned int)photoInfo.channel, (unsigned int)photoInfo.preset); ALOGI("TAKE_PHOTO: CH=%u PR=%u\n", (unsigned int)photoInfo.channel, (unsigned int)photoInfo.preset);
mPhotoInfo = photoInfo; mPhotoInfo = photoInfo;
mPath = path; mPath = path;
mDisplayDimension = DisplayDimension(photoInfo.width, photoInfo.height); mDisplayDimension = DisplayDimension(photoInfo.width, photoInfo.height);
LOGE("Image Buffer Size: %d", photoInfo.width * photoInfo.height * 4); ALOGE("Image Buffer Size: %d", photoInfo.width * photoInfo.height * 4);
imageBuffer_ = (uint8_t*)malloc(photoInfo.width * photoInfo.height * 4); imageBuffer_ = (uint8_t*)malloc(photoInfo.width * photoInfo.height * 4);
ASSERT(imageBuffer_ != nullptr, "Failed to allocate imageBuffer_"); AASSERT(imageBuffer_ != nullptr, "Failed to allocate imageBuffer_");
int cameraId = (int)photoInfo.channel - 1; int cameraId = (int)photoInfo.channel - 1;
@ -246,33 +275,33 @@ bool CPhoneDevice2::TakePhoto(const IDevice::PHOTO_INFO& photoInfo, const vector
camera_status = ACameraManager_getCameraIdList(cameraManager, &cameraIdList); camera_status = ACameraManager_getCameraIdList(cameraManager, &cameraIdList);
if (camera_status != ACAMERA_OK) { if (camera_status != ACAMERA_OK) {
LOGI("Failed to get camera id list (reason: %d)\n", camera_status); ALOGI("Failed to get camera id list (reason: %d)\n", camera_status);
TakePhotoCb(false, photoInfo, path, 0); TakePhotoCb(false, photoInfo, path, 0);
return false; return false;
} }
if (cameraIdList->numCameras < 1 ) { if (cameraIdList->numCameras < 1 ) {
LOGI("No camera device detected.\n"); ALOGI("No camera device detected.\n");
TakePhotoCb(false, photoInfo, path, 0); TakePhotoCb(false, photoInfo, path, 0);
return false; return false;
} }
if (cameraIdList->numCameras <= cameraId ) { if (cameraIdList->numCameras <= cameraId ) {
LOGI("No required camera device %d detected.\n", cameraId); ALOGI("No required camera device %d detected.\n", cameraId);
TakePhotoCb(false, photoInfo, path, 0); TakePhotoCb(false, photoInfo, path, 0);
return false; return false;
} }
selectedCameraId = cameraIdList->cameraIds[cameraId]; selectedCameraId = cameraIdList->cameraIds[cameraId];
LOGI("Trying to open Camera2 (id: %s, num of camera : %d)\n", selectedCameraId, ALOGI("Trying to open Camera2 (id: %s, num of camera : %d)\n", selectedCameraId,
cameraIdList->numCameras); cameraIdList->numCameras);
camera_status = ACameraManager_getCameraCharacteristics(cameraManager, selectedCameraId, camera_status = ACameraManager_getCameraCharacteristics(cameraManager, selectedCameraId,
&cameraMetadata); &cameraMetadata);
if (camera_status != ACAMERA_OK) { if (camera_status != ACAMERA_OK) {
LOGI("Failed to get camera meta data of ID:%s\n", selectedCameraId); ALOGI("Failed to get camera meta data of ID:%s\n", selectedCameraId);
} }
ACameraMetadata_const_entry face, orientation; ACameraMetadata_const_entry face, orientation;
@ -286,7 +315,7 @@ bool CPhoneDevice2::TakePhoto(const IDevice::PHOTO_INFO& photoInfo, const vector
camera_status = ACameraMetadata_getConstEntry(cameraMetadata, ACAMERA_SENSOR_ORIENTATION, &orientation); camera_status = ACameraMetadata_getConstEntry(cameraMetadata, ACAMERA_SENSOR_ORIENTATION, &orientation);
LOGI("====Current SENSOR_ORIENTATION: %8d", orientation.data.i32[0]); ALOGI("====Current SENSOR_ORIENTATION: %8d", orientation.data.i32[0]);
uint32_t cameraOrientation_ = orientation.data.i32[0]; uint32_t cameraOrientation_ = orientation.data.i32[0];
if (cameraOrientation_ == 90 || cameraOrientation_ == 270) if (cameraOrientation_ == 90 || cameraOrientation_ == 270)
{ {
@ -303,14 +332,14 @@ bool CPhoneDevice2::TakePhoto(const IDevice::PHOTO_INFO& photoInfo, const vector
&deviceStateCallbacks, &cameraDevice); &deviceStateCallbacks, &cameraDevice);
if (camera_status != ACAMERA_OK) { if (camera_status != ACAMERA_OK) {
LOGI("Failed to open camera device (id: %s)\n", selectedCameraId); ALOGI("Failed to open camera device (id: %s)\n", selectedCameraId);
} }
camera_status = ACameraDevice_createCaptureRequest(cameraDevice, TEMPLATE_STILL_CAPTURE/*TEMPLATE_PREVIEW*/, camera_status = ACameraDevice_createCaptureRequest(cameraDevice, TEMPLATE_STILL_CAPTURE/*TEMPLATE_PREVIEW*/,
&captureRequest); &captureRequest);
if (camera_status != ACAMERA_OK) { if (camera_status != ACAMERA_OK) {
LOGI("Failed to create preview capture request (id: %s)\n", selectedCameraId); ALOGI("Failed to create preview capture request (id: %s)\n", selectedCameraId);
} }
ACaptureSessionOutputContainer_create(&captureSessionOutputContainer); ACaptureSessionOutputContainer_create(&captureSessionOutputContainer);
@ -328,7 +357,7 @@ bool CPhoneDevice2::TakePhoto(const IDevice::PHOTO_INFO& photoInfo, const vector
status = AImageReader_new(resCap.width, resCap.height, resCap.format, 5, &mAImageReader); status = AImageReader_new(resCap.width, resCap.height, resCap.format, 5, &mAImageReader);
if (status != AMEDIA_OK) if (status != AMEDIA_OK)
{ {
LOGI("AImageReader_new error\n"); ALOGI("AImageReader_new error\n");
TakePhotoCb(false, photoInfo, path, 0); TakePhotoCb(false, photoInfo, path, 0);
return false; return false;
} }
@ -343,12 +372,12 @@ bool CPhoneDevice2::TakePhoto(const IDevice::PHOTO_INFO& photoInfo, const vector
status = AImageReader_getWindow(mAImageReader, &theNativeWindow); status = AImageReader_getWindow(mAImageReader, &theNativeWindow);
if (status != AMEDIA_OK) if (status != AMEDIA_OK)
{ {
LOGI("AImageReader_getWindow error\n"); ALOGI("AImageReader_getWindow error\n");
TakePhotoCb(false, photoInfo, path, 0); TakePhotoCb(false, photoInfo, path, 0);
return false; return false;
} }
LOGI("Surface is prepared in %p.\n", theNativeWindow); ALOGI("Surface is prepared in %p.\n", theNativeWindow);
// theNativeWindow // theNativeWindow
ACameraOutputTarget_create(theNativeWindow, &cameraOutputTarget); ACameraOutputTarget_create(theNativeWindow, &cameraOutputTarget);
@ -362,7 +391,7 @@ bool CPhoneDevice2::TakePhoto(const IDevice::PHOTO_INFO& photoInfo, const vector
// ACameraCaptureSession_setRepeatingRequest(captureSession, NULL, 1, &captureRequest, NULL); // ACameraCaptureSession_setRepeatingRequest(captureSession, NULL, 1, &captureRequest, NULL);
ACameraCaptureSession_capture(captureSession, NULL, 1, &captureRequest, NULL); ACameraCaptureSession_capture(captureSession, NULL, 1, &captureRequest, NULL);
LOGI("Surface is prepared in here.\n"); ALOGI("Surface is prepared in here.\n");
return true; return true;
} }
@ -388,10 +417,10 @@ void CPhoneDevice2::ImageCallback(AImageReader *reader)
{ {
int32_t srcFormat = -1; int32_t srcFormat = -1;
AImage_getFormat(image, &srcFormat); AImage_getFormat(image, &srcFormat);
ASSERT(AIMAGE_FORMAT_YUV_420_888 == srcFormat, "Failed to get format"); AASSERT(AIMAGE_FORMAT_YUV_420_888 == srcFormat, "Failed to get format");
int32_t srcPlanes = 0; int32_t srcPlanes = 0;
AImage_getNumberOfPlanes(image, &srcPlanes); AImage_getNumberOfPlanes(image, &srcPlanes);
ASSERT(srcPlanes == 3, "Is not 3 planes"); AASSERT(srcPlanes == 3, "Is not 3 planes");
AImageCropRect srcRect; AImageCropRect srcRect;
AImage_getCropRect(image, &srcRect); AImage_getCropRect(image, &srcRect);
@ -474,10 +503,10 @@ bool CPhoneDevice2::WriteFile(AImage *image, const string& path)
int planeCount = 0; int planeCount = 0;
media_status_t status = AImage_getNumberOfPlanes(image, &planeCount); media_status_t status = AImage_getNumberOfPlanes(image, &planeCount);
LOGI("Info: getNumberOfPlanes() planeCount = %d", planeCount); ALOGI("Info: getNumberOfPlanes() planeCount = %d", planeCount);
if (!(status == AMEDIA_OK && planeCount == 1)) if (!(status == AMEDIA_OK && planeCount == 1))
{ {
LOGE("Error: getNumberOfPlanes() planeCount = %d", planeCount); ALOGE("Error: getNumberOfPlanes() planeCount = %d", planeCount);
return false; return false;
} }
@ -492,7 +521,7 @@ bool CPhoneDevice2::WriteFile(AImage *image, const string& path)
fwrite(data, 1, len, file); fwrite(data, 1, len, file);
fclose(file); fclose(file);
LOGI("Capture: %s", path.c_str()); ALOGI("Capture: %s", path.c_str());
res = true; res = true;
@ -545,7 +574,7 @@ bool CPhoneDevice2::MatchCaptureSizeRequest(ACameraManager *cameraManager, const
if (format == AIMAGE_FORMAT_YUV_420_888 || format == AIMAGE_FORMAT_JPEG) { if (format == AIMAGE_FORMAT_YUV_420_888 || format == AIMAGE_FORMAT_JPEG) {
DisplayDimension res(entry.data.i32[i + 1], entry.data.i32[i + 2]); DisplayDimension res(entry.data.i32[i + 1], entry.data.i32[i + 2]);
LOGI("Camera Resolution: %d x %d fmt=%d", res.width(), res.height(), format); ALOGI("Camera Resolution: %d x %d fmt=%d", res.width(), res.height(), format);
if (!disp.IsSameRatio(res)) continue; if (!disp.IsSameRatio(res)) continue;
if (format == AIMAGE_FORMAT_YUV_420_888 && res > disp) { if (format == AIMAGE_FORMAT_YUV_420_888 && res > disp) {
foundIt = true; foundIt = true;
@ -562,7 +591,7 @@ bool CPhoneDevice2::MatchCaptureSizeRequest(ACameraManager *cameraManager, const
resCap->width = foundRes.org_width(); resCap->width = foundRes.org_width();
resCap->height = foundRes.org_height(); resCap->height = foundRes.org_height();
} else { } else {
LOGI("Did not find any compatible camera resolution, taking 640x480"); ALOGI("Did not find any compatible camera resolution, taking 640x480");
resCap->width = disp.org_width(); resCap->width = disp.org_width();
resCap->height = disp.org_height(); resCap->height = disp.org_height();
// *resCap = *resView; // *resCap = *resView;
@ -583,16 +612,16 @@ bool CPhoneDevice2::MatchCaptureSizeRequest(ACameraManager *cameraManager, const
* it will be deleted via {@link AImage_delete} * it will be deleted via {@link AImage_delete}
*/ */
bool CPhoneDevice2::DisplayImage(ANativeWindow_Buffer *buf, AImage *image) { bool CPhoneDevice2::DisplayImage(ANativeWindow_Buffer *buf, AImage *image) {
ASSERT(buf->format == WINDOW_FORMAT_RGBX_8888 || AASSERT(buf->format == WINDOW_FORMAT_RGBX_8888 ||
buf->format == WINDOW_FORMAT_RGBA_8888, buf->format == WINDOW_FORMAT_RGBA_8888,
"Not supported buffer format"); "Not supported buffer format");
int32_t srcFormat = -1; int32_t srcFormat = -1;
AImage_getFormat(image, &srcFormat); AImage_getFormat(image, &srcFormat);
ASSERT(AIMAGE_FORMAT_YUV_420_888 == srcFormat, "Failed to get format"); AASSERT(AIMAGE_FORMAT_YUV_420_888 == srcFormat, "Failed to get format");
int32_t srcPlanes = 0; int32_t srcPlanes = 0;
AImage_getNumberOfPlanes(image, &srcPlanes); AImage_getNumberOfPlanes(image, &srcPlanes);
ASSERT(srcPlanes == 3, "Is not 3 planes"); AASSERT(srcPlanes == 3, "Is not 3 planes");
switch (presentRotation_) { switch (presentRotation_) {
case 0: case 0:
@ -608,7 +637,7 @@ bool CPhoneDevice2::DisplayImage(ANativeWindow_Buffer *buf, AImage *image) {
PresentImage270(buf, image); PresentImage270(buf, image);
break; break;
default: default:
ASSERT(0, "NOT recognized display rotation: %d", presentRotation_); AASSERT(0, "NOT recognized display rotation: %d", presentRotation_);
} }
AImage_delete(image); AImage_delete(image);
@ -857,27 +886,27 @@ bool CPhoneDevice2::SendBroadcastMessage(String16 action, int value)
void CPhoneDevice2::camera_device_on_disconnected(void *context, ACameraDevice *device) void CPhoneDevice2::camera_device_on_disconnected(void *context, ACameraDevice *device)
{ {
LOGI("Camera(id: %s) is diconnected.\n", ACameraDevice_getId(device)); ALOGI("Camera(id: %s) is diconnected.\n", ACameraDevice_getId(device));
CPhoneDevice2* pThis = (CPhoneDevice2*)context; CPhoneDevice2* pThis = (CPhoneDevice2*)context;
// delete pThis; // delete pThis;
} }
void CPhoneDevice2::camera_device_on_error(void *context, ACameraDevice *device, int error) void CPhoneDevice2::camera_device_on_error(void *context, ACameraDevice *device, int error)
{ {
LOGI("Error(code: %d) on Camera(id: %s).\n", error, ACameraDevice_getId(device)); ALOGI("Error(code: %d) on Camera(id: %s).\n", error, ACameraDevice_getId(device));
} }
void CPhoneDevice2::capture_session_on_ready(void *context, ACameraCaptureSession *session) void CPhoneDevice2::capture_session_on_ready(void *context, ACameraCaptureSession *session)
{ {
LOGI("Session is ready. %p\n", session); ALOGI("Session is ready. %p\n", session);
} }
void CPhoneDevice2::capture_session_on_active(void *context, ACameraCaptureSession *session) void CPhoneDevice2::capture_session_on_active(void *context, ACameraCaptureSession *session)
{ {
LOGI("Session is activated. %p\n", session); ALOGI("Session is activated. %p\n", session);
} }
void CPhoneDevice2::capture_session_on_closed(void *context, ACameraCaptureSession *session) void CPhoneDevice2::capture_session_on_closed(void *context, ACameraCaptureSession *session)
{ {
LOGI("Session is closed. %p\n", session); ALOGI("Session is closed. %p\n", session);
} }

@ -17,11 +17,6 @@
#include <camera/NdkCameraDevice.h> #include <camera/NdkCameraDevice.h>
#include <camera/NdkCameraMetadataTags.h> #include <camera/NdkCameraMetadataTags.h>
#include <media/NdkImageReader.h> #include <media/NdkImageReader.h>
#include <android/log.h>
// #define LOG_TAG "native-camera2-jni"
#define PD_LOG_TAG "PhoneDev"
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,PD_LOG_TAG,__VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,PD_LOG_TAG,__VA_ARGS__)
#include <Client/Device.h> #include <Client/Device.h>
#include <string> #include <string>

@ -1,16 +1,22 @@
#include "TerminalDevice.h" #include "TerminalDevice.h"
#include <dlfcn.h> #include <dlfcn.h>
#include "Camera.h" #include "Camera.h"
#include <AndroidHelper.h>
typedef jbyteArray (*TakePhotoFunc)(int, int, int, int); typedef jbyteArray (*TakePhotoFunc)(int, int, int, int);
extern bool GetJniEnv(JavaVM *vm, JNIEnv **env); extern bool GetJniEnv(JavaVM *vm, JNIEnv **env, bool& didAttachThread);
CTerminalDevice::CTerminalDevice(JavaVM* vm, jobject service) CTerminalDevice::CTerminalDevice(JavaVM* vm, jobject service)
{ {
m_vm = vm; m_vm = vm;
JNIEnv* env = NULL; JNIEnv* env = NULL;
bool attached = GetJniEnv(m_vm, &env); bool attached = false;
bool res = GetJniEnv(m_vm, &env, attached);
if (!res)
{
ALOGE("Failed to get JNI Env");
}
m_javaService = env->NewGlobalRef(service); m_javaService = env->NewGlobalRef(service);
if (attached) if (attached)
{ {
@ -21,7 +27,12 @@ CTerminalDevice::CTerminalDevice(JavaVM* vm, jobject service)
CTerminalDevice::~CTerminalDevice() CTerminalDevice::~CTerminalDevice()
{ {
JNIEnv* env = NULL; JNIEnv* env = NULL;
bool attached = GetJniEnv(m_vm, &env); bool attached = false;
bool res = GetJniEnv(m_vm, &env, attached);
if (!res)
{
ALOGE("Failed to get JNI Env");
}
env->DeleteGlobalRef(m_javaService); env->DeleteGlobalRef(m_javaService);
if (attached) if (attached)
{ {

@ -17,6 +17,24 @@
#ifndef __CAMERA2_HELPER_H__ #ifndef __CAMERA2_HELPER_H__
#define __CAMERA2_HELPER_H__ #define __CAMERA2_HELPER_H__
template <typename T>
class RangeValue {
public:
T min_, max_;
/**
* return absolute value from relative value
* value: in percent (50 for 50%)
*/
T value(int percent) {
return static_cast<T>(min_ + (max_ - min_) * percent / 100);
}
RangeValue() { min_ = max_ = static_cast<T>(0); }
bool Supported(void) const { return (min_ != max_); }
};
struct ImageFormat { struct ImageFormat {
int32_t width; int32_t width;
int32_t height; int32_t height;

@ -20,6 +20,7 @@
#include <opencv2/core/core.hpp> #include <opencv2/core/core.hpp>
#include "mat.h" #include "mat.h"
#include "Camera2Helper.h" #include "Camera2Helper.h"
#include <AndroidHelper.h>
static void onDisconnected(void* context, ACameraDevice* device) static void onDisconnected(void* context, ACameraDevice* device)
{ {
@ -70,7 +71,7 @@ void onCaptureSequenceAborted(void* context, ACameraCaptureSession* session, int
void onCaptureCompleted(void* context, ACameraCaptureSession* session, ACaptureRequest* request, const ACameraMetadata* result) void onCaptureCompleted(void* context, ACameraCaptureSession* session, ACaptureRequest* request, const ACameraMetadata* result)
{ {
__android_log_print(ANDROID_LOG_WARN, "NdkCamera", "onCaptureCompleted %p %p %p", session, request, result); ((NdkCamera*)context)->onCaptureCompleted(session, request, result);
} }
NdkCamera::NdkCamera(int32_t width, int32_t height) NdkCamera::NdkCamera(int32_t width, int32_t height)
@ -82,6 +83,10 @@ NdkCamera::NdkCamera(int32_t width, int32_t height)
mWidth = width; mWidth = width;
mHeight = height; mHeight = height;
hdrSupported = false;
nightModeSupported = false;
nightPortraitModeSupported = false;
camera_manager = 0; camera_manager = 0;
camera_device = 0; camera_device = 0;
image_reader = 0; image_reader = 0;
@ -202,6 +207,64 @@ int NdkCamera::open(const char* cameraId)
} }
{
ACameraMetadata_const_entry val = { 0 };
camera_status_t status = ACameraMetadata_getConstEntry(camera_metadata, ACAMERA_SENSOR_INFO_EXPOSURE_TIME_RANGE, &val);
if (status == ACAMERA_OK) {
exposureRange.min_ = val.data.i64[0];
if (exposureRange.min_ < kMinExposureTime) {
exposureRange.min_ = kMinExposureTime;
}
exposureRange.max_ = val.data.i64[1];
if (exposureRange.max_ > kMaxExposureTime) {
exposureRange.max_ = kMaxExposureTime;
}
// exposureTime = exposureRange.value(2);
} else {
ALOGW("Unsupported ACAMERA_SENSOR_INFO_EXPOSURE_TIME_RANGE");
exposureRange.min_ = exposureRange.max_ = 0l;
// exposureTime_ = 0l;
}
}
{
ACameraMetadata_const_entry val = { 0 };
camera_status_t status = ACameraMetadata_getConstEntry(camera_metadata, ACAMERA_SENSOR_INFO_SENSITIVITY_RANGE, &val);
if (status == ACAMERA_OK) {
sensitivityRange.min_ = val.data.i32[0];
sensitivityRange.max_ = val.data.i32[1];
// sensitivity = sensitivityRange.value(2);
} else {
ALOGW("failed for ACAMERA_SENSOR_INFO_SENSITIVITY_RANGE");
sensitivityRange.min_ = sensitivityRange.max_ = 0;
// sensitivity_ = 0;
}
}
{
ACameraMetadata_const_entry e = { 0 };
ACameraMetadata_getConstEntry(camera_metadata, ACAMERA_CONTROL_AVAILABLE_SCENE_MODES, &e);
for (int i = 0; i < e.count; i ++) {
if (ACAMERA_CONTROL_SCENE_MODE_HDR == e.data.u8[i])
{
hdrSupported = true;
break;
}
else if (ACAMERA_CONTROL_SCENE_MODE_NIGHT == e.data.u8[i])
{
nightModeSupported = true;
}
else if (ACAMERA_CONTROL_SCENE_MODE_NIGHT_PORTRAIT == e.data.u8[i])
{
nightPortraitModeSupported = true;
}
}
}
ACameraMetadata_free(camera_metadata); ACameraMetadata_free(camera_metadata);
@ -216,6 +279,11 @@ int NdkCamera::open(const char* cameraId)
return 1; return 1;
} }
if (camera_id == "1")
{
camera_facing = 1;
}
mCameraId = camera_id; mCameraId = camera_id;
camera_status_t res = ACAMERA_OK; camera_status_t res = ACAMERA_OK;
@ -257,6 +325,49 @@ int NdkCamera::open(const char* cameraId)
{ {
res = ACameraDevice_createCaptureRequest(camera_device, TEMPLATE_STILL_CAPTURE, &capture_request); res = ACameraDevice_createCaptureRequest(camera_device, TEMPLATE_STILL_CAPTURE, &capture_request);
int32_t fpsRange[2] = {10,15};
res = ACaptureRequest_setEntry_i32(capture_request, ACAMERA_CONTROL_AE_TARGET_FPS_RANGE,2,fpsRange);
bool usingAE = true;
if (usingAE) {
uint8_t aeModeOff = ACAMERA_CONTROL_AE_MODE_ON;
ACaptureRequest_setEntry_u8(capture_request, ACAMERA_CONTROL_AE_MODE, 1, &aeModeOff);
// ACaptureRequest_setEntry_i32(capture_request, ACAMERA_SENSOR_SENSITIVITY, 1, &sensitivity_);
uint8_t aeLockOff = ACAMERA_CONTROL_AE_LOCK_OFF;
ACaptureRequest_setEntry_u8(capture_request, ACAMERA_CONTROL_AE_LOCK, 1, &aeLockOff);
} else {
uint8_t aeModeOff = ACAMERA_CONTROL_AE_MODE_OFF;
res = ACaptureRequest_setEntry_u8(capture_request, ACAMERA_CONTROL_AE_MODE, 1, &aeModeOff);
uint8_t hdrMode = ACAMERA_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_HDR10; // ACAMERA_CONTROL_SCENE_MODE_HDR
res = ACaptureRequest_setEntry_u8(capture_request, ACAMERA_CONTROL_SCENE_MODE_HDR, 1, &hdrMode);
int32_t sensitivity = sensitivityRange.value(2);
res = ACaptureRequest_setEntry_i32(capture_request,ACAMERA_SENSOR_SENSITIVITY, 1, &sensitivity);
int64_t exposureTime = exposureRange.value(5);
res = ACaptureRequest_setEntry_i64(capture_request, ACAMERA_SENSOR_EXPOSURE_TIME, 1, &exposureTime);
}
if (hdrSupported) {
uint8_t hdrMode = ACAMERA_CONTROL_SCENE_MODE_HDR; // ACAMERA_CONTROL_SCENE_MODE_HDR
// res = ACaptureRequest_setEntry_u8(capture_request, ACAMERA_CONTROL_SCENE_MODE_HDR, 1, &hdrMode);
res = ACaptureRequest_setEntry_u8(capture_request, ACAMERA_CONTROL_SCENE_MODE, 1, &hdrMode);
}
if (nightModeSupported) {
uint8_t modeEnabled = 1; // ACAMERA_CONTROL_SCENE_MODE_HDR
res = ACaptureRequest_setEntry_u8(capture_request, ACAMERA_CONTROL_SCENE_MODE_NIGHT, 1, &modeEnabled);
}
if (nightPortraitModeSupported) {
uint8_t modeEnabled = 1; // ACAMERA_CONTROL_SCENE_MODE_HDR
res = ACaptureRequest_setEntry_u8(capture_request, ACAMERA_CONTROL_SCENE_MODE_NIGHT_PORTRAIT, 1, &modeEnabled);
}
res = ACameraOutputTarget_create(image_reader_surface, &image_reader_target); res = ACameraOutputTarget_create(image_reader_surface, &image_reader_target);
res = ACaptureRequest_addTarget(capture_request, image_reader_target); res = ACaptureRequest_addTarget(capture_request, image_reader_target);
} }
@ -281,7 +392,7 @@ int NdkCamera::open(const char* cameraId)
camera_capture_session_capture_callbacks.context = this; camera_capture_session_capture_callbacks.context = this;
camera_capture_session_capture_callbacks.onCaptureStarted = 0; camera_capture_session_capture_callbacks.onCaptureStarted = 0;
camera_capture_session_capture_callbacks.onCaptureProgressed = 0; camera_capture_session_capture_callbacks.onCaptureProgressed = 0;
camera_capture_session_capture_callbacks.onCaptureCompleted = onCaptureCompleted; camera_capture_session_capture_callbacks.onCaptureCompleted = ::onCaptureCompleted;
camera_capture_session_capture_callbacks.onCaptureFailed = onCaptureFailed; camera_capture_session_capture_callbacks.onCaptureFailed = onCaptureFailed;
camera_capture_session_capture_callbacks.onCaptureSequenceCompleted = onCaptureSequenceCompleted; camera_capture_session_capture_callbacks.onCaptureSequenceCompleted = onCaptureSequenceCompleted;
camera_capture_session_capture_callbacks.onCaptureSequenceAborted = onCaptureSequenceAborted; camera_capture_session_capture_callbacks.onCaptureSequenceAborted = onCaptureSequenceAborted;
@ -442,8 +553,6 @@ void NdkCamera::onImageAvailable(AImageReader* reader)
} }
AImage_delete(image); AImage_delete(image);
ACameraCaptureSession_stopRepeating(capture_session);
} }
void NdkCamera::on_error(const std::string& msg) const void NdkCamera::on_error(const std::string& msg) const
@ -515,3 +624,26 @@ void NdkCamera::on_image(const unsigned char* nv21, int nv21_width, int nv21_hei
on_image(rgb); on_image(rgb);
} }
void NdkCamera::onCaptureCompleted(ACameraCaptureSession* session, ACaptureRequest* request, const ACameraMetadata* result)
{
// CALL_REQUEST(setEntry_i64(requests_[PREVIEW_REQUEST_IDX].request_,
// ACAMERA_SENSOR_EXPOSURE_TIME, 1, &exposureTime_));
// ACameraMetadata_getConstEntry(result, )
ACameraMetadata_const_entry val = { 0 };
camera_status_t status = ACameraMetadata_getConstEntry(result, ACAMERA_SENSOR_EXPOSURE_TIME, &val);
int64_t exTime = val.data.i64[0];
val = { 0 };
status = ACameraMetadata_getConstEntry(result, ACAMERA_CONTROL_AE_MODE, &val);
uint8_t aeMode = val.data.u8[0];
// ACaptureRequest_setEntry_i32(capture_request, ACAMERA_SENSOR_SENSITIVITY, 1, &sensitivity_);
ALOGD("onCaptureCompleted EXPOSURE_TIME=%lld, camera id=%s, AE=%s", val.data.i64[0], mCameraId.c_str(), ((aeMode == 1) ? 'ON' : 'OFF'));
// __android_log_print(ANDROID_LOG_WARN, "NdkCamera", "onCaptureCompleted %p %p %p", session, request, result);
}

@ -21,10 +21,23 @@
#include <media/NdkImageReader.h> #include <media/NdkImageReader.h>
#include <opencv2/core/core.hpp> #include <opencv2/core/core.hpp>
#include "Camera2Helper.h"
/**
* Range of Camera Exposure Time:
* Camera's capability range have a very long range which may be disturbing
* on camera. For this sample purpose, clamp to a range showing visible
* video on preview: 100000ns ~ 250000000ns
*/
static const uint64_t kMinExposureTime = static_cast<uint64_t>(1000000);
static const uint64_t kMaxExposureTime = static_cast<uint64_t>(250000000);
class NdkCamera class NdkCamera
{ {
public: public:
NdkCamera(int32_t width, int32_t height); NdkCamera(int32_t width, int32_t height);
virtual ~NdkCamera(); virtual ~NdkCamera();
@ -38,6 +51,9 @@ public:
virtual void on_image(const unsigned char* nv21, int nv21_width, int nv21_height) const; virtual void on_image(const unsigned char* nv21, int nv21_width, int nv21_height) const;
void onCaptureCompleted(ACameraCaptureSession* session, ACaptureRequest* request, const ACameraMetadata* result);
public: public:
int camera_facing; int camera_facing;
int camera_orientation; int camera_orientation;
@ -46,6 +62,15 @@ public:
int32_t mHeight; int32_t mHeight;
std::string mCameraId; std::string mCameraId;
bool hdrSupported;
bool nightModeSupported;
bool nightPortraitModeSupported;
// int64_t exposureTime_;
RangeValue<int64_t> exposureRange;
// int32_t sensitivity_;
RangeValue<int32_t> sensitivityRange;
private: private:
ACameraManager* camera_manager; ACameraManager* camera_manager;
ACameraDevice* camera_device; ACameraDevice* camera_device;

@ -50,9 +50,14 @@ public class FloatingWindow extends Service {
@Override @Override
public void onDestroy() { public void onDestroy() {
try {
if (mView != null) { if (mView != null) {
mWindowManager.removeView(mView); mWindowManager.removeView(mView);
} }
} catch (Exception ex) {
ex.printStackTrace();
}
super.onDestroy(); super.onDestroy();
} }

@ -5,6 +5,7 @@ import android.annotation.SuppressLint;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.graphics.Path;
import android.graphics.SurfaceTexture; import android.graphics.SurfaceTexture;
import android.hardware.Camera; import android.hardware.Camera;
import android.os.Build; import android.os.Build;
@ -19,6 +20,7 @@ import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle; import android.os.Bundle;
import android.telephony.SubscriptionManager; import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager; import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.Log; import android.util.Log;
import android.view.Display; import android.view.Display;
import android.view.View; import android.view.View;
@ -46,8 +48,6 @@ import org.json.JSONException;
import org.json.JSONObject; import org.json.JSONObject;
public class MainActivity extends AppCompatActivity { public class MainActivity extends AppCompatActivity {
public static final String TAG = "MainActivity"; public static final String TAG = "MainActivity";
private static int MY_PERMISSIONS_REQUEST_FOREGROUND_SERVICE = 100; private static int MY_PERMISSIONS_REQUEST_FOREGROUND_SERVICE = 100;
@ -55,22 +55,18 @@ public class MainActivity extends AppCompatActivity {
static { static {
System.loadLibrary("microphoto"); System.loadLibrary("microphoto");
} }
private ActivityMainBinding binding; private ActivityMainBinding binding;
private int defaultDataSubId; private int defaultDataSubId;
@Override @Override
protected void onDestroy() { protected void onDestroy() {
super.onDestroy(); super.onDestroy();
} }
protected class AppConfig { protected class AppConfig {
public String cmdid; public String cmdid;
public String server; public String server;
public int port; public int port;
public int protocol; public int protocol;
} }
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
@ -84,7 +80,6 @@ public class MainActivity extends AppCompatActivity {
int width = defaultDisplay.getWidth(); int width = defaultDisplay.getWidth();
int height = defaultDisplay.getHeight(); int height = defaultDisplay.getHeight();
Log.d(TAG, "Screen Size: " + width + " x " + height); Log.d(TAG, "Screen Size: " + width + " x " + height);
String cmdid = "0123456789ABCDEFG"; String cmdid = "0123456789ABCDEFG";
@ -96,7 +91,6 @@ public class MainActivity extends AppCompatActivity {
binding.cmdid.setText(appConfig.cmdid); binding.cmdid.setText(appConfig.cmdid);
binding.server.setText(appConfig.server); binding.server.setText(appConfig.server);
binding.port.setText(Integer.toString(appConfig.port)); binding.port.setText(Integer.toString(appConfig.port));
this.binding.startServBtn.setOnClickListener(new View.OnClickListener() { this.binding.startServBtn.setOnClickListener(new View.OnClickListener() {
@Override @Override
public void onClick(View view) { public void onClick(View view) {
@ -154,36 +148,28 @@ public class MainActivity extends AppCompatActivity {
binding.stopServBtn.setEnabled(true); binding.stopServBtn.setEnabled(true);
} }
}); });
this.binding.takePhotoBtn.setOnClickListener(new View.OnClickListener() { this.binding.takePhotoBtn.setOnClickListener(new View.OnClickListener() {
@Override @Override
public void onClick(View view) { public void onClick(View view) {
MicroPhotoService.takePhoto(MainActivity.this, 1, 255, true); MicroPhotoService.takePhoto(MainActivity.this.getApplicationContext(), 1, 255, true);
// setDefaultDataSubId(1);
} }
}); });
this.binding.takePhotoBtn2.setOnClickListener(new View.OnClickListener() { this.binding.takePhotoBtn2.setOnClickListener(new View.OnClickListener() {
@Override @Override
public void onClick(View view) { public void onClick(View view) {
MicroPhotoService.takePhoto(MainActivity.this, 2, 255, true); MicroPhotoService.takePhoto(MainActivity.this, 2, 255, true);
// setDefaultDataSubId(2);
} }
}); });
this.binding.takePhotoBtn3.setOnClickListener(new View.OnClickListener() { this.binding.takePhotoBtn3.setOnClickListener(new View.OnClickListener() {
@Override @Override
public void onClick(View view) { public void onClick(View view) {
MicroPhotoService.takePhoto(MainActivity.this, 3, 255, true); MicroPhotoService.takePhoto(MainActivity.this, 3, 255, true);
// setDefaultDataSubId(2);
} }
}); });
this.binding.takePhotoBtn4.setOnClickListener(new View.OnClickListener() { this.binding.takePhotoBtn4.setOnClickListener(new View.OnClickListener() {
@Override @Override
public void onClick(View view) { public void onClick(View view) {
MicroPhotoService.takePhoto(MainActivity.this, 4, 255, true); MicroPhotoService.takePhoto(MainActivity.this, 4, 255, true);
// setDefaultDataSubId(2);
} }
}); });
@ -225,14 +211,20 @@ public class MainActivity extends AppCompatActivity {
} }
}); });
if (!TextUtils.isEmpty(appConfig.cmdid) && !TextUtils.isEmpty(appConfig.server) && appConfig.port != 0) {
Handler handler = new Handler(); Handler handler = new Handler();
Runnable runnable = new Runnable() { Runnable runnable = new Runnable() {
@Override @Override
public void run() { public void run() {
// binding.startServBtn.performClick(); if (binding.startServBtn.isEnabled()) {
binding.startServBtn.performClick();
}
} }
}; };
handler.postDelayed(runnable, 1000); handler.postDelayed(runnable, 5000);
}
} }
private void setDefaultDataSubId(int subId) { private void setDefaultDataSubId(int subId) {
@ -256,7 +248,7 @@ public class MainActivity extends AppCompatActivity {
InputStreamReader inputStreamReader = null; InputStreamReader inputStreamReader = null;
try { try {
inputStreamReader = new InputStreamReader(new FileInputStream(new File(appPath + "App.json")), "UTF-8"); inputStreamReader = new InputStreamReader(new FileInputStream(new File(appPath + "data/App.json")), "UTF-8");
BufferedReader bufferedReader = new BufferedReader(inputStreamReader); BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
String line; String line;
StringBuilder stringBuilder = new StringBuilder(); StringBuilder stringBuilder = new StringBuilder();

@ -1,6 +1,5 @@
package com.xinyingpower.microphoto; package com.xinyingpower.microphoto;
import android.Manifest;
import android.app.AlarmManager; import android.app.AlarmManager;
import android.app.Notification; import android.app.Notification;
import android.app.NotificationChannel; import android.app.NotificationChannel;
@ -11,25 +10,14 @@ import android.content.BroadcastReceiver;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.IntentFilter; import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Environment;
import android.os.IBinder; import android.os.IBinder;
import android.os.PowerManager; import android.os.PowerManager;
import android.os.SystemClock; import android.os.SystemClock;
import androidx.core.app.ActivityCompat;
import androidx.core.app.NotificationCompat; import androidx.core.app.NotificationCompat;
import android.telephony.CellLocation;
import android.telephony.PhoneStateListener;
import android.telephony.ServiceState;
import android.telephony.SignalStrength;
import android.telephony.SubscriptionManager; import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager; import android.telephony.TelephonyManager;
import android.telephony.cdma.CdmaCellLocation;
import android.telephony.gsm.GsmCellLocation;
import android.text.TextUtils; import android.text.TextUtils;
import android.text.format.DateFormat; import android.text.format.DateFormat;
import android.util.Log; import android.util.Log;
@ -43,7 +31,6 @@ import java.time.format.DateTimeFormatter;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Date; import java.util.Date;
import java.util.HashMap; import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@ -54,63 +41,45 @@ public class MicroPhotoService extends Service {
static { static {
System.loadLibrary("microphoto"); System.loadLibrary("microphoto");
} }
private static final String ALARM_EVENT = "com.xinyingpower.mp.MicroPhotoService.AlarmReceiver";
private static String ALARM_EVENT = "com.xinyingpower.mp.MicroPhotoService.AlarmReceiver";
public static final int NOTIFICATION_ID_FOREGROUND_SERVICE = 8466503; public static final int NOTIFICATION_ID_FOREGROUND_SERVICE = 8466503;
public static final String ACTION_START = "ACT_START"; public static final String ACTION_START = "ACT_START";
public static final String ACTION_STOP = "ACT_STOP"; public static final String ACTION_STOP = "ACT_STOP";
public static final String ACTION_MAIN = "ACT_MAIN"; public static final String ACTION_MAIN = "ACT_MAIN";
private static final String ACTION_HEARTBEAT = "ACT_HB";
private static String ACTION_HEARTBEAT = "ACT_HB"; private static final String ACTION_TAKE_PHOTO = "ACT_TP";
private static String ACTION_TAKE_PHOTO = "ACT_TP"; private static final String ACTION_TAKE_PHOTO_MANUALLY = "ACT_TP_M";
private static String ACTION_TAKE_PHOTO_MANUALLY = "ACT_TP_M"; private static final String ACTION_TIMEOUT = "ACT_TIMEOUT";
private static final String EXTRA_PARAM_CHANNEL = "Channel";
private static String ACTION_TIMEOUT = "ACT_TIMEOUT"; private static final String EXTRA_PARAM_PRESET = "Preset";
private static final String EXTRA_PARAM_PHOTO_OR_VIDEO = "PhotoOrVideo";
private static String EXTRA_PARAM_CHANNEL = "Channel"; private static final String EXTRA_PARAM_SCHEDULES = "Schedules";
private static String EXTRA_PARAM_PRESET = "Preset"; private static final String EXTRA_PARAM_SCHEDULE = "Schedule_";
private static String EXTRA_PARAM_PHOTO_OR_VIDEO = "PhotoOrVideo"; private static final String EXTRA_PARAM_TIME = "Time";
private static String EXTRA_PARAM_SCHEDULES = "Schedules";
private static String EXTRA_PARAM_SCHEDULE = "Schedule_";
private static String EXTRA_PARAM_TIME = "Time";
// private static String EXTRA_PARAM_FILENAME = "FileName"; // private static String EXTRA_PARAM_FILENAME = "FileName";
private static final String EXTRA_PARAM_TIMER_UID = "TimerUid";
private static String EXTRA_PARAM_TIMER_UID = "TimerUid";
// private static String EXTRA_PARAM_TIMER_TYPE = "TimerType"; // private static String EXTRA_PARAM_TIMER_TYPE = "TimerType";
private static String EXTRA_PARAM_TIMEOUT = "Timeout"; private static final String EXTRA_PARAM_TIMEOUT = "Timeout";
private static final String EXTRA_PARAM_TIMES = "Times";
private final static String FOREGROUND_CHANNEL_ID = "foreground_channel_id"; private static final String EXTRA_PARAM_ELASPED_TIMES = "ElapsedTimes";
private static final String FOREGROUND_CHANNEL_ID = "foreground_channel_id";
public static class STATE_SERVICE { public static class STATE_SERVICE {
public static final int CONNECTED = 10; public static final int CONNECTED = 10;
public static final int NOT_CONNECTED = 0; public static final int NOT_CONNECTED = 0;
} }
private NotificationManager mNotificationManager; private NotificationManager mNotificationManager;
private final Map<String, PowerManager.WakeLock> mWakeLocks = new HashMap<>();
private Map<String, PowerManager.WakeLock> mWakeLocks = new HashMap<>();
private int mHeartbeatDuration = 0; // 5m: 5 * 60 * 1000 private int mHeartbeatDuration = 0; // 5m: 5 * 60 * 1000
private long mNextHeartbeatTime = 0; private long mNextHeartbeatTime = 0;
private final Map<Long, PendingIntent> mTimers = new HashMap<>();
private Map<Long, PendingIntent> mTimers = new HashMap<>();
private static int stateService = STATE_SERVICE.NOT_CONNECTED; private static int stateService = STATE_SERVICE.NOT_CONNECTED;
public MicroPhotoService() { public MicroPhotoService() {
} }
@Override @Override
public IBinder onBind(Intent intent) { public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service. // TODO: Return the communication channel to the service.
throw new UnsupportedOperationException("Not yet implemented"); throw new UnsupportedOperationException("Not yet implemented");
} }
@Override @Override
public void onCreate() { public void onCreate() {
super.onCreate(); super.onCreate();
@ -121,6 +90,8 @@ public class MicroPhotoService extends Service {
DeviceUtil.getPhoneState(this.getApplicationContext()); DeviceUtil.getPhoneState(this.getApplicationContext());
alarmReceiver = new AlarmReceiver(this); alarmReceiver = new AlarmReceiver(this);
screenactionreceiver = new ScreenActionReceiver();
// 注册广播接受者 // 注册广播接受者
IntentFilter intentFilter = new IntentFilter(ACTION_HEARTBEAT); IntentFilter intentFilter = new IntentFilter(ACTION_HEARTBEAT);
intentFilter.addAction(ACTION_TAKE_PHOTO); intentFilter.addAction(ACTION_TAKE_PHOTO);
@ -136,19 +107,20 @@ public class MicroPhotoService extends Service {
break; break;
} }
/*
if (aci.getShowIntent().isBroadcast()) { if (aci.getShowIntent().isBroadcast()) {
// alarmManager.cancel(aci.getShowIntent()); // alarmManager.cancel(aci.getShowIntent());
} }
*/
} }
// alarmManager.cancel(); // alarmManager.cancel();
boolean res = false; // boolean res = false;
// Environment.getExternalStoragePublicDirectory(String) // Environment.getExternalStoragePublicDirectory(String)
// registerHeartbeatTimer(getHeartbeatDuration()); // registerHeartbeatTimer(getHeartbeatDuration());
} }
@Override @Override
public void onDestroy() { public void onDestroy() {
@ -158,6 +130,7 @@ public class MicroPhotoService extends Service {
mHandler = 0; mHandler = 0;
unregisterReceiver(alarmReceiver); unregisterReceiver(alarmReceiver);
unregisterReceiver(screenactionreceiver);
for(Map.Entry<String, PowerManager.WakeLock> entry : mWakeLocks.entrySet()) { for(Map.Entry<String, PowerManager.WakeLock> entry : mWakeLocks.entrySet()) {
entry.getValue().release(); entry.getValue().release();
@ -166,22 +139,18 @@ public class MicroPhotoService extends Service {
super.onDestroy(); super.onDestroy();
} }
public static class AlarmReceiver extends BroadcastReceiver { public static class AlarmReceiver extends BroadcastReceiver {
private MicroPhotoService mService; private MicroPhotoService mService;
public AlarmReceiver() { public AlarmReceiver() {
mService = null; mService = null;
} }
public AlarmReceiver(MicroPhotoService service) { public AlarmReceiver(MicroPhotoService service) {
mService = service; mService = service;
} }
public void onReceive(Context context, Intent intent) { public void onReceive(Context context, Intent intent) {
String action = intent.getAction(); String action = intent.getAction();
if (TextUtils.equals(ACTION_HEARTBEAT, action)) { if (TextUtils.equals(ACTION_HEARTBEAT, action)) {
Log.i(TAG, "receiver ACTION=" + action); Log.i(TAG, "HB Timer Fired ACTION=" + action);
mService.sendHeartbeat(mService.mHandler); mService.sendHeartbeat(mService.mHandler);
mService.registerHeartbeatTimer(); mService.registerHeartbeatTimer();
} else if (TextUtils.equals(ACTION_TAKE_PHOTO, action)) { } else if (TextUtils.equals(ACTION_TAKE_PHOTO, action)) {
@ -194,6 +163,7 @@ public class MicroPhotoService extends Service {
int channel = (int) ((val & 0xFF0000L) >> 16); int channel = (int) ((val & 0xFF0000L) >> 16);
int preset = (int) ((val & 0xFF00L) >> 8); int preset = (int) ((val & 0xFF00L) >> 8);
Log.i(TAG, "PhotoTimer Fired: CH=" + channel + " PR=" + preset);
mService.notifyToTakePhoto(mService.mHandler, channel, preset, ts, mService.buildPhotoDir(mService.getApplicationContext(), channel), mService.buildPhotoFileName(channel, preset, ts), true); mService.notifyToTakePhoto(mService.mHandler, channel, preset, ts, mService.buildPhotoDir(mService.getApplicationContext(), channel), mService.buildPhotoFileName(channel, preset, ts), true);
} }
} }
@ -215,24 +185,34 @@ public class MicroPhotoService extends Service {
boolean photoOrVideo = intent.getBooleanExtra(EXTRA_PARAM_PHOTO_OR_VIDEO, true); boolean photoOrVideo = intent.getBooleanExtra(EXTRA_PARAM_PHOTO_OR_VIDEO, true);
long ts = System.currentTimeMillis() / 1000; long ts = System.currentTimeMillis() / 1000;
Log.i(TAG, "Take Photo CH=" + channel + " PR=" + preset); Log.i(TAG, "Take Photo CH=" + channel + " PR=" + preset + " Mannually");
mService.notifyToTakePhoto(mService.mHandler, channel, preset, ts, mService.buildPhotoDir(mService.getApplicationContext(), channel), mService.buildPhotoFileName(channel, preset, ts), photoOrVideo); mService.notifyToTakePhoto(mService.mHandler, channel, preset, ts, mService.buildPhotoDir(mService.getApplicationContext(), channel), mService.buildPhotoFileName(channel, preset, ts), photoOrVideo);
} else if (TextUtils.equals(ACTION_TIMEOUT, action)) { } else if (TextUtils.equals(ACTION_TIMEOUT, action)) {
long uid = intent.getLongExtra(EXTRA_PARAM_TIMER_UID, 0); long uid = intent.getLongExtra(EXTRA_PARAM_TIMER_UID, 0);
Log.i(TAG, "Timeout:" + uid); long expectedTimes = intent.getLongExtra(EXTRA_PARAM_TIMES, 0);
mService.fireTimeout(mService.mHandler, uid); long elapsedTimes = intent.getLongExtra(EXTRA_PARAM_ELASPED_TIMES, 0);
elapsedTimes++;
Log.i(TAG, "Timeout uid=" + uid + " expectedTimes=" + expectedTimes + " Times=" + elapsedTimes);
mService.fireTimeout(mService.mHandler, uid, elapsedTimes);
intent.putExtra(EXTRA_PARAM_ELASPED_TIMES, elapsedTimes);
int timeout = intent.getIntExtra(EXTRA_PARAM_TIMEOUT, 0);
Long uidObj = Long.valueOf(uid); Long uidObj = Long.valueOf(uid);
if ((expectedTimes == 0) || (elapsedTimes < expectedTimes)) {
int timeout = intent.getIntExtra(EXTRA_PARAM_TIMEOUT, 0);
PendingIntent pendingIntent = mService.mTimers.get(uidObj); PendingIntent pendingIntent = mService.mTimers.get(uidObj);
if (pendingIntent != null) { if (pendingIntent != null) {
mService.registerTimer(pendingIntent, uid, timeout); mService.registerTimer(pendingIntent, uid, timeout);
} }
} else {
mService.mTimers.remove(uidObj);
}
} }
} }
} }
private void registerHeartbeatTimer(int duration) { private void registerHeartbeatTimer(int duration) {
int orgHeartbeatDuration = mHeartbeatDuration; int orgHeartbeatDuration = mHeartbeatDuration;
mHeartbeatDuration = duration; mHeartbeatDuration = duration;
@ -241,7 +221,6 @@ public class MicroPhotoService extends Service {
} }
} }
private void registerHeartbeatTimer() { private void registerHeartbeatTimer() {
// 创建延迟意图 // 创建延迟意图
@ -256,7 +235,7 @@ public class MicroPhotoService extends Service {
// alarmManager.setExactAndAllowWhileIdle(AlarmManager.ELAPSED_REALTIME, SystemClock.elapsedRealtime() + timeout, pendingIntent); // alarmManager.setExactAndAllowWhileIdle(AlarmManager.ELAPSED_REALTIME, SystemClock.elapsedRealtime() + timeout, pendingIntent);
} }
private void registerPhotoTimer(int channel, int preset, long ts, long timeout, List<Long> schedules) { private static void registerPhotoTimer(Context context, int channel, int preset, long ts, long timeout, List<Long> schedules) {
// 创建延迟意图 // 创建延迟意图
Intent alarmIntent = new Intent(); Intent alarmIntent = new Intent();
@ -265,33 +244,39 @@ public class MicroPhotoService extends Service {
alarmIntent.putExtra(EXTRA_PARAM_SCHEDULES, cnt); alarmIntent.putExtra(EXTRA_PARAM_SCHEDULES, cnt);
String channelStr = ""; String channelStr = "";
for (int idx = 0; idx < cnt; idx++) { for (int idx = 0; idx < cnt; idx++) {
long val = schedules.get(idx).longValue();
alarmIntent.putExtra(EXTRA_PARAM_SCHEDULE + idx, schedules.get(idx).longValue()); alarmIntent.putExtra(EXTRA_PARAM_SCHEDULE + idx, schedules.get(idx).longValue());
channelStr += schedules.get(idx).toString() + " "; channelStr += "CH=" + ((val & 0XFF0000) >> 16) + "-PR=" + ((val & 0XFF00) >> 8) + " ";
} }
alarmIntent.putExtra(EXTRA_PARAM_TIME, ts); alarmIntent.putExtra(EXTRA_PARAM_TIME, ts);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, alarmIntent, PendingIntent.FLAG_UPDATE_CURRENT); PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, alarmIntent, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE); AlarmManager alarmManager = (AlarmManager) context.getSystemService(ALARM_SERVICE);
long currentTimeMillis = System.currentTimeMillis(); long currentTimeMillis = System.currentTimeMillis();
Date date = new Date(currentTimeMillis + timeout); Date date = new Date(currentTimeMillis + timeout);
String dateStr = (String) DateFormat.format("MM-dd kk:mm:ss", date); String dateStr = (String) DateFormat.format("MM-dd kk:mm:ss", date);
Log.d(TAG, "Register Photo Timer: " + dateStr + " currentTimeMillis=" + currentTimeMillis + " timeout=" + timeout + " Channels=" + channelStr); Log.d(TAG, "PhotoTimer Reg: " + dateStr + " currentTimeMillis=" + currentTimeMillis + " timeout=" + timeout + " Channels=" + channelStr);
alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + timeout, pendingIntent); alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + timeout, pendingIntent);
} }
private void registerPhotoTimer(int channel, int preset, long ts, long timeout, List<Long> schedules) {
// private HashMap<Long, Integer> mTimers = new HashMap<Long, Integer>(); registerPhotoTimer(this.getApplicationContext(), channel, preset, ts, timeout, schedules);
}
public boolean registerTimer(long uid, int timeout) { // private HashMap<Long, Integer> mTimers = new HashMap<Long, Integer>();
public boolean registerTimer(long uid, int timeout, long times) {
// 创建延迟意图 // 创建延迟意图
Intent alarmIntent = new Intent(); Intent alarmIntent = new Intent();
alarmIntent.setAction(ACTION_TIMEOUT); alarmIntent.setAction(ACTION_TIMEOUT);
alarmIntent.putExtra(EXTRA_PARAM_TIMER_UID, uid); alarmIntent.putExtra(EXTRA_PARAM_TIMER_UID, uid);
alarmIntent.putExtra(EXTRA_PARAM_TIMEOUT, timeout); alarmIntent.putExtra(EXTRA_PARAM_TIMEOUT, timeout);
alarmIntent.putExtra(EXTRA_PARAM_TIMES, times);
alarmIntent.putExtra(EXTRA_PARAM_ELASPED_TIMES, 0L);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, alarmIntent, PendingIntent.FLAG_UPDATE_CURRENT); PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, alarmIntent, PendingIntent.FLAG_UPDATE_CURRENT);
@ -311,7 +296,6 @@ public class MicroPhotoService extends Service {
Log.e(TAG, "wjz debug setDefaultDataSubId: error is " + e.getMessage()); Log.e(TAG, "wjz debug setDefaultDataSubId: error is " + e.getMessage());
} }
} }
private int getDefaultDataSubId() { private int getDefaultDataSubId() {
SubscriptionManager subscriptionManager = (SubscriptionManager) getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE); SubscriptionManager subscriptionManager = (SubscriptionManager) getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE);
try { try {
@ -322,7 +306,6 @@ public class MicroPhotoService extends Service {
} }
return 0; return 0;
} }
public boolean registerTimer(PendingIntent pendingIntent, long uid, int timeout) { public boolean registerTimer(PendingIntent pendingIntent, long uid, int timeout) {
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE); AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
@ -332,7 +315,6 @@ public class MicroPhotoService extends Service {
Log.i(TAG, "RegTimer:" + uid + " timeout=" + timeout); Log.i(TAG, "RegTimer:" + uid + " timeout=" + timeout);
return true; return true;
} }
public boolean unregisterTimer(long uid) { public boolean unregisterTimer(long uid) {
Long uidObj = Long.valueOf(uid); Long uidObj = Long.valueOf(uid);
@ -348,7 +330,6 @@ public class MicroPhotoService extends Service {
return true; return true;
} }
private boolean registerCaptureSchedule(long startTime, long baseTime) { private boolean registerCaptureSchedule(long startTime, long baseTime) {
long[] photoTimeData = getPhotoTimeData(mHandler); long[] photoTimeData = getPhotoTimeData(mHandler);
@ -386,7 +367,7 @@ public class MicroPhotoService extends Service {
schedules.add(Long.valueOf(val)); schedules.add(Long.valueOf(val));
Log.i(TAG, "Reg Photo Timer: CH=" + channel + " PR=" + preset); Log.i(TAG, "PhotoTimer Reg: CH=" + channel + " PR=" + preset);
} else if (ts > currentTs) { } else if (ts > currentTs) {
break; break;
} else { } else {
@ -394,7 +375,7 @@ public class MicroPhotoService extends Service {
channel = (short) ((val & 0xFF0000L) >> 16); channel = (short) ((val & 0xFF0000L) >> 16);
preset = (short) ((val & 0xFF00L) >> 8); preset = (short) ((val & 0xFF00L) >> 8);
Log.i(TAG, "Reg Photo Timer: CH=" + channel + " PR=" + preset); Log.i(TAG, "PhotoTimer Reg: CH=" + channel + " PR=" + preset);
schedules.add(Long.valueOf(val)); schedules.add(Long.valueOf(val));
} }
} }
@ -417,11 +398,14 @@ public class MicroPhotoService extends Service {
public static void takePhoto(Context context, int channel, int preset, boolean photoOrVideo) { public static void takePhoto(Context context, int channel, int preset, boolean photoOrVideo) {
Intent intent = new Intent(ACTION_TAKE_PHOTO_MANUALLY); List<Long> schedules = new ArrayList<>();
intent.putExtra(EXTRA_PARAM_CHANNEL, channel); long ts = System.currentTimeMillis() / 1000;
intent.putExtra(EXTRA_PARAM_PRESET, preset); long val = (ts << 24);
intent.putExtra(EXTRA_PARAM_PHOTO_OR_VIDEO, photoOrVideo); val |= ((long)channel << 16);
context.sendBroadcast(intent); val |= ((long)preset << 8);
schedules.add(Long.valueOf(val));
registerPhotoTimer(context, channel, preset, System.currentTimeMillis() / 1000, 0, schedules);
} }
@Override @Override
@ -441,20 +425,23 @@ public class MicroPhotoService extends Service {
connect(); connect();
registerReceiver(screenactionreceiver, screenactionreceiver.getFilter());
// File path = getApplicationContext().getFilesDir(); // File path = getApplicationContext().getFilesDir();
String appPath = buildAppDir(this.getApplicationContext()); String appPath = buildAppDir(this.getApplicationContext());
String ip = intent.getStringExtra("server"); String ip = intent.getStringExtra("server");
int port = intent.getIntExtra("port", 0); int port = intent.getIntExtra("port", 0);
String cmdid = intent.getStringExtra("cmdid"); String cmdid = intent.getStringExtra("cmdid");
int protocol = intent.getIntExtra("protocol", 0);
Log.i(TAG, "AppPath=" + appPath + " Server=" + ip + ":" + port + " cmdid=" + cmdid); Log.i(TAG, "AppPath=" + appPath + " Server=" + ip + ":" + port + " cmdid=" + cmdid + " protocol" + protocol);
mHandler = init(appPath, ip, port, cmdid); mHandler = init(appPath, ip, port, cmdid, protocol);
// Start the locker receiver // Start the locker receiver
registerReceiver(screenactionreceiver, screenactionreceiver.getFilter()); if (mHandler !=0) {
Date date = new Date(); Date date = new Date();
long nowTs = date.getTime() / 1000; long nowTs = date.getTime() / 1000;
date.setHours(0); date.setHours(0);
@ -465,6 +452,8 @@ public class MicroPhotoService extends Service {
registerCaptureSchedule(startTime, baseTime); registerCaptureSchedule(startTime, baseTime);
}
// registerPhotoTimer(); // registerPhotoTimer();
break; break;
case ACTION_STOP: case ACTION_STOP:
@ -483,7 +472,7 @@ public class MicroPhotoService extends Service {
public void requestWakelock(String name, long timeout) { public void requestWakelock(String name, long timeout) {
PowerManager powerManager = (PowerManager) getSystemService(POWER_SERVICE); PowerManager powerManager = (PowerManager) getSystemService(POWER_SERVICE);
PowerManager.WakeLock wl = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, name); PowerManager.WakeLock wl = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK | PowerManager.ON_AFTER_RELEASE, name);
PowerManager.WakeLock wl2 = null; PowerManager.WakeLock wl2 = null;
synchronized (mWakeLocks) { synchronized (mWakeLocks) {
wl2 = mWakeLocks.replace(name, wl); wl2 = mWakeLocks.replace(name, wl);
@ -578,7 +567,7 @@ public class MicroPhotoService extends Service {
.setContentIntent(pendingIntent); .setContentIntent(pendingIntent);
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) { if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
notificationBuilder.setVisibility(Notification.VISIBILITY_PUBLIC); notificationBuilder.setVisibility(NotificationCompat.VISIBILITY_PUBLIC);
} }
return notificationBuilder.build(); return notificationBuilder.build();
@ -655,16 +644,16 @@ CellSignalStrengthGsm cellSignalStrengthGsm = cellInfoGsm.getCellSignalStrength(
cellSignalStrengthGsm.getDbm(); cellSignalStrengthGsm.getDbm();
*/ */
protected native long init(String appPath, String ip, int port, String cmdid); protected native long init(String appPath, String ip, int port, String cmdid, int protocol);
protected native long getHeartbeatDuration(long handler); protected native long getHeartbeatDuration(long handler);
protected native long[] getPhotoTimeData(long handler); protected native long[] getPhotoTimeData(long handler);
// protected native long[] getNextScheduleItem(long handler); // protected native long[] getNextScheduleItem(long handler);
protected native boolean notifyToTakePhoto(long handler, int channel, int preset, long scheduleTime, String path, String fileName, boolean sendToCma); protected native boolean notifyToTakePhoto(long handler, int channel, int preset, long scheduleTime, String path, String fileName, boolean sendToCma);
protected native boolean sendHeartbeat(long handler); protected native boolean sendHeartbeat(long handler);
protected native boolean fireTimeout(long handler, long uid); protected native boolean fireTimeout(long handler, long uid, long times);
protected native boolean uninit(long handler); protected native boolean uninit(long handler);
protected long mHandler = 0; protected long mHandler = 0;
private AlarmReceiver alarmReceiver = null; private AlarmReceiver alarmReceiver = null;
final ScreenActionReceiver screenactionreceiver = new ScreenActionReceiver(); private ScreenActionReceiver screenactionreceiver = null;
} }

@ -15,7 +15,6 @@ public class ScreenActionReceiver extends BroadcastReceiver {
@Override @Override
public void onReceive(Context context, Intent intent) { public void onReceive(Context context, Intent intent) {
//LOG //LOG
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
sb.append("Action: " + intent.getAction() + "\n"); sb.append("Action: " + intent.getAction() + "\n");
@ -34,8 +33,6 @@ public class ScreenActionReceiver extends BroadcastReceiver {
//Run the locker //Run the locker
context.startService(new Intent(context, FloatingWindow.class)); context.startService(new Intent(context, FloatingWindow.class));
} }
else if(Intent.ACTION_SCREEN_OFF.equals(action)) else if(Intent.ACTION_SCREEN_OFF.equals(action))

Loading…
Cancel
Save